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_notes?: string | null;
|
||||
|
||||
photo?: { id?: string } | string | null;
|
||||
screen?: { id?: string } | string | null;
|
||||
photo?: { id?: string } | string | number | null;
|
||||
screen?: { id?: string } | string | number | null;
|
||||
|
||||
// ids & readable fields
|
||||
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;
|
||||
}
|
||||
|
||||
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}` : "";
|
||||
}
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
export default function CO2GalvoDetail({
|
||||
id,
|
||||
|
|
@ -171,10 +180,11 @@ export default function CO2GalvoDetail({
|
|||
|
||||
const initialValues = useMemo(() => {
|
||||
if (!rec) return null;
|
||||
|
||||
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 screenId = typeof rec.screen === "string" || typeof rec.screen === "number" ? String(rec.screen) : rec.screen?.id ?? null;
|
||||
const photoId = resolveFileId(rec.photo);
|
||||
const screenId = resolveFileId(rec.screen);
|
||||
|
||||
const matId = toId(rec.mat);
|
||||
const coatId = toId(rec.mat_coat);
|
||||
|
|
@ -229,14 +239,33 @@ export default function CO2GalvoDetail({
|
|||
);
|
||||
}
|
||||
|
||||
// VIEW (readable)
|
||||
// VIEW
|
||||
const ownerDisplay = ownerLabel(rec.owner);
|
||||
const canEdit = showOwnerEdit && isMine(rec.owner, meId);
|
||||
|
||||
const photoId = typeof rec.photo === "object" ? rec.photo?.id : (rec.photo as any);
|
||||
const screenId = typeof rec.screen === "object" ? rec.screen?.id : (rec.screen as any);
|
||||
const photoSrc = photoId ? fileUrl(String(photoId)) : "";
|
||||
const screenSrc = screenId ? fileUrl(String(screenId)) : "";
|
||||
const photoSrc = assetSrc(resolveFileId(rec.photo));
|
||||
const screenSrc = assetSrc(resolveFileId(rec.screen));
|
||||
|
||||
// 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 (
|
||||
<div className="space-y-6">
|
||||
|
|
@ -285,18 +314,8 @@ export default function CO2GalvoDetail({
|
|||
</div>
|
||||
|
||||
<div className="grid grid-cols-2 gap-4">
|
||||
{photoSrc ? (
|
||||
<figure className="border rounded overflow-hidden">
|
||||
<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}
|
||||
<Thumb src={photoSrc} alt="Result" />
|
||||
<Thumb src={screenSrc} alt="Settings Screenshot" />
|
||||
</div>
|
||||
</section>
|
||||
|
||||
|
|
@ -406,6 +425,23 @@ export default function CO2GalvoDetail({
|
|||
</div>
|
||||
</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>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue