import { useEffect, useState } from "react"; import { useLocation, useNavigate } from "react-router-dom"; import { api } from "../api"; import { EmptyState, FeedbackBanner, FreshnessBanner, LoadingState } from "../components/Feedback"; import { usePollingResource } from "../hooks/usePollingResource"; import { isTimestampStale, visitorStatusMeta } from "../lib/format"; import type { PublicStatusDto } from "../types"; import { VisitorTicketCard } from "./VisitorTicketCard"; const PHONE_STORAGE_KEY = "scenic-visitor-query-phone"; function ticketKey(ticket: PublicStatusDto): string { return `${ticket.project?.id ?? ticket.project_name}:${ticket.ticket_number}`; } function readStoredPhone(): string { try { return window.sessionStorage.getItem(PHONE_STORAGE_KEY) ?? ""; } catch { return ""; } } function storePhone(phone: string): void { try { window.sessionStorage.setItem(PHONE_STORAGE_KEY, phone); } catch { // Session storage is only a refresh convenience for this temporary flow. } } function clearStoredPhone(): void { try { window.sessionStorage.removeItem(PHONE_STORAGE_KEY); } catch { // Ignore storage failures; the page can still navigate normally. } } interface VisitorPhoneLocationState { phone?: string; } export function VisitorPhonePage() { const location = useLocation(); const navigate = useNavigate(); const locationPhone = (location.state as VisitorPhoneLocationState | null)?.phone?.trim() ?? ""; const [phone] = useState(() => locationPhone || readStoredPhone()); const [selectedKey, setSelectedKey] = useState(null); const resource = usePollingResource((signal) => api.publicStatusByPhone(phone, signal), { enabled: Boolean(phone), intervalMs: 3_000, resourceKey: phone || "visitor-phone", }); const data = resource.data; const tickets = data?.tickets ?? []; const selectedTicket = tickets.find((ticket) => ticketKey(ticket) === selectedKey) ?? tickets[0]; const freshnessTime = resource.lastClientSuccessAt; const stale = Boolean(data) && isTimestampStale(freshnessTime, 30_000); useEffect(() => { if (locationPhone) storePhone(locationPhone); }, [locationPhone]); useEffect(() => { if (!tickets.length) { setSelectedKey(null); return; } const currentKey = selectedKey && tickets.some((ticket) => ticketKey(ticket) === selectedKey) ? selectedKey : ticketKey(tickets[0]); if (currentKey !== selectedKey) setSelectedKey(currentKey); }, [selectedKey, tickets]); function returnToLookup() { clearStoredPhone(); navigate("/visitor"); } const liveTone = resource.offline ? "offline" : stale || resource.error ? "stale" : "live"; const liveLabel = resource.offline ? "连接中断" : stale || resource.error ? "更新延迟" : "实时更新"; return (
小七孔文旅集团排队服务