import { useEffect, useState } from 'react'; import { useMutation } from '@tanstack/react-query'; import { queryFunnel, USE_MOCK } from '../../api/funnel'; import type { FunnelPeriod, FunnelQueryRequest, FunnelQueryResponse, } from '../../api/types'; import { DEFAULT_PERIOD, funnelRangeText, toSnapshotParam, yesterday, } from './period'; import { TimePeriodSelect } from './components/TimePeriodSelect'; import { FunnelResult } from './components/FunnelResult'; import { Badge } from '@/components/ui/badge'; /** * 拼团 5-step funnel page (docs/02 §5 v3). The funnel is fixed. Inputs are the * standard period plus — for `day` only — a historical date. Selecting a period * (incl. the default on first load) or, in single-day mode, a date immediately * fires a query. */ export function FunnelPage() { const [period, setPeriod] = useState(DEFAULT_PERIOD); // Selected calendar day for `period: 'day'`; defaults to yesterday (max). const [snapshotDt, setSnapshotDt] = useState(() => yesterday()); const mutation = useMutation({ mutationFn: queryFunnel, }); const { mutate } = mutation; // Query on mount and whenever the period — or, for single-day, the chosen // date — changes. Send snapshot_dt ONLY for `day`; omit it for 7d/30d. const dayParam = period === 'day' ? toSnapshotParam(snapshotDt) : undefined; useEffect(() => { mutate( period === 'day' ? { period, snapshot_dt: dayParam } : { period }, ); }, [period, dayParam, mutate]); return (
{/* 标题行:标题 + Mock 徽章 在左,控件 ml-auto 落右;时间边界在控件正下方 */}

漏斗分析

{USE_MOCK && ( Mock 模式 )}
{/* 单日 / 近7天 / 近30天 三选一,选中 mint 高亮;单日可选历史。 */} { setSnapshotDt(d); setPeriod('day'); }} onPickRolling={(p) => setPeriod(p)} /> {/* 时间边界:简短日期,不含今日 */} {mutation.data?.snapshot_dt && ( {funnelRangeText(period, mutation.data.snapshot_dt)} · 不含今日 )}

拼团漏斗:启动 → 曝光 → 拼团详情 → 下单 → 成功

); } export default FunnelPage;