commits
tags
import { useEffect, useState } from "react";
import { ApiError, api } from "../lib/api";
interface Props {
label: string;
value: string;
onChange: (v: string) => void;
}
/** Fält för desktop_*_image-stegens referensbild: filnamn + "Fånga"-knapp +
* lista över befintliga bilder + miniatyr. */
export function ImageField({ label, value, onChange }: Props) {
const [images, setImages] = useState<string[]>([]);
const [busy, setBusy] = useState(false);
const [err, setErr] = useState<string | null>(null);
const refresh = () => api.listDesktopImages().then(setImages).catch(() => {});
useEffect(() => {
refresh();
}, []);
async function capture() {
const suggested = value.replace(/\.png$/i, "") || `bild ${images.length + 1}`;
const name = window.prompt("Namn på referensbilden:", suggested);
if (name === null) return;
setBusy(true);
setErr(null);
try {
const res = await api.captureDesktopImage(name.trim());
onChange(res.name);
await refresh();
} catch (e) {
setErr(e instanceof ApiError ? String(e.detail) : String(e));
} finally {
setBusy(false);
}
}
const known = value && images.includes(value);
return (
<label className="field image-field">
<span>{label}</span>
<div className="image-field-row">
<input
type="text"
list="desktop-images"
value={value ?? ""}
placeholder="filnamn.png"
onChange={(e) => onChange(e.target.value)}
/>
<datalist id="desktop-images">
{images.map((n) => (
<option key={n} value={n} />
))}
</datalist>
<button type="button" className="secondary tiny" disabled={busy} onClick={capture}>
{busy ? "…" : "📷 Fånga"}
</button>
</div>
{known && <img className="image-field-preview" src={api.desktopImageUrl(value)} alt={value} />}
{err && <span className="assist-msg error">{err}</span>}
</label>
);
}