import { Menu } from "lucide-react";
import { ModelSelector } from "@/components/chat/model-selector";
import { Button } from "@/components/ui/button";
import type { ChatModel } from "@/lib/chat/models";
import type { ModelId } from "@/lib/chat/types";
import type { QuotaState } from "@/hooks/use-chat";
type ChatHeaderProps = {
models: ChatModel[];
modelId: ModelId;
onModelChange: (id: ModelId) => void;
onOpenMenu: () => void;
quota: QuotaState;
};
export function ChatHeader({
modelId,
models,
onModelChange,
onOpenMenu,
quota,
}: ChatHeaderProps) {
return (
<header className="flex h-14 shrink-0 items-center gap-2 border-b px-3 md:px-5">
<Button
aria-label="Открыть меню"
className="md:hidden"
onClick={onOpenMenu}
size="icon"
type="button"
variant="ghost"
>
<Menu aria-hidden="true" />
</Button>
<ModelSelector models={models} modelId={modelId} onChange={onModelChange} />
<div aria-live="polite" className="ml-auto text-right text-xs text-muted-foreground">
<p>{quotaLabel(quota)}</p>
{quota.status === "ready" && quota.snapshot.resetsAt ? (
<p>
Сброс:{" "}
<time dateTime={quota.snapshot.resetsAt}>
{formatReset(quota.snapshot.resetsAt)}
</time>
</p>
) : null}
</div>
</header>
);
}
function quotaLabel(quota: QuotaState): string {
if (quota.status === "loading") return "Баланс…";
if (quota.status === "unavailable") return "Баланс недоступен";
if (quota.snapshot.unlimited) return "Без лимита";
return `${new Intl.NumberFormat("ru-RU").format(quota.snapshot.availableTokens ?? 0)} токенов`;
}
function formatReset(value: string): string {
return `${new Intl.DateTimeFormat("ru-RU", {
dateStyle: "short",
timeStyle: "short",
timeZone: "UTC",
}).format(new Date(value))} UTC`;
}