haixunMaster/components/product-context-form.tsx

116 lines
4.1 KiB
TypeScript
Raw Normal View History

2026-06-21 12:50:31 +00:00
"use client";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Textarea } from "@/components/ui/textarea";
import {
CTA_TYPE_OPTIONS,
parseProductContext,
serializeProductContext,
type CtaType,
type ProductContextFields,
} from "@/lib/types/product-context";
interface ProductContextFormProps {
value: string;
onChange: (serialized: string) => void;
compact?: boolean;
/** 產品層級表單:隱藏品牌欄位(品牌由上層品牌卡管理) */
productOnly?: boolean;
}
export function ProductContextForm({
value,
onChange,
compact = false,
productOnly = false,
}: ProductContextFormProps) {
const fields = parseProductContext(value);
function update(patch: Partial<ProductContextFields>) {
onChange(serializeProductContext({ ...fields, ...patch }));
}
return (
<div className={compact ? "space-y-3" : "space-y-4"}>
{!productOnly ? (
<div className="grid gap-3 sm:grid-cols-2">
<div className="space-y-1.5">
<Label className="text-xs"></Label>
<Input
value={fields.brand}
onChange={(e) => update({ brand: e.target.value })}
placeholder="例kahu"
/>
</div>
<div className="space-y-1.5">
<Label className="text-xs"></Label>
<Input
value={fields.product}
onChange={(e) => update({ product: e.target.value })}
placeholder="例:寵物洗毛精"
/>
</div>
</div>
) : (
<div className="space-y-1.5">
<Label className="text-xs"></Label>
<Input
value={fields.product}
onChange={(e) => update({ product: e.target.value })}
placeholder="例:溫和洗毛精"
/>
</div>
)}
<div className="space-y-1.5">
<Label className="text-xs"></Label>
<Textarea
value={fields.features}
onChange={(e) => update({ features: e.target.value })}
rows={compact ? 2 : 3}
placeholder="例:溫和無香料、適合皮膚敏感的狗,在家洗澡好沖洗不殘留"
/>
</div>
<div className="space-y-1.5">
<Label className="text-xs"></Label>
<Textarea
value={fields.placementTone ?? ""}
onChange={(e) => update({ placementTone: e.target.value })}
rows={2}
placeholder="例:像朋友分享經驗,先回應對方困擾再順帶提到;不要第一句就講品牌"
/>
</div>
<div className="grid gap-3 sm:grid-cols-2">
<div className="space-y-1.5">
<Label className="text-xs"> CTA </Label>
<select
value={(fields.ctaType ?? "none") as CtaType}
onChange={(e) => update({ ctaType: e.target.value as CtaType })}
className="flex h-9 w-full rounded-md border border-input bg-background px-3 py-1 text-sm shadow-sm focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring"
>
{CTA_TYPE_OPTIONS.map((opt) => (
<option key={opt.value} value={opt.value}>
{opt.label}
</option>
))}
</select>
</div>
{fields.ctaType === "link" && (
<div className="space-y-1.5">
<Label className="text-xs">CTA </Label>
<Input
value={fields.ctaUrl ?? ""}
onChange={(e) => update({ ctaUrl: e.target.value })}
placeholder="https://… 有填才會自然帶進留言,沒填就不帶"
/>
</div>
)}
</div>
{fields.ctaType === "link" && (
<p className="text-[11px] text-muted-foreground">
AI 稿
</p>
)}
</div>
);
}