"use client"; import { useState, useRef } from "react"; import { useTranslations } from "next-intl"; import { Upload, X, Star } from "lucide-react"; import { Button } from "@/components/ui/button"; import { getPublicUrl } from "@/lib/storage"; export type PhotoEntry = { key: string; isCover: boolean; preview: string; }; export function PhotoUploader({ recipeId, photos, onChange, }: { recipeId: string; photos: PhotoEntry[]; onChange: (photos: PhotoEntry[]) => void; }) { const t = useTranslations("recipeForm"); const [uploading, setUploading] = useState(false); const inputRef = useRef(null); async function handleFiles(files: FileList) { setUploading(true); try { for (const file of Array.from(files)) { const res = await fetch("/api/v1/upload/presign", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ recipeId, contentType: file.type }), }); if (!res.ok) continue; const { url, key } = await res.json() as { url: string; key: string }; await fetch(url, { method: "PUT", body: file, headers: { "Content-Type": file.type } }); const isFirst = photos.length === 0; onChange([...photos, { key, isCover: isFirst, preview: URL.createObjectURL(file) }]); } } finally { setUploading(false); } } function setCover(key: string) { onChange(photos.map((p) => ({ ...p, isCover: p.key === key }))); } function remove(key: string) { const filtered = photos.filter((p) => p.key !== key); if (filtered.length > 0 && !filtered.some((p) => p.isCover)) { filtered[0]!.isCover = true; } onChange(filtered); } return (
{photos.map((photo) => (
{photo.isCover && ( cover )}
))}
e.target.files && handleFiles(e.target.files)} />
); }