feat: bootstrap auto virtual tryon admin frontend

This commit is contained in:
afei A
2026-03-27 23:38:50 +08:00
commit 98c6b741d6
119 changed files with 19046 additions and 0 deletions

View File

@@ -0,0 +1,96 @@
import {
Card,
CardContent,
CardDescription,
CardEyebrow,
CardHeader,
CardTitle,
} from "@/components/ui/card";
import type { ResourcePickerOption } from "@/features/orders/resource-picker-options";
type ResourcePickerCardProps = {
description: string;
disabled?: boolean;
isLoading?: boolean;
items: ResourcePickerOption[];
label: string;
title: string;
value: string;
onChange: (value: string) => void;
};
function joinClasses(...values: Array<string | false | null | undefined>) {
return values.filter(Boolean).join(" ");
}
export function ResourcePickerCard({
description,
disabled = false,
isLoading = false,
items,
label,
title,
value,
onChange,
}: ResourcePickerCardProps) {
const selectedItem = items.find((item) => item.id === value) ?? null;
return (
<Card>
<CardHeader>
<CardEyebrow>Mock backed selector</CardEyebrow>
<CardTitle>{title}</CardTitle>
<CardDescription>{description}</CardDescription>
</CardHeader>
<CardContent className="space-y-4">
<label className="flex flex-col gap-2 text-sm text-[var(--ink-strong)]">
<span className="font-medium">{label}</span>
<select
aria-label={label}
className={joinClasses(
"min-h-12 rounded-[18px] border border-[var(--border-strong)] bg-[var(--surface-muted)] px-4 text-sm text-[var(--ink-strong)]",
"focus:outline-none focus:ring-2 focus:ring-[var(--accent-ring)]",
)}
disabled={disabled || isLoading}
value={value}
onChange={(event) => onChange(event.target.value)}
>
<option value="">
{isLoading ? "正在加载占位资源..." : "请选择一个资源"}
</option>
{items.map((item) => (
<option key={item.id} value={item.id}>
{item.name}
</option>
))}
</select>
</label>
{selectedItem ? (
<div className="rounded-[20px] border border-[var(--border-soft)] bg-[var(--surface-muted)] p-4">
<div className="flex flex-wrap items-start justify-between gap-3">
<div className="space-y-1">
<p className="text-sm font-semibold text-[var(--ink-strong)]">
{selectedItem.name}
</p>
<p className="text-sm leading-6 text-[var(--ink-muted)]">
{selectedItem.description}
</p>
</div>
<span className="rounded-full bg-[var(--accent-soft)] px-3 py-1 font-[var(--font-mono)] text-[11px] uppercase tracking-[0.18em] text-[var(--accent-ink)]">
{selectedItem.isMock ? "mock" : "live"}
</span>
</div>
<p className="mt-3 font-[var(--font-mono)] text-xs text-[var(--ink-faint)]">
{selectedItem.previewUri}
</p>
</div>
) : (
<p className="text-sm leading-6 text-[var(--ink-muted)]">
ID
</p>
)}
</CardContent>
</Card>
);
}