w-funnel/src/components/admin/builder/templates/FormScreenConfig.tsx
2025-09-25 18:04:52 +02:00

195 lines
6.8 KiB
TypeScript

"use client";
import { Button } from "@/components/ui/button";
import { TextInput } from "@/components/ui/TextInput/TextInput";
import type { FormScreenDefinition, FormFieldDefinition } from "@/lib/funnel/types";
import type { BuilderScreen } from "@/lib/admin/builder/types";
interface FormScreenConfigProps {
screen: BuilderScreen & { template: "form" };
onUpdate: (updates: Partial<FormScreenDefinition>) => void;
}
export function FormScreenConfig({ screen, onUpdate }: FormScreenConfigProps) {
const formScreen = screen as FormScreenDefinition & { position: any };
const updateField = (index: number, updates: Partial<FormFieldDefinition>) => {
const newFields = [...(formScreen.fields || [])];
newFields[index] = { ...newFields[index], ...updates };
onUpdate({ fields: newFields });
};
const addField = () => {
const newField: FormFieldDefinition = {
id: `field_${Date.now()}`,
label: "New Field",
placeholder: "Enter value",
type: "text",
required: true,
};
onUpdate({
fields: [...(formScreen.fields || []), newField]
});
};
const removeField = (index: number) => {
const newFields = formScreen.fields?.filter((_, i) => i !== index) || [];
onUpdate({ fields: newFields });
};
return (
<div className="space-y-4">
{/* Title Configuration */}
<div className="space-y-2">
<label className="text-sm font-medium">Title</label>
<TextInput
placeholder="Enter your details"
value={formScreen.title?.text || ""}
onChange={(value) => onUpdate({
title: {
...formScreen.title,
text: value,
font: formScreen.title?.font || "manrope",
weight: formScreen.title?.weight || "bold",
}
})}
/>
</div>
{/* Subtitle Configuration */}
<div className="space-y-2">
<label className="text-sm font-medium">Subtitle (Optional)</label>
<TextInput
placeholder="Please fill in all fields"
value={formScreen.subtitle?.text || ""}
onChange={(value) => onUpdate({
subtitle: value ? {
text: value,
font: formScreen.subtitle?.font || "inter",
weight: formScreen.subtitle?.weight || "medium",
color: formScreen.subtitle?.color || "muted",
} : undefined
})}
/>
</div>
{/* Form Fields Configuration */}
<div className="space-y-3">
<div className="flex items-center justify-between">
<h3 className="text-sm font-semibold">Form Fields</h3>
<Button
size="sm"
onClick={addField}
className="h-7 px-3 text-xs"
>
Add Field
</Button>
</div>
{formScreen.fields?.map((field, index) => (
<div key={index} className="rounded border border-border p-3 space-y-2">
<div className="flex items-center justify-between">
<span className="text-sm font-medium">Field {index + 1}</span>
<Button
size="sm"
variant="ghost"
onClick={() => removeField(index)}
className="h-6 px-2 text-xs text-red-600 hover:text-red-700"
>
Remove
</Button>
</div>
<div className="grid grid-cols-2 gap-2">
<div className="space-y-1">
<label className="text-xs font-medium text-muted-foreground">Field ID</label>
<TextInput
placeholder="field_id"
value={field.id}
onChange={(value) => updateField(index, { id: value })}
/>
</div>
<div className="space-y-1">
<label className="text-xs font-medium text-muted-foreground">Type</label>
<select
className="w-full rounded border border-border bg-background px-2 py-1 text-sm"
value={field.type}
onChange={(e) => updateField(index, { type: e.target.value as any })}
>
<option value="text">Text</option>
<option value="email">Email</option>
<option value="tel">Phone</option>
<option value="url">URL</option>
</select>
</div>
</div>
<div className="space-y-1">
<label className="text-xs font-medium text-muted-foreground">Label</label>
<TextInput
placeholder="Field Label"
value={field.label}
onChange={(value) => updateField(index, { label: value })}
/>
</div>
<div className="space-y-1">
<label className="text-xs font-medium text-muted-foreground">Placeholder</label>
<TextInput
placeholder="Enter placeholder"
value={field.placeholder || ""}
onChange={(value) => updateField(index, { placeholder: value })}
/>
</div>
<div className="flex items-center gap-4">
<label className="flex items-center gap-2 text-sm">
<input
type="checkbox"
checked={field.required || false}
onChange={(e) => updateField(index, { required: e.target.checked })}
/>
Required
</label>
{field.maxLength && (
<div className="flex items-center gap-2">
<label className="text-xs text-muted-foreground">Max Length:</label>
<input
type="number"
className="w-16 rounded border border-border bg-background px-2 py-1 text-xs"
value={field.maxLength}
onChange={(e) => updateField(index, { maxLength: parseInt(e.target.value) || undefined })}
/>
</div>
)}
</div>
</div>
))}
{(!formScreen.fields || formScreen.fields.length === 0) && (
<div className="text-center py-4 text-sm text-muted-foreground">
No fields added yet. Click "Add Field" to get started.
</div>
)}
</div>
{/* Bottom Action Button */}
<div className="space-y-2">
<label className="text-sm font-medium">Button Text</label>
<TextInput
placeholder="Continue"
value={formScreen.bottomActionButton?.text || ""}
onChange={(value) => onUpdate({
bottomActionButton: {
text: value || "Continue",
}
})}
/>
</div>
</div>
);
}