"use client"; import { useState, useEffect, useRef } from "react"; import { useQuery } from "@tanstack/react-query"; import { EVENT_CONFIG, EventType, formatDuration } from "@/lib/event-config"; import { EventIcon } from "@/components/event-icon"; import { useBaby } from "@/contexts/baby-context"; import { format } from "date-fns"; import { fr } from "date-fns/locale"; import { Search, FileText, StickyNote } from "lucide-react"; interface SearchEvent { id: string; type: EventType; startedAt: string; endedAt?: string; notes?: string; metadata?: Record; user: { id: string; name: string }; } interface SearchNote { id: string; date: string; content: string; user: { id: string; name: string }; } function eventSummary(ev: SearchEvent): string { const meta = ev.metadata ?? {}; if (ev.type === "BREASTFEED") { const side = meta.breastSide === "left" ? "gauche" : meta.breastSide === "right" ? "droite" : "les deux"; if (ev.endedAt) return `${formatDuration(new Date(ev.startedAt), new Date(ev.endedAt))} · ${side}`; return side; } if (ev.type === "BOTTLE") return meta.volume ? `${meta.volume} mL` : ""; if (ev.type === "TEMPERATURE") return meta.value ? `${meta.value}°${meta.unit ?? "C"}` : ""; if (ev.type === "MEDICATION") return String(meta.name ?? ""); if (ev.type === "SYMPTOM") return ((meta.tags as string[]) ?? []).join(", "); if ((ev.type === "NAP" || ev.type === "NIGHT_SLEEP") && ev.endedAt) return formatDuration(new Date(ev.startedAt), new Date(ev.endedAt)); return ""; } function highlight(text: string, q: string): React.ReactNode { if (!q || !text) return text; const idx = text.toLowerCase().indexOf(q.toLowerCase()); if (idx === -1) return text; return ( <> {text.slice(0, idx)} {text.slice(idx, idx + q.length)} {text.slice(idx + q.length)} ); } export default function SearchPage() { const { selectedBaby } = useBaby(); const [q, setQ] = useState(""); const [debouncedQ, setDebouncedQ] = useState(""); const inputRef = useRef(null); useEffect(() => { inputRef.current?.focus(); }, []); useEffect(() => { const t = setTimeout(() => setDebouncedQ(q), 300); return () => clearTimeout(t); }, [q]); const { data, isFetching } = useQuery<{ events: SearchEvent[]; notes: SearchNote[] }>({ queryKey: ["search", selectedBaby?.id, debouncedQ], queryFn: () => fetch(`/api/search?babyId=${selectedBaby!.id}&q=${encodeURIComponent(debouncedQ)}`).then((r) => r.json()), enabled: !!selectedBaby?.id && debouncedQ.length >= 2, placeholderData: { events: [], notes: [] }, }); const events = data?.events ?? []; const notes = data?.notes ?? []; const hasResults = events.length > 0 || notes.length > 0; const searched = debouncedQ.length >= 2; return (

Recherche

setQ(e.target.value)} placeholder="Rechercher dans les notes et événements…" className="w-full pl-10 pr-4 py-3 rounded-xl border border-slate-200 dark:border-slate-700 bg-white dark:bg-slate-800 text-slate-900 dark:text-slate-100 text-sm focus:outline-none focus:ring-2 focus:ring-indigo-400" /> {isFetching && (
)}
{!searched && (

Saisissez au moins 2 caractères

)} {searched && !hasResults && !isFetching && (

Aucun résultat pour « {debouncedQ} »

)} {events.length > 0 && (

Événements · {events.length}

{events.map((ev) => { const cfg = EVENT_CONFIG[ev.type]; const summary = eventSummary(ev); return (
{cfg.label} {summary && {summary}}
{ev.notes && (

{highlight(ev.notes, debouncedQ)}

)}

{format(new Date(ev.startedAt), "d MMM yyyy HH:mm", { locale: fr })} · {ev.user.name}

); })}
)} {notes.length > 0 && (

Journal · {notes.length}

{notes.map((note) => (

{format(new Date(note.date), "d MMMM yyyy", { locale: fr })} · {note.user.name}

{highlight(note.content, debouncedQ)}

))}
)}
); }