63 lines
2.5 KiB
TypeScript
63 lines
2.5 KiB
TypeScript
"use client";
|
|
|
|
import { useState, useTransition } from "react";
|
|
import { UserPlus } from "lucide-react";
|
|
import { Button } from "@/components/ui/button";
|
|
import { generateFamilyInvite } from "./actions";
|
|
|
|
// xuchao: 家庭管理——展示成员列表,生成一次性邀请码让其他家长注册加入
|
|
export function FamilyManage({
|
|
familyName,
|
|
parents,
|
|
kids,
|
|
}: {
|
|
familyName: string;
|
|
parents: { id: number; name: string }[];
|
|
kids: { id: number; name: string }[];
|
|
}) {
|
|
const [invite, setInvite] = useState<{ code?: string; error?: string } | null>(null);
|
|
const [pending, startTransition] = useTransition();
|
|
|
|
const gen = () => {
|
|
setInvite(null);
|
|
startTransition(async () => {
|
|
setInvite(await generateFamilyInvite());
|
|
});
|
|
};
|
|
|
|
return (
|
|
<div className="space-y-3">
|
|
<p className="text-sm text-slate-700">
|
|
<span className="font-semibold">{familyName}</span> · {parents.length} 位家长 · {kids.length} 个孩子
|
|
</p>
|
|
<div className="space-y-1.5">
|
|
{parents.map((p) => (
|
|
<div key={p.id} className="flex items-center justify-between rounded-lg border border-slate-200 bg-white px-3 py-2 text-sm">
|
|
<span className="font-medium text-slate-800">{p.name}</span>
|
|
<span className="rounded-full bg-indigo-100 px-2 py-0.5 text-xs font-medium text-indigo-700">家长</span>
|
|
</div>
|
|
))}
|
|
{kids.map((k) => (
|
|
<div key={k.id} className="flex items-center justify-between rounded-lg border border-slate-200 bg-white px-3 py-2 text-sm">
|
|
<span className="font-medium text-slate-800">{k.name}</span>
|
|
<span className="rounded-full bg-slate-100 px-2 py-0.5 text-xs font-medium text-slate-500">孩子</span>
|
|
</div>
|
|
))}
|
|
</div>
|
|
<div className="flex flex-wrap items-center gap-3">
|
|
<Button size="sm" variant="secondary" disabled={pending} onClick={gen}>
|
|
<UserPlus className="size-4" /> {pending ? "生成中…" : "生成邀请码"}
|
|
</Button>
|
|
{invite?.error && <p className="text-sm font-medium text-destructive">{invite.error}</p>}
|
|
{invite?.code && (
|
|
<p className="text-sm text-slate-700">
|
|
邀请码{" "}
|
|
<span className="font-mono text-lg font-bold tracking-widest text-indigo-600">{invite.code}</span>
|
|
<span className="ml-1 text-xs text-muted-foreground">15 分钟有效,一次性</span>
|
|
</p>
|
|
)}
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|