'use client' import { useState } from 'react' import { useParams, useRouter } from 'next/navigation' import { createFunnel, type CreateFunnelRequest, type FunnelStep } from '@/lib/api/funnels' import { toast, Input, Button, ChevronLeftIcon, PlusIcon, TrashIcon } from '@ciphera-net/ui' import Link from 'next/link' function isValidRegex(pattern: string): boolean { try { new RegExp(pattern) return true } catch { return false } } export default function CreateFunnelPage() { const params = useParams() const router = useRouter() const siteId = params.id as string const [name, setName] = useState('') const [description, setDescription] = useState('') // * Backend requires at least one step (API binding min=1, DB rejects empty steps) const [steps, setSteps] = useState[]>([ { name: 'Step 1', value: '/', type: 'exact' }, { name: 'Step 2', value: '', type: 'exact' } ]) const [saving, setSaving] = useState(false) const handleAddStep = () => { setSteps([...steps, { name: `Step ${steps.length + 1}`, value: '', type: 'exact' }]) } const handleRemoveStep = (index: number) => { if (steps.length <= 1) return const newSteps = steps.filter((_, i) => i !== index) setSteps(newSteps) } const handleUpdateStep = (index: number, field: keyof Omit, value: string) => { const newSteps = [...steps] newSteps[index] = { ...newSteps[index], [field]: value } setSteps(newSteps) } const handleSubmit = async (e: React.FormEvent) => { e.preventDefault() if (!name.trim()) { toast.error('Please enter a funnel name') return } if (steps.some(s => !s.name.trim())) { toast.error('Please enter a name for all steps') return } if (steps.some(s => !s.value.trim())) { toast.error('Please enter a path for all steps') return } const invalidRegexStep = steps.find(s => s.type === 'regex' && !isValidRegex(s.value)) if (invalidRegexStep) { toast.error(`Invalid regex pattern in step: ${invalidRegexStep.name}`) return } try { setSaving(true) const funnelSteps = steps.map((s, i) => ({ ...s, order: i + 1 })) await createFunnel(siteId, { name, description, steps: funnelSteps }) toast.success('Funnel created') router.push(`/sites/${siteId}/funnels`) } catch (error) { toast.error('Failed to create funnel. Please try again.') } finally { setSaving(false) } } return (
Back to Funnels

Create New Funnel

Define the steps users take to complete a goal.

setName(e.target.value)} placeholder="e.g. Signup Flow" autoFocus required maxLength={100} /> {name.length > 80 && ( 90 ? 'text-amber-500' : 'text-neutral-400'}`}>{name.length}/100 )}
setDescription(e.target.value)} placeholder="Tracks users from landing page to signup" />

Funnel Steps

{steps.map((step, index) => (
{index + 1}
handleUpdateStep(index, 'name', e.target.value)} placeholder="e.g. Landing Page" />
handleUpdateStep(index, 'value', e.target.value)} placeholder={step.type === 'exact' ? '/pricing' : 'pricing'} className="flex-1" />
))}
) }