87 lines
4.7 KiB
TypeScript
87 lines
4.7 KiB
TypeScript
import Link from "next/link";
|
||
import { ChevronRight, PenLine, ScanLine } from "lucide-react";
|
||
|
||
import { PanelShell } from "@/components/panel-shell";
|
||
import { getCaregiverOverview } from "@/lib/caregiver-panel";
|
||
import { formatDateTime, getDeviceName, getMessageHref, truncateText } from "@/lib/panel-format";
|
||
import { requireCaregiverSession } from "@/lib/page-auth";
|
||
import { getCaregiverDisplayName } from "@/lib/session";
|
||
|
||
export const dynamic = "force-dynamic";
|
||
|
||
function greeting() {
|
||
const hour = new Date().getHours();
|
||
if (hour < 11) return "早上好";
|
||
if (hour < 14) return "中午好";
|
||
if (hour < 18) return "下午好";
|
||
return "晚上好";
|
||
}
|
||
|
||
export default async function Home() {
|
||
const caregiver = await requireCaregiverSession("/");
|
||
const { dashboard, recentIncomingMessages } = await getCaregiverOverview(caregiver.id);
|
||
const name = getCaregiverDisplayName(dashboard.caregiver);
|
||
const unreadIn = dashboard.devices.reduce((n, d) => n + d.elderUnreadCount, 0);
|
||
const unreadOut = dashboard.devices.reduce((n, d) => n + d.familyUnreadCount, 0);
|
||
const conversations = dashboard.devices.reduce((n, d) => n + d.elderDevice._count.conversationTurns, 0);
|
||
const date = new Intl.DateTimeFormat("zh-CN", { month: "numeric", day: "numeric", weekday: "short" }).format(new Date());
|
||
|
||
return (
|
||
<PanelShell
|
||
currentPath="/"
|
||
title={`${greeting()},${name}`}
|
||
description={`${date} · ${dashboard.devices.length} 台设备已连接`}
|
||
caregiverLabel={name}
|
||
unreadCount={unreadIn}
|
||
>
|
||
<section className="card">
|
||
{dashboard.devices.length ? dashboard.devices.map((binding) => (
|
||
<Link key={binding.id} href={`/devices/${binding.elderDevice.deviceUuid}`} className="list-row" style={{ alignItems: "center" }}>
|
||
<span className={`dot ${binding.elderDevice.lastSeenAt ? "online" : "offline"}`} style={{ marginTop: 0 }} />
|
||
<span className="row-title" style={{ flex: 1 }}>{getDeviceName(binding.alias, binding.elderDevice.displayName)}</span>
|
||
<span className="row-meta" style={{ marginTop: 0 }}>{binding.elderDevice.lastSeenAt ? "在线" : "未连接"}</span>
|
||
<ChevronRight size={14} color="var(--muted-light)" />
|
||
</Link>
|
||
)) : <div className="empty">还没有连接设备,扫码即可开始守护。</div>}
|
||
</section>
|
||
|
||
<section className="stats" style={{ gridTemplateColumns: "repeat(4,1fr)" }}>
|
||
<Link href="/messages" className="stat accent"><strong>{unreadIn}</strong><span>新留言</span></Link>
|
||
<Link href="/messages" className="stat"><strong>{unreadOut}</strong><span>待长辈听</span></Link>
|
||
<Link href="/activity" className="stat"><strong>{conversations}</strong><span>陪伴对话</span></Link>
|
||
<Link href="/devices" className="stat"><strong>{dashboard.devices.length}</strong><span>设备</span></Link>
|
||
</section>
|
||
|
||
<div className="button-row">
|
||
<Link href={dashboard.devices[0] ? `/devices/${dashboard.devices[0].elderDevice.deviceUuid}` : "/devices"} className="btn primary" style={{ flex: 1 }}>
|
||
<PenLine size={15} />给长辈留言
|
||
</Link>
|
||
<Link href="/scan" className="btn" style={{ flex: 1 }}><ScanLine size={15} />扫码绑定</Link>
|
||
</div>
|
||
|
||
<section>
|
||
<div className="section-title"><h2>长辈的新留言</h2><Link href="/messages">全部</Link></div>
|
||
<div className="card">
|
||
{recentIncomingMessages.length ? recentIncomingMessages.slice(0, 3).map((message) => (
|
||
<Link key={message.id} href={getMessageHref(message.publicId)} className="list-row">
|
||
<span className="dot" />
|
||
<span className="row-main">
|
||
<span className="row-title">{truncateText(message.content, 62)}</span>
|
||
<span className="row-meta">{message.importance !== "NORMAL" ? <span className="tag">重要</span> : null}{getDeviceName(message.elderDevice.displayName)} · {formatDateTime(message.createdAt)}</span>
|
||
</span>
|
||
</Link>
|
||
)) : <div className="empty">暂时还没有收到新留言。</div>}
|
||
</div>
|
||
</section>
|
||
|
||
<section>
|
||
<div className="section-title"><h2>陪伴动态</h2><Link href="/activity">全部</Link></div>
|
||
<div className="card">
|
||
<div className="timeline-item"><div className="timeline-top">设备连接情况<span className="timeline-time">现在</span></div><p className="timeline-body">{dashboard.devices.length} 台长辈设备已加入家人守护。</p></div>
|
||
<div className="timeline-item"><div className="timeline-top">陪伴对话<span className="timeline-time">累计</span></div><p className="timeline-body">数字人已完成 {conversations} 轮陪伴对话。</p></div>
|
||
</div>
|
||
</section>
|
||
</PanelShell>
|
||
);
|
||
}
|