From ceb668890b370b555d224970c2afda1adf4ac4ba Mon Sep 17 00:00:00 2001 From: Usman Baig Date: Thu, 5 Feb 2026 00:04:44 +0100 Subject: [PATCH] feat: enhance error handling in FunnelReportPage by adding specific messages for not found and general load errors, improving user feedback and experience --- app/sites/[id]/funnels/[funnelId]/page.tsx | 26 +++++++++++++++++++++- app/sites/[id]/funnels/new/page.tsx | 5 +++++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/app/sites/[id]/funnels/[funnelId]/page.tsx b/app/sites/[id]/funnels/[funnelId]/page.tsx index ac1b729..ddbec35 100644 --- a/app/sites/[id]/funnels/[funnelId]/page.tsx +++ b/app/sites/[id]/funnels/[funnelId]/page.tsx @@ -2,6 +2,7 @@ import { useCallback, useEffect, useMemo, useState } from 'react' import { useParams, useRouter } from 'next/navigation' +import { ApiError } from '@/lib/api/client' import { getFunnel, getFunnelStats, deleteFunnel, type Funnel, type FunnelStats } from '@/lib/api/funnels' import { toast, LoadingOverlay, Select, DatePicker, ChevronLeftIcon, ArrowRightIcon, TrashIcon, useTheme } from '@ciphera-net/ui' import Link from 'next/link' @@ -45,8 +46,10 @@ export default function FunnelReportPage() { const [dateRange, setDateRange] = useState(getDateRange(30)) const [datePreset, setDatePreset] = useState<'7' | '30' | 'custom'>('30') const [isDatePickerOpen, setIsDatePickerOpen] = useState(false) + const [loadError, setLoadError] = useState<'not_found' | 'error' | null>(null) const loadData = useCallback(async () => { + setLoadError(null) try { setLoading(true) const [funnelData, statsData] = await Promise.all([ @@ -56,7 +59,9 @@ export default function FunnelReportPage() { setFunnel(funnelData) setStats(statsData) } catch (error) { - toast.error('Failed to load funnel data') + const is404 = error instanceof ApiError && error.status === 404 + setLoadError(is404 ? 'not_found' : 'error') + if (!is404) toast.error('Failed to load funnel data') } finally { setLoading(false) } @@ -88,6 +93,25 @@ export default function FunnelReportPage() { return } + if (loadError === 'not_found' || (!funnel && !stats && !loadError)) { + return ( +
+

Funnel not found

+
+ ) + } + + if (loadError === 'error') { + return ( +
+

Failed to load funnel data

+ +
+ ) + } + if (!funnel || !stats) { return (
diff --git a/app/sites/[id]/funnels/new/page.tsx b/app/sites/[id]/funnels/new/page.tsx index 30aa77b..fedc126 100644 --- a/app/sites/[id]/funnels/new/page.tsx +++ b/app/sites/[id]/funnels/new/page.tsx @@ -53,6 +53,11 @@ export default function CreateFunnelPage() { 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