- 家长手机号登录 + 孩子设备一次性激活(长期会话) - 周模板自动生成每日任务快照,支持拍照凭证直传对象存储 - 连击计算(空白日自动达成)、家长补卡带标记 - 家长端三标签:今日概览 / 任务模板 / 设备管理 - Docker 独立输出,经 Traefik 接入 jump.hn12301.net Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
63 lines
2.2 KiB
TypeScript
63 lines
2.2 KiB
TypeScript
import { Flame } from "lucide-react";
|
|
import { redirect } from "next/navigation";
|
|
import { todayStr } from "@/lib/dates";
|
|
import { getSessionUser } from "@/lib/auth";
|
|
import { streakOf } from "@/lib/streak";
|
|
import { dayTasks } from "@/lib/tasks";
|
|
import { TaskCard } from "./task-card";
|
|
|
|
export default async function KidPage() {
|
|
const user = await getSessionUser();
|
|
if (!user) redirect("/join");
|
|
if (user.role !== "child") redirect("/parent");
|
|
|
|
const today = todayStr();
|
|
const [tasks, streak] = await Promise.all([
|
|
dayTasks(user.id, today),
|
|
streakOf(user.id),
|
|
]);
|
|
const doneCount = tasks.filter((t) => t.status === "done").length;
|
|
const allDone = tasks.length > 0 && doneCount === tasks.length;
|
|
|
|
return (
|
|
<main className="mx-auto max-w-lg space-y-5 p-4 pb-10">
|
|
<header className="flex items-center justify-between">
|
|
<div>
|
|
<h1 className="text-2xl font-bold">你好,{user.displayName}</h1>
|
|
<p className="text-sm text-muted-foreground">{today}</p>
|
|
</div>
|
|
<div className="flex items-center gap-1 rounded-full bg-orange-100 px-4 py-2 text-orange-600">
|
|
<Flame className="size-6" fill="currentColor" />
|
|
<span className="text-xl font-bold">{streak}</span>
|
|
<span className="text-sm">天</span>
|
|
</div>
|
|
</header>
|
|
|
|
{tasks.length === 0 ? (
|
|
<div className="rounded-2xl bg-muted p-8 text-center">
|
|
<p className="text-2xl">🎉</p>
|
|
<p className="mt-2 text-lg font-medium">今天没有任务</p>
|
|
<p className="mt-1 text-sm text-muted-foreground">连击自动保持,去玩吧!</p>
|
|
</div>
|
|
) : (
|
|
<>
|
|
<p className="text-sm text-muted-foreground">
|
|
已完成 {doneCount} / {tasks.length} 项
|
|
</p>
|
|
<div className="space-y-3">
|
|
{tasks.map((t) => (
|
|
<TaskCard key={t.id} task={t} />
|
|
))}
|
|
</div>
|
|
{allDone && (
|
|
<div className="rounded-2xl bg-green-100 p-6 text-center">
|
|
<p className="text-2xl">💪</p>
|
|
<p className="mt-2 text-lg font-bold text-green-700">今天全部完成,太棒了!</p>
|
|
</div>
|
|
)}
|
|
</>
|
|
)}
|
|
</main>
|
|
);
|
|
}
|