"use client"; import { useRef, useState } from "react"; import { useTranslations } from "next-intl"; import { useRouter } from "next/navigation"; import { Camera, Loader2 } from "lucide-react"; import { toast } from "sonner"; import { Button } from "@/components/ui/button"; import { FakeProgressBar } from "@/components/ui/fake-progress-bar"; export function PhotoImportButton() { const t = useTranslations("recipe"); const router = useRouter(); const fileRef = useRef(null); const [loading, setLoading] = useState(false); const [stage, setStage] = useState<"recognizing" | "generating">("recognizing"); const stageTimerRef = useRef | null>(null); function handleClick() { fileRef.current?.click(); } async function handleFile(e: React.ChangeEvent) { const file = e.target.files?.[0]; if (!file) return; setLoading(true); setStage("recognizing"); // The photo-import flow is two sequential AI calls (vision recognition, // then text generation) behind a single request/response — there's no // real progress signal to react to, so this just approximates the // handoff point for the loading copy. stageTimerRef.current = setTimeout(() => setStage("generating"), 5000); try { const base64 = await new Promise((resolve, reject) => { const reader = new FileReader(); reader.onload = () => { const result = reader.result as string; // Strip the data:mime/type;base64, prefix const comma = result.indexOf(","); resolve(comma !== -1 ? result.slice(comma + 1) : result); }; reader.onerror = () => reject(reader.error); reader.readAsDataURL(file); }); const res = await fetch("/api/v1/ai/import-photo", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ imageBase64: base64, mimeType: file.type, }), }); if (!res.ok) { if (res.status === 422) throw new Error(t("photoNoRecipeFound")); const data = await res.json().catch(() => ({})) as { error?: string }; throw new Error(data.error ?? `Request failed: ${res.status}`); } const { id } = await res.json() as { id: string }; router.push(`/recipes/${id}/edit`); } catch (err) { toast.error(err instanceof Error ? err.message : t("photoImportFailed")); } finally { if (stageTimerRef.current) clearTimeout(stageTimerRef.current); setLoading(false); // Reset input so the same file can be re-selected if (fileRef.current) fileRef.current.value = ""; } } return (
); }