"use client"; import { useEffect, useState } from "react"; import { Box, Card, CardContent, Typography, IconButton, Alert, } from "@mui/material"; import MoreVertIcon from "@mui/icons-material/MoreVert"; import CalendarTodayIcon from "@mui/icons-material/CalendarToday"; import { Range } from "react-date-range"; import { DateRangePicker } from "../DateRangePicker/DateRangePicker"; import { StatItem } from "./components/StatItem"; import { DEFAULT_DATE_RANGE } from "./constants"; import { IHealthData } from "@/app/services/health"; import { getHealthData } from "@/app/services/transactions"; import "./GeneralHealthCard.scss"; interface IGeneralHealthCardProps { initialHealthData?: IHealthData | null; initialStats?: Array<{ label: string; value: string | number; change: string; }> | null; initialDateRange?: Range[]; } const DEBOUNCE_MS = 1000; export const GeneralHealthCard = ({ initialHealthData = null, initialStats = null, initialDateRange, }: IGeneralHealthCardProps) => { const [dateRange, setDateRange] = useState( initialDateRange ?? DEFAULT_DATE_RANGE ); const [healthData, setHealthData] = useState( initialHealthData ); const [error, setError] = useState(null); /** * Fetch health data for a given range */ const fetchHealthData = async (range: Range[]) => { const startDate = range[0]?.startDate; const endDate = range[0]?.endDate; if (!startDate || !endDate) return; setError(null); try { const data = await getHealthData({ dateStart: startDate.toISOString(), dateEnd: endDate.toISOString(), }); setHealthData(data); } catch (err) { const message = err instanceof Error ? err.message : "Failed to fetch health data"; setError(message); setHealthData(null); } }; /** * Date picker change handler * (state only — side effects are debounced below) */ const handleDateRangeChange = (newRange: Range[]) => { setDateRange(newRange); }; /** * Debounced fetch when date range changes */ useEffect(() => { const currentRange = dateRange[0]; if (!currentRange?.startDate || !currentRange?.endDate) return; const isInitialDateRange = initialDateRange && currentRange.startDate.getTime() === initialDateRange[0]?.startDate?.getTime() && currentRange.endDate.getTime() === initialDateRange[0]?.endDate?.getTime(); // Skip fetch if we're still on SSR-provided data if (initialHealthData && isInitialDateRange) return; const timeout = setTimeout(() => { fetchHealthData(dateRange); }, DEBOUNCE_MS); return () => clearTimeout(timeout); }, [dateRange]); /** * Resolve stats source */ const stats = healthData?.stats ?? initialStats ?? [ { label: "TOTAL", value: 0, change: "0%" }, { label: "SUCCESSFUL", value: 0, change: "0%" }, { label: "ACCEPTANCE RATE", value: "0%", change: "0%" }, { label: "AMOUNT", value: "€0.00", change: "0%" }, { label: "ATV", value: "€0.00", change: "0%" }, ]; return ( General Health {error && ( {error} )} {!error && ( {stats.map((item, i) => ( ))} )} ); };