perf: migrate Settings, Funnels, and Uptime to SWR data fetching

Replace manual useState/useEffect fetch patterns with SWR hooks so
cached data renders instantly on tab revisit. Skeleton loading now
only appears on the initial cold load, not every navigation.

New hooks: useFunnels, useUptimeStatus, useGoals, useReportSchedules,
useSubscription — all with background revalidation.
This commit is contained in:
Usman Baig
2026-03-13 12:21:55 +01:00
parent b6a7c642f2
commit 6380f216aa
5 changed files with 143 additions and 190 deletions

View File

@@ -29,6 +29,11 @@ import { listAnnotations } from '@/lib/api/annotations'
import type { Annotation } from '@/lib/api/annotations'
import { getSite } from '@/lib/api/sites'
import type { Site } from '@/lib/api/sites'
import { listFunnels, type Funnel } from '@/lib/api/funnels'
import { getUptimeStatus, type UptimeStatusResponse } from '@/lib/api/uptime'
import { listGoals, type Goal } from '@/lib/api/goals'
import { listReportSchedules, type ReportSchedule } from '@/lib/api/report-schedules'
import { getSubscription, type SubscriptionDetails } from '@/lib/api/billing'
import type {
Stats,
DailyStat,
@@ -69,6 +74,11 @@ const fetchers = {
getJourneyTopPaths(siteId, start, end, { limit, minSessions, entryPath }),
journeyEntryPoints: (siteId: string, start: string, end: string) =>
getJourneyEntryPoints(siteId, start, end),
funnels: (siteId: string) => listFunnels(siteId),
uptimeStatus: (siteId: string) => getUptimeStatus(siteId),
goals: (siteId: string) => listGoals(siteId),
reportSchedules: (siteId: string) => listReportSchedules(siteId),
subscription: () => getSubscription(),
}
// * Standard SWR config for dashboard data
@@ -334,5 +344,71 @@ export function useJourneyEntryPoints(siteId: string, start: string, end: string
)
}
// * Hook for funnels list
export function useFunnels(siteId: string) {
return useSWR<Funnel[]>(
siteId ? ['funnels', siteId] : null,
() => fetchers.funnels(siteId),
{
...dashboardSWRConfig,
refreshInterval: 60 * 1000,
dedupingInterval: 10 * 1000,
}
)
}
// * Hook for uptime status (refreshes every 30s to match original polling)
export function useUptimeStatus(siteId: string) {
return useSWR<UptimeStatusResponse>(
siteId ? ['uptimeStatus', siteId] : null,
() => fetchers.uptimeStatus(siteId),
{
...dashboardSWRConfig,
refreshInterval: 30 * 1000,
dedupingInterval: 10 * 1000,
keepPreviousData: true,
}
)
}
// * Hook for goals list
export function useGoals(siteId: string) {
return useSWR<Goal[]>(
siteId ? ['goals', siteId] : null,
() => fetchers.goals(siteId),
{
...dashboardSWRConfig,
refreshInterval: 60 * 1000,
dedupingInterval: 10 * 1000,
}
)
}
// * Hook for report schedules
export function useReportSchedules(siteId: string) {
return useSWR<ReportSchedule[]>(
siteId ? ['reportSchedules', siteId] : null,
() => fetchers.reportSchedules(siteId),
{
...dashboardSWRConfig,
refreshInterval: 60 * 1000,
dedupingInterval: 10 * 1000,
}
)
}
// * Hook for subscription details (changes rarely)
export function useSubscription() {
return useSWR<SubscriptionDetails>(
'subscription',
() => fetchers.subscription(),
{
...dashboardSWRConfig,
refreshInterval: 5 * 60 * 1000,
dedupingInterval: 30 * 1000,
}
)
}
// * Re-export for convenience
export { fetchers }