From 585cb4fd8837d1e3fdc6418343ff5b984087e87e Mon Sep 17 00:00:00 2001 From: Usman Baig Date: Wed, 18 Mar 2026 14:27:45 +0100 Subject: [PATCH] feat(funnels): add edit funnel page with pre-populated form --- .../[id]/funnels/[funnelId]/edit/page.tsx | 58 +++++++++++++++++++ app/sites/[id]/funnels/[funnelId]/page.tsx | 8 +++ 2 files changed, 66 insertions(+) create mode 100644 app/sites/[id]/funnels/[funnelId]/edit/page.tsx diff --git a/app/sites/[id]/funnels/[funnelId]/edit/page.tsx b/app/sites/[id]/funnels/[funnelId]/edit/page.tsx new file mode 100644 index 0000000..cea7f0f --- /dev/null +++ b/app/sites/[id]/funnels/[funnelId]/edit/page.tsx @@ -0,0 +1,58 @@ +'use client' + +import { useEffect, useState } from 'react' +import { useParams, useRouter } from 'next/navigation' +import { useSWRConfig } from 'swr' +import { getFunnel, updateFunnel, type Funnel, type CreateFunnelRequest } from '@/lib/api/funnels' +import { toast } from '@ciphera-net/ui' +import FunnelForm from '@/components/funnels/FunnelForm' +import { FunnelDetailSkeleton } from '@/components/skeletons' + +export default function EditFunnelPage() { + const params = useParams() + const router = useRouter() + const { mutate } = useSWRConfig() + const siteId = params.id as string + const funnelId = params.funnelId as string + const [funnel, setFunnel] = useState(null) + const [saving, setSaving] = useState(false) + + useEffect(() => { + getFunnel(siteId, funnelId).then(setFunnel).catch(() => { + toast.error('Failed to load funnel') + router.push(`/sites/${siteId}/funnels`) + }) + }, [siteId, funnelId, router]) + + const handleSubmit = async (data: CreateFunnelRequest) => { + try { + setSaving(true) + await updateFunnel(siteId, funnelId, data) + await mutate(['funnels', siteId]) + toast.success('Funnel updated') + router.push(`/sites/${siteId}/funnels/${funnelId}`) + } catch { + toast.error('Failed to update funnel. Please try again.') + } finally { + setSaving(false) + } + } + + if (!funnel) return + + return ( + rest), + conversion_window_value: funnel.conversion_window_value, + conversion_window_unit: funnel.conversion_window_unit, + }} + onSubmit={handleSubmit} + submitLabel={saving ? 'Saving...' : 'Save Changes'} + cancelHref={`/sites/${siteId}/funnels/${funnelId}`} + /> + ) +} diff --git a/app/sites/[id]/funnels/[funnelId]/page.tsx b/app/sites/[id]/funnels/[funnelId]/page.tsx index 4936335..5e688d9 100644 --- a/app/sites/[id]/funnels/[funnelId]/page.tsx +++ b/app/sites/[id]/funnels/[funnelId]/page.tsx @@ -8,6 +8,7 @@ import FilterBar from '@/components/dashboard/FilterBar' import AddFilterDropdown from '@/components/dashboard/AddFilterDropdown' import { type DimensionFilter, serializeFilters } from '@/lib/filters' import { toast, Select, DatePicker, ChevronLeftIcon, ArrowRightIcon, TrashIcon, Button } from '@ciphera-net/ui' +import { PencilSimple } from '@phosphor-icons/react' import { FunnelDetailSkeleton, useMinimumLoading, useSkeletonFade } from '@/components/skeletons' import Link from 'next/link' import { FunnelChart } from '@/components/ui/funnel-chart' @@ -162,6 +163,13 @@ export default function FunnelReportPage() { ]} /> + + +