'use client' import { useEffect, useState } from 'react' import { useParams } from 'next/navigation' import { motion } from 'framer-motion' import { getDateRange, formatDate, getThisWeekRange, getThisMonthRange } from '@/lib/utils/dateRanges' import { Select, DatePicker } from '@ciphera-net/ui' import ColumnJourney from '@/components/journeys/ColumnJourney' import SankeyJourney from '@/components/journeys/SankeyJourney' import TopPathsTable from '@/components/journeys/TopPathsTable' import { JourneysSkeleton, useMinimumLoading, useSkeletonFade } from '@/components/skeletons' import { useDashboard, useJourneyTransitions, useJourneyTopPaths, useJourneyEntryPoints, } from '@/lib/swr/dashboard' const DEFAULT_DEPTH = 4 export default function JourneysPage() { const params = useParams() const siteId = params.id as string const [period, setPeriod] = useState('30') const [dateRange, setDateRange] = useState(() => getDateRange(30)) const [isDatePickerOpen, setIsDatePickerOpen] = useState(false) const [depth, setDepth] = useState(DEFAULT_DEPTH) const [committedDepth, setCommittedDepth] = useState(DEFAULT_DEPTH) const [entryPath, setEntryPath] = useState('') const [viewMode, setViewMode] = useState<'columns' | 'flow'>('columns') useEffect(() => { const t = setTimeout(() => setCommittedDepth(depth), 300) return () => clearTimeout(t) }, [depth]) const isDefault = depth === DEFAULT_DEPTH && !entryPath function resetFilters() { setDepth(DEFAULT_DEPTH) setCommittedDepth(DEFAULT_DEPTH) setEntryPath('') } const { data: transitionsData, isLoading: transitionsLoading } = useJourneyTransitions( siteId, dateRange.start, dateRange.end, committedDepth, 1, entryPath || undefined ) const { data: topPaths, isLoading: topPathsLoading } = useJourneyTopPaths( siteId, dateRange.start, dateRange.end, 20, 1, entryPath || undefined ) const { data: entryPoints } = useJourneyEntryPoints(siteId, dateRange.start, dateRange.end) const { data: dashboard } = useDashboard(siteId, dateRange.start, dateRange.end) useEffect(() => { const domain = dashboard?.site?.domain document.title = domain ? `Journeys \u00b7 ${domain} | Pulse` : 'Journeys | Pulse' }, [dashboard?.site?.domain]) const showSkeleton = useMinimumLoading(transitionsLoading && !transitionsData) const fadeClass = useSkeletonFade(showSkeleton) const entryPointOptions = [ { value: '', label: 'All entry points' }, ...(entryPoints ?? []).map((ep) => ({ value: ep.path, label: `${ep.path} (${ep.session_count.toLocaleString()})`, })), ] if (showSkeleton) return const totalSessions = transitionsData?.total_sessions ?? 0 return (
{/* Header */}

Journeys

How visitors navigate through your site

setDepth(parseInt(e.target.value))} aria-label="Journey depth" aria-valuetext={`${depth} steps deep`} className="w-full h-2 bg-neutral-200 rounded-lg appearance-none cursor-pointer dark:bg-neutral-700 accent-brand-orange focus:outline-none" />
{/* Entry point + Reset */}