final settings pages fixes
This commit is contained in:
parent
fc380a49fb
commit
919894ee92
1 changed files with 58 additions and 22 deletions
|
|
@ -10,8 +10,8 @@ type Rec = {
|
||||||
setting_title?: string | null;
|
setting_title?: string | null;
|
||||||
setting_notes?: string | null;
|
setting_notes?: string | null;
|
||||||
|
|
||||||
photo?: { id?: string } | string | null;
|
photo?: { id?: string } | string | number | null;
|
||||||
screen?: { id?: string } | string | null;
|
screen?: { id?: string } | string | number | null;
|
||||||
|
|
||||||
// ids & readable fields
|
// ids & readable fields
|
||||||
mat?: { id?: string | number; name?: string | null } | null;
|
mat?: { id?: string | number; name?: string | null } | null;
|
||||||
|
|
@ -54,9 +54,18 @@ function isMine(owner: Rec["owner"], meId: string | null) {
|
||||||
return owner.id != null && String(owner.id) === meId;
|
return owner.id != null && String(owner.id) === meId;
|
||||||
}
|
}
|
||||||
|
|
||||||
function fileUrl(id?: string) {
|
// --- Image helpers -----------------------------------------------------------
|
||||||
|
function resolveFileId(v: Rec["photo"]): string | null {
|
||||||
|
if (v == null) return null;
|
||||||
|
if (typeof v === "string" || typeof v === "number") return String(v);
|
||||||
|
if (typeof v === "object" && v.id) return String(v.id);
|
||||||
|
// some Directus shapes may nest deeper; add more cases if needed
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
function assetSrc(id?: string | null) {
|
||||||
return id ? `/api/dx/assets/${id}` : "";
|
return id ? `/api/dx/assets/${id}` : "";
|
||||||
}
|
}
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
export default function CO2GalvoDetail({
|
export default function CO2GalvoDetail({
|
||||||
id,
|
id,
|
||||||
|
|
@ -171,10 +180,11 @@ export default function CO2GalvoDetail({
|
||||||
|
|
||||||
const initialValues = useMemo(() => {
|
const initialValues = useMemo(() => {
|
||||||
if (!rec) return null;
|
if (!rec) return null;
|
||||||
|
|
||||||
const toId = (v: any) => (v == null ? null : typeof v === "object" ? v.id ?? v.submission_id ?? null : v);
|
const toId = (v: any) => (v == null ? null : typeof v === "object" ? v.id ?? v.submission_id ?? null : v);
|
||||||
|
|
||||||
const photoId = typeof rec.photo === "string" || typeof rec.photo === "number" ? String(rec.photo) : rec.photo?.id ?? null;
|
const photoId = resolveFileId(rec.photo);
|
||||||
const screenId = typeof rec.screen === "string" || typeof rec.screen === "number" ? String(rec.screen) : rec.screen?.id ?? null;
|
const screenId = resolveFileId(rec.screen);
|
||||||
|
|
||||||
const matId = toId(rec.mat);
|
const matId = toId(rec.mat);
|
||||||
const coatId = toId(rec.mat_coat);
|
const coatId = toId(rec.mat_coat);
|
||||||
|
|
@ -229,14 +239,33 @@ export default function CO2GalvoDetail({
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// VIEW (readable)
|
// VIEW
|
||||||
const ownerDisplay = ownerLabel(rec.owner);
|
const ownerDisplay = ownerLabel(rec.owner);
|
||||||
const canEdit = showOwnerEdit && isMine(rec.owner, meId);
|
const canEdit = showOwnerEdit && isMine(rec.owner, meId);
|
||||||
|
|
||||||
const photoId = typeof rec.photo === "object" ? rec.photo?.id : (rec.photo as any);
|
const photoSrc = assetSrc(resolveFileId(rec.photo));
|
||||||
const screenId = typeof rec.screen === "object" ? rec.screen?.id : (rec.screen as any);
|
const screenSrc = assetSrc(resolveFileId(rec.screen));
|
||||||
const photoSrc = photoId ? fileUrl(String(photoId)) : "";
|
|
||||||
const screenSrc = screenId ? fileUrl(String(screenId)) : "";
|
// simple lightbox state
|
||||||
|
const [lightbox, setLightbox] = useState<{ src: string; alt: string } | null>(null);
|
||||||
|
|
||||||
|
function Thumb({ src, alt }: { src: string; alt: string }) {
|
||||||
|
if (!src) return null;
|
||||||
|
return (
|
||||||
|
<figure className="border rounded overflow-hidden">
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={() => setLightbox({ src, alt })}
|
||||||
|
className="block w-full aspect-square overflow-hidden"
|
||||||
|
aria-label={`Open ${alt}`}
|
||||||
|
>
|
||||||
|
{/* 1:1 crop */}
|
||||||
|
<img src={src} alt={alt} className="w-full h-full object-cover" loading="lazy" />
|
||||||
|
</button>
|
||||||
|
<figcaption className="text-xs p-1 text-muted-foreground">{alt}</figcaption>
|
||||||
|
</figure>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="space-y-6">
|
<div className="space-y-6">
|
||||||
|
|
@ -285,18 +314,8 @@ export default function CO2GalvoDetail({
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="grid grid-cols-2 gap-4">
|
<div className="grid grid-cols-2 gap-4">
|
||||||
{photoSrc ? (
|
<Thumb src={photoSrc} alt="Result" />
|
||||||
<figure className="border rounded overflow-hidden">
|
<Thumb src={screenSrc} alt="Settings Screenshot" />
|
||||||
<img src={photoSrc} alt="Result" className="w-full h-auto" />
|
|
||||||
<figcaption className="text-xs p-1 text-muted-foreground">Result</figcaption>
|
|
||||||
</figure>
|
|
||||||
) : null}
|
|
||||||
{screenSrc ? (
|
|
||||||
<figure className="border rounded overflow-hidden">
|
|
||||||
<img src={screenSrc} alt="Settings screenshot" className="w-full h-auto" />
|
|
||||||
<figcaption className="text-xs p-1 text-muted-foreground">Settings Screenshot</figcaption>
|
|
||||||
</figure>
|
|
||||||
) : null}
|
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
|
@ -406,6 +425,23 @@ export default function CO2GalvoDetail({
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
{/* Lightbox overlay */}
|
||||||
|
{lightbox && (
|
||||||
|
<div
|
||||||
|
className="fixed inset-0 z-50 bg-black/80 flex items-center justify-center p-4"
|
||||||
|
onClick={() => setLightbox(null)}
|
||||||
|
role="dialog"
|
||||||
|
aria-modal="true"
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
src={lightbox.src}
|
||||||
|
alt={lightbox.alt}
|
||||||
|
className="max-w-[90vw] max-h-[90vh] object-contain rounded"
|
||||||
|
onClick={(e) => e.stopPropagation()}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue