ai-chatbot/app/(admin)/settings/_components/local-ai-section-shell.tsx
Your Name 1365a22d5b refactor: modularize admin settings local ai sections
Also removes the legacy home mode selector from the settings form because the affected JSX lives inside the same settings client refactor.
2026-05-26 19:31:57 +08:00

122 lines
2.8 KiB
TypeScript

"use client";
import { ArrowDown, ArrowUp } from "lucide-react";
import type { ReactNode } from "react";
import { Button } from "@/components/ui/button";
import {
Card,
CardContent,
CardDescription,
CardHeader,
CardTitle,
} from "@/components/ui/card";
import { cn } from "@/lib/utils";
import type { SettingStatusTone } from "../_lib/types";
import { SettingStatusBadge } from "./setting-status-badge";
export function LocalAiGroupHeading({
eyebrow,
title,
description,
}: {
eyebrow: string;
title: string;
description: string;
}) {
return (
<div className="rounded-lg border bg-muted/20 px-4 py-3">
<div className="font-semibold text-[11px] text-muted-foreground uppercase tracking-[0.16em]">
{eyebrow}
</div>
<div className="mt-1 flex flex-col gap-1 md:flex-row md:items-end md:justify-between">
<h3 className="font-semibold text-base text-foreground">{title}</h3>
<p className="max-w-3xl text-muted-foreground text-sm">{description}</p>
</div>
</div>
);
}
export function LocalAiSectionSummary({
items,
}: {
items: Array<{
label: string;
tone?: SettingStatusTone;
}>;
}) {
return (
<div className="flex flex-wrap gap-2 pt-1">
{items.map((item) => (
<SettingStatusBadge key={item.label} tone={item.tone || "neutral"}>
{item.label}
</SettingStatusBadge>
))}
</div>
);
}
export function LocalAiSectionToggleButton({
expanded,
onClick,
}: {
expanded: boolean;
onClick: () => void;
}) {
return (
<Button
aria-expanded={expanded}
className="h-8 shrink-0 gap-1.5 rounded-md px-2.5 text-xs"
onClick={onClick}
size="sm"
type="button"
variant="outline"
>
{expanded ? (
<ArrowUp className="h-3.5 w-3.5" />
) : (
<ArrowDown className="h-3.5 w-3.5" />
)}
{expanded ? "收起配置" : "展开配置"}
</Button>
);
}
export function LocalAiSectionShell({
id,
title,
description,
summary,
expanded,
onToggle,
children,
}: {
id: string;
title: ReactNode;
description: ReactNode;
summary?: ReactNode;
expanded: boolean;
onToggle: () => void;
children: ReactNode;
}) {
return (
<Card id={id}>
<CardHeader className="flex flex-col gap-4 space-y-0 md:flex-row md:items-start md:justify-between">
<div className="space-y-1.5">
<CardTitle className="text-xl">{title}</CardTitle>
<CardDescription>{description}</CardDescription>
{summary}
</div>
<LocalAiSectionToggleButton expanded={expanded} onClick={onToggle} />
</CardHeader>
<CardContent
className={cn(
"local-ai-config-card-content space-y-6 pt-6",
!expanded && "hidden"
)}
>
{children}
</CardContent>
</Card>
);
}