// Animated progress for a photo search. The search is a single server call (embed -> search -> rank // all happen server-side in ~1s), so this walks through the real stages on a short timer with an // indeterminate bar, and surfaces how many dogs the photo is being compared against. import { useEffect, useState } from "react"; // Minimum time the progress panel stays up, so the staged steps play out at a readable pace even // when the search itself returns in a fraction of a second. The callers await this before showing // results. export const MIN_PROGRESS_MS = 1600; export default function SearchProgress({ mode = "match", count, }: { mode?: "match" | "breed"; count?: number; }) { const dogs = count && count > 0 ? count.toLocaleString() : null; const steps = mode === "breed" ? ["Reading the image", "Classifying across 120 breeds", "Ranking the closest look-alikes"] : [ "Extracting features", dogs ? `Searching ${dogs} dogs` : "Searching the database", "Ranking the closest matches", ]; const subtitle = mode === "breed" ? "Classifying against 120 known breeds" : dogs ? `Comparing against ${dogs} found & unclaimed dogs` : null; const [step, setStep] = useState(0); useEffect(() => { const id = setInterval(() => setStep((s) => Math.min(s + 1, steps.length - 1)), 600); return () => clearInterval(id); }, [steps.length]); const pct = [34, 68, 95][step]; return (

{steps[step]}…

{subtitle &&

{subtitle}

}
    {steps.map((s, i) => (
  1. {s}
  2. ))}
); }