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 } 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'`. `null` = latest available day // (data is T+1 and may lag, so the default queries MAX(dt) server-side // rather than hard-coding yesterday); a picked date overrides it. const [snapshotDt, setSnapshotDt] = useState(null); 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` with a picked date; omit it // for latest single-day and for 7d/30d (the server returns the latest row). const dayParam = period === 'day' && snapshotDt ? toSnapshotParam(snapshotDt) : undefined; useEffect(() => { mutate(dayParam ? { period: 'day', snapshot_dt: dayParam } : { period }); }, [period, dayParam, mutate]); return (
{/* 标题行:标题 + Mock 徽章 在左,控件 ml-auto 落右;时间边界在控件正下方 */}

漏斗分析

{USE_MOCK && ( Mock 模式 )}
{/* 单日 / 近7天 / 近30天 三选一,选中 mint 高亮;单日可选历史。 */} { setSnapshotDt(d); setPeriod('day'); }} onPickLatest={() => { setSnapshotDt(null); setPeriod('day'); }} onPickRolling={(p) => setPeriod(p)} /> {/* 滚动周期显示日期范围;单日不显示。查询 pending 时不渲染, 避免用旧 snapshot_dt 配新 period 算出错误范围。 */} {!mutation.isPending && mutation.data?.snapshot_dt && period !== 'day' && ( {funnelRangeText(period, mutation.data.snapshot_dt)} )}

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

); } export default FunnelPage;