mega-plant/components/QrTextCell.tsx

79 lines
2.7 KiB
TypeScript
Raw Normal View History

"use client";
import { useState } from "react";
import { Pencil } from "lucide-react";
type Asset = { id: string; code: string; qr_code?: string };
/**
* The text on a vehicle's QR sticker. Double-click (or tap the pencil) to type it in; Enter
* or leaving the box saves, Escape cancels, and an empty box clears it. Saves on its own —
* it does not wait for the table's Edit mode, because it is one value, not a batch.
*/
export function QrTextCell({ asset, onSaved }: { asset: Asset; onSaved: (qr: string) => void }) {
const [editing, setEditing] = useState(false);
const [value, setValue] = useState("");
const [saving, setSaving] = useState(false);
const [error, setError] = useState("");
function begin() {
setValue(asset.qr_code || "");
setError("");
setEditing(true);
}
async function save() {
if (saving) return;
const next = value.trim();
if (next === (asset.qr_code || "")) { setEditing(false); return; }
setSaving(true);
setError("");
try {
const res = await fetch(`/api/assets/${asset.id}`, {
method: "PATCH",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ qr_code: next }),
});
const j = await res.json().catch(() => ({}));
if (!res.ok || !j.ok) throw new Error(j.error || "Could not save");
onSaved(next);
setEditing(false);
} catch (e: any) {
setError(e.message);
} finally {
setSaving(false);
}
}
if (editing) {
return (
<div>
<input
autoFocus
value={value}
disabled={saving}
maxLength={200}
aria-label={`QR code for ${asset.code}`}
onChange={(e) => setValue(e.target.value)}
onBlur={save}
onKeyDown={(e) => {
if (e.key === "Enter") { e.preventDefault(); save(); }
if (e.key === "Escape") setEditing(false);
}}
className="w-full sm:w-44 min-h-[44px] px-2 rounded-md text-sm font-mono border border-[#30638E] bg-white dark:bg-white/10 focus:outline-none"
/>
{error && <p role="alert" className="text-xs text-[#D1495B] mt-1 max-w-[11rem]">{error}</p>}
</div>
);
}
return (
<div className="flex items-center gap-1 min-h-[44px]" onDoubleClick={begin} title="Double-click to set the QR code">
<span className={asset.qr_code ? "font-mono text-gray-700 dark:text-gray-300 break-all" : "text-gray-400 dark:text-gray-500"}>
{asset.qr_code || "—"}
</span>
<button type="button" onClick={begin} aria-label={`Edit QR code for ${asset.code}`}
className="grid place-items-center min-h-[44px] min-w-[44px] text-gray-400 hover:text-[#30638E]">
<Pencil className="w-3.5 h-3.5" />
</button>
</div>
);
}