Phone formatting works, start card moved, registration styling changed

This commit is contained in:
2026-02-01 15:16:12 -06:00
parent 235156a9ee
commit af27190e29
3 changed files with 202 additions and 182 deletions

View File

@@ -51,6 +51,7 @@ import {
Zap,
Copy,
X,
Grip
} from 'lucide-react';
// Field type icons
@@ -319,11 +320,11 @@ const AdminRegistrationBuilder = () => {
steps: prev.steps.map((s) =>
s.id === selectedStep
? {
...s,
sections: s.sections
.filter((sec) => sec.id !== sectionId)
.map((sec, idx) => ({ ...sec, order: idx + 1 })),
}
...s,
sections: s.sections
.filter((sec) => sec.id !== sectionId)
.map((sec, idx) => ({ ...sec, order: idx + 1 })),
}
: s
),
}));
@@ -361,13 +362,13 @@ const AdminRegistrationBuilder = () => {
steps: prev.steps.map((s) =>
s.id === selectedStep
? {
...s,
sections: s.sections.map((sec) =>
sec.id === selectedSection
? { ...sec, fields: [...(sec.fields || []), newField] }
: sec
),
}
...s,
sections: s.sections.map((sec) =>
sec.id === selectedSection
? { ...sec, fields: [...(sec.fields || []), newField] }
: sec
),
}
: s
),
}));
@@ -395,18 +396,18 @@ const AdminRegistrationBuilder = () => {
steps: prev.steps.map((s) =>
s.id === selectedStep
? {
...s,
sections: s.sections.map((sec) =>
sec.id === selectedSection
? {
...sec,
fields: sec.fields
.filter((f) => f.id !== fieldId)
.map((f, idx) => ({ ...f, order: idx + 1 })),
}
: sec
),
}
...s,
sections: s.sections.map((sec) =>
sec.id === selectedSection
? {
...sec,
fields: sec.fields
.filter((f) => f.id !== fieldId)
.map((f, idx) => ({ ...f, order: idx + 1 })),
}
: sec
),
}
: s
),
}));
@@ -423,18 +424,18 @@ const AdminRegistrationBuilder = () => {
steps: prev.steps.map((s) =>
s.id === selectedStep
? {
...s,
sections: s.sections.map((sec) =>
sec.id === selectedSection
? {
...sec,
fields: sec.fields.map((f) =>
f.id === fieldId ? { ...f, ...updates } : f
),
}
: sec
),
}
...s,
sections: s.sections.map((sec) =>
sec.id === selectedSection
? {
...sec,
fields: sec.fields.map((f) =>
f.id === fieldId ? { ...f, ...updates } : f
),
}
: sec
),
}
: s
),
}));
@@ -492,132 +493,137 @@ const AdminRegistrationBuilder = () => {
)}
{/* Main Builder Layout */}
<div className="grid grid-cols-1 lg:grid-cols-12 gap-6">
{/* Left Sidebar - Steps & Sections */}
<div className="lg:col-span-3">
<Card className="p-4">
<div className="flex justify-between items-center mb-4">
<h2 className="text-lg font-semibold">Steps</h2>
<Button size="sm" variant="ghost" onClick={() => setAddStepDialogOpen(true)}>
<Plus className="h-4 w-4" />
</Button>
</div>
{/* Left Sidebar - Steps & Sections */}
<div className="lg:col-span-3">
<Card className="p-4">
<div className="flex justify-between items-center mb-4">
<h2 className="text-lg font-semibold">Steps</h2>
<Button size="sm" variant="ghost" onClick={() => setAddStepDialogOpen(true)}>
<Plus className="h-4 w-4" />
</Button>
</div>
<div className="space-y-2">
{sortedSteps.map((step, index) => (
<div
key={step.id}
className={`p-3 rounded-lg border cursor-pointer transition-colors ${
selectedStep === step.id
<div className="flex space-y-2">
{sortedSteps.map((step, index) => (
<div
key={step.id}
className={`p-3 rounded-t-lg border cursor-pointer transition-colors ${selectedStep === step.id
? ' bg-brand-lavender/10 border-b-4 border-b-brand-dark-lavender'
: ''
}`}
onClick={() => {
setSelectedStep(step.id);
setSelectedSection(null);
setSelectedField(null);
}}
>
<div className="flex items-center justify-between">
<div className="flex items-center gap-2">
<div className="font-medium">Step: </div>
<span className="font-medium text-sm">{step.title}</span>
</div>
{/* Mod Buttons */}
<div className="flex items-center gap-1">
{/* <Button
size="icon"
variant="ghost"
className="h-6 w-6"
onClick={(e) => {
e.stopPropagation();
handleMoveStep(step.id, 'up');
}}
disabled={index === 0}
>
<ChevronUp className="h-3 w-3" />
</Button>
<Button
size="icon"
variant="ghost"
className="h-6 w-6"
onClick={(e) => {
e.stopPropagation();
handleMoveStep(step.id, 'down');
}}
disabled={index === sortedSteps.length - 1}
>
<ChevronDown className="h-3 w-3" />
</Button> */}
<Button
size="icon"
variant="ghost"
className="h-6 w-6 text-red-500 hover:text-white ml-2"
onClick={(e) => {
e.stopPropagation();
handleDeleteStep(step.id);
}}
>
<Trash2 className="size-3" />
</Button>
</div>
</div>
</div>
))}
</div>
{/* Sections for selected step */}
{currentStep && (
<>
<div className="flex justify-between items-center mt-6 mb-4">
<h2 className="text-lg font-semibold">Sections</h2>
<Button size="sm" variant="ghost" onClick={() => setAddSectionDialogOpen(true)}>
<Plus className="h-4 w-4" />
</Button>
</div>
<div className="space-y-2">
{sortedSections.map((section) => (
<div
key={section.id}
className={`p-3 rounded-lg border cursor-pointer transition-colors ${selectedSection === section.id
? 'border-brand-purple bg-brand-lavender/10'
: 'border-gray-200 hover:border-gray-300'
}`}
onClick={() => {
setSelectedStep(step.id);
setSelectedSection(null);
setSelectedField(null);
}}
>
<div className="flex items-center justify-between">
<div className="flex items-center gap-2">
<GripVertical className="h-4 w-4 text-gray-400" />
<span className="font-medium text-sm">{step.title}</span>
</div>
<div className="flex items-center gap-1">
<Button
size="icon"
variant="ghost"
className="h-6 w-6"
onClick={(e) => {
e.stopPropagation();
handleMoveStep(step.id, 'up');
}}
disabled={index === 0}
>
<ChevronUp className="h-3 w-3" />
</Button>
<Button
size="icon"
variant="ghost"
className="h-6 w-6"
onClick={(e) => {
e.stopPropagation();
handleMoveStep(step.id, 'down');
}}
disabled={index === sortedSteps.length - 1}
>
<ChevronDown className="h-3 w-3" />
</Button>
}`}
onClick={() => {
setSelectedSection(section.id);
setSelectedField(null);
}}
>
<div className="flex items-center justify-between">
<span className="text-sm">{section.title}</span>
<Button
size="icon"
variant="ghost"
className="h-6 w-6 text-red-500 hover:text-red-700"
onClick={(e) => {
e.stopPropagation();
handleDeleteStep(step.id);
handleDeleteSection(section.id);
}}
>
<Trash2 className="h-3 w-3" />
</Button>
</div>
</div>
</div>
))}
</div>
{/* Sections for selected step */}
{currentStep && (
<>
<div className="flex justify-between items-center mt-6 mb-4">
<h2 className="text-lg font-semibold">Sections</h2>
<Button size="sm" variant="ghost" onClick={() => setAddSectionDialogOpen(true)}>
<Plus className="h-4 w-4" />
</Button>
</div>
<div className="space-y-2">
{sortedSections.map((section) => (
<div
key={section.id}
className={`p-3 rounded-lg border cursor-pointer transition-colors ${
selectedSection === section.id
? 'border-brand-purple bg-brand-lavender/10'
: 'border-gray-200 hover:border-gray-300'
}`}
onClick={() => {
setSelectedSection(section.id);
setSelectedField(null);
}}
>
<div className="flex items-center justify-between">
<span className="text-sm">{section.title}</span>
<Button
size="icon"
variant="ghost"
className="h-6 w-6 text-red-500 hover:text-red-700"
onClick={(e) => {
e.stopPropagation();
handleDeleteSection(section.id);
}}
>
<Trash2 className="h-3 w-3" />
</Button>
</div>
</div>
))}
</div>
</>
)}
</Card>
</div>
))}
</div>
</>
)}
</Card>
</div>
<div className="grid grid-cols-1 lg:grid-cols-12 gap-6">
{/* Center - Form Canvas */}
<div className="lg:col-span-6">
<div className="lg:col-span-9">
<Card className="p-6">
<div className="flex justify-between items-center mb-6">
<h2 className="text-xl font-semibold">
{currentStep?.title || 'Select a step'}
</h2>
<div className='relative -mx-11 -my-2 flex gap-2 items-center'>
<Grip className="size-10 text-gray-400 py-2 bg-background" />
<h2 className="text-xl font-semibold">
{currentStep?.title || 'Select a step'}
</h2>
</div>
{selectedSection && (
<Button size="sm" onClick={() => setAddFieldDialogOpen(true)}>
<Plus className="h-4 w-4 mr-2" />
@@ -637,11 +643,10 @@ const AdminRegistrationBuilder = () => {
return (
<div
key={section.id}
className={`mb-6 p-4 rounded-lg border-2 ${
selectedSection === section.id
? 'border-brand-purple'
: 'border-dashed border-gray-200'
}`}
className={`mb-6 p-4 rounded-lg border-2 ${selectedSection === section.id
? 'border-brand-purple'
: 'border-dashed border-gray-200'
}`}
onClick={() => setSelectedSection(section.id)}
>
<h3 className="text-lg font-medium mb-4">{section.title}</h3>
@@ -656,11 +661,10 @@ const AdminRegistrationBuilder = () => {
return (
<div
key={field.id}
className={`p-3 rounded-lg border cursor-pointer transition-all ${
selectedField === field.id
? 'border-brand-purple bg-brand-lavender/5 ring-2 ring-brand-purple/20'
: 'border-gray-200 hover:border-gray-300'
} ${field.is_fixed ? 'bg-gray-50' : ''}`}
className={`p-3 rounded-lg border cursor-pointer transition-all ${selectedField === field.id
? 'border-brand-purple bg-brand-lavender/5 ring-2 ring-brand-purple/20'
: 'border-gray-200 hover:border-gray-300'
} ${field.is_fixed ? 'bg-gray-50' : ''}`}
onClick={(e) => {
e.stopPropagation();
setSelectedSection(section.id);
@@ -719,23 +723,7 @@ const AdminRegistrationBuilder = () => {
)}
</Card>
{/* Conditional Rules */}
<Card className="p-6 mt-6">
<div className="flex justify-between items-center mb-4">
<div className="flex items-center gap-2">
<Zap className="h-5 w-5 text-yellow-500" />
<h2 className="text-lg font-semibold">Conditional Rules</h2>
</div>
<Button size="sm" variant="outline" onClick={() => setConditionalDialogOpen(true)}>
<Settings className="h-4 w-4 mr-2" />
Manage Rules
</Button>
</div>
<div className="text-sm text-muted-foreground">
{schema?.conditional_rules?.length || 0} conditional rule(s) configured
</div>
</Card>
</div>
{/* Right Sidebar - Field Properties */}
@@ -912,6 +900,23 @@ const AdminRegistrationBuilder = () => {
</div>
)}
</Card>
{/* Conditional Rules */}
<Card className="p-6 mt-6">
<div className="flex flex-col justify-between items-center mb-4">
<div className="flex items-center gap-2">
<Zap className="h-5 w-5 text-yellow-500" />
<h2 className="text-lg font-semibold">Conditional Rules</h2>
</div>
<Button size="sm" variant="outline" onClick={() => setConditionalDialogOpen(true)}>
<Settings className="h-4 w-4 mr-2" />
Manage Rules
</Button>
</div>
<div className="text-sm text-muted-foreground">
{schema?.conditional_rules?.length || 0} conditional rule(s) configured
</div>
</Card>
</div>
</div>
@@ -1120,13 +1125,12 @@ const AdminRegistrationBuilder = () => {
.map((field) => (
<div
key={field.id}
className={`${
field.width === 'full'
? 'col-span-2'
: field.width === 'third'
className={`${field.width === 'full'
? 'col-span-2'
: field.width === 'third'
? 'col-span-1'
: 'col-span-1'
}`}
}`}
>
<Label>
{field.label}