import { Loader2 } from "lucide-react"; import { useState } from "react"; import { useTranslation } from "@/contexts/i18n-context"; import { formatHeaders } from "@/lib/api"; import { format } from "@/lib/format"; import { useBase64Store } from "@/stores/base64-store"; import { useFileStore } from "@/stores/file-store"; const OUTPUT_FORMATS = [ { value: "original", label: "Keep Original" }, { value: "jpeg", label: "JPEG" }, { value: "png", label: "PNG" }, { value: "webp", label: "WebP" }, { value: "avif", label: "AVIF" }, { value: "jxl", label: "JXL" }, ] as const; export function ImageToBase64Settings() { const { t } = useTranslation(); const { files } = useFileStore(); const { processing, setProcessing, setProgress, addResult, addError, reset } = useBase64Store(); const [outputFormat, setOutputFormat] = useState("original"); const [quality, setQuality] = useState(80); const [maxWidth, setMaxWidth] = useState(0); const [maxHeight, setMaxHeight] = useState(0); const [error, setError] = useState(null); const handleProcess = async () => { if (files.length === 0) return; setProcessing(true); setError(null); reset(); setProcessing(true); const settings = JSON.stringify({ outputFormat, quality, maxWidth, maxHeight }); for (let i = 0; i < files.length; i++) { const file = files[i]; setProgress({ completed: i, total: files.length, currentFile: file.name }); try { const formData = new FormData(); formData.append("files", file); formData.append("settings", settings); const res = await fetch("/api/v1/tools/image-to-base64", { method: "POST", headers: formatHeaders(), body: formData, }); if (!res.ok) { const body = await res.json().catch(() => ({})); addError({ filename: file.name, error: body.error || `Failed: ${res.status}` }); continue; } const data = await res.json(); for (const r of data.results) addResult(r); for (const e of data.errors) addError(e); } catch (err) { addError({ filename: file.name, error: err instanceof Error ? err.message : "Failed to convert", }); } } setProgress(null); setProcessing(false); }; const hasFiles = files.length > 0; const showQuality = outputFormat === "jpeg" || outputFormat === "webp" || outputFormat === "avif" || outputFormat === "jxl"; return (
{/* Output Format */}
Output Image Format

Convert before encoding to control MIME type and size

{OUTPUT_FORMATS.map((fmt) => ( ))}
{/* Quality slider */} {showQuality && (
{quality}%
setQuality(Number(e.target.value))} className="w-full mt-1 accent-primary" />

Lower quality = smaller base64 string

)} {/* Max Width */}
setMaxWidth(Math.max(0, Number(e.target.value)))} placeholder="0 = no limit" className="mt-1 w-full rounded bg-muted px-3 py-1.5 text-xs text-foreground placeholder:text-muted-foreground outline-none" />
{/* Max Height */}
setMaxHeight(Math.max(0, Number(e.target.value)))} placeholder="0 = no limit" className="mt-1 w-full rounded bg-muted px-3 py-1.5 text-xs text-foreground placeholder:text-muted-foreground outline-none" />

Resize before encoding. Aspect ratio is preserved. 0 = no limit.

{/* Process button */} {error &&

{error}

}
); }