"use client"; import Link from "next/link"; import ZxdbBreadcrumbs from "@/app/zxdb/components/ZxdbBreadcrumbs"; type Label = { id: number; name: string; labeltypeId: string | null }; export type EntryDetailData = { id: number; title: string; isXrated: number; machinetype: { id: number | null; name: string | null }; language: { id: string | null; name: string | null }; genre: { id: number | null; name: string | null }; authors: Label[]; publishers: Label[]; licenses?: { id: number; name: string; type: { id: string; name: string | null }; isOfficial: boolean; linkWikipedia?: string | null; linkSite?: string | null; comments?: string | null; }[]; relations?: { direction: "from" | "to"; type: { id: string; name: string | null }; entry: { id: number; title: string | null }; }[]; tags?: { id: number; name: string; type: { id: string; name: string | null }; category: { id: number | null; name: string | null }; memberSeq: number | null; link: string | null; comments: string | null; }[]; ports?: { id: number; title: string | null; platform: { id: number; name: string | null }; isOfficial: boolean; linkSystem: string | null; }[]; remakes?: { id: number; title: string; fileLink: string; fileDate: string | null; fileSize: number | null; authors: string | null; platforms: string | null; remakeYears: string | null; remakeStatus: string | null; }[]; scores?: { website: { id: number; name: string | null }; score: number; votes: number; }[]; notes?: { id: number; type: { id: string; name: string | null }; text: string; }[]; origins?: { type: { id: string; name: string | null }; libraryTitle: string; publication: string | null; containerId: number | null; issueId: number | null; issue: { id: number; magazineId: number | null; magazineTitle: string | null } | null; date: { year: number | null; month: number | null; day: number | null }; }[]; // extra fields for richer details maxPlayers?: number; availabletypeId?: string | null; withoutLoadScreen?: number; withoutInlay?: number; issueId?: number | null; files?: { id: number; link: string; size: number | null; md5: string | null; comments: string | null; type: { id: number; name: string }; }[]; // Flat downloads by entry_id downloadsFlat?: { id: number; link: string; size: number | null; md5: string | null; comments: string | null; isDemo: boolean; type: { id: number; name: string }; language: { id: string | null; name: string | null }; machinetype: { id: number | null; name: string | null }; scheme: { id: string | null; name: string | null }; source: { id: string | null; name: string | null }; case: { id: string | null; name: string | null }; year: number | null; releaseSeq: number; localLink?: string | null; }[]; releases?: { releaseSeq: number; type: { id: string | null; name: string | null }; language: { id: string | null; name: string | null }; machinetype: { id: number | null; name: string | null }; year: number | null; comments: string | null; downloads: { id: number; link: string; size: number | null; md5: string | null; comments: string | null; isDemo: boolean; type: { id: number; name: string }; language: { id: string | null; name: string | null }; machinetype: { id: number | null; name: string | null }; scheme: { id: string | null; name: string | null }; source: { id: string | null; name: string | null }; case: { id: string | null; name: string | null }; year: number | null; localLink?: string | null; }[]; }[]; // Additional relationships aliases?: { releaseSeq: number; languageId: string; title: string }[]; webrefs?: { link: string; languageId: string; website: { id: number; name: string; link?: string | null } }[]; magazineRefs?: { id: number; issueId: number; magazineId: number | null; magazineName: string | null; referencetypeId: number; referencetypeName: string | null; page: number; isOriginal: number; scoreGroup: string; issue: { dateYear: number | null; dateMonth: number | null; dateDay: number | null; volume: number | null; number: number | null; special: string | null; supplement: string | null; }; }[]; }; export default function EntryDetailClient({ data }: { data: EntryDetailData | null }) { if (!data) return
Not found
; return (

{data.title}

{data.genre.name && ( {data.genre.name} )} {data.language.name && ( {data.language.name} )} {data.machinetype.name && ( {data.machinetype.name} )} {data.isXrated ? 18+ : null}
Entry Summary
{typeof data.maxPlayers !== "undefined" && ( )} {typeof data.availabletypeId !== "undefined" && ( )} {typeof data.withoutLoadScreen !== "undefined" && ( )} {typeof data.withoutInlay !== "undefined" && ( )} {typeof data.issueId !== "undefined" && ( )}
ID {data.id}
Title {data.title}
Machine {data.machinetype.id != null ? ( data.machinetype.name ? ( {data.machinetype.name} ) : ( #{data.machinetype.id} ) ) : ( - )}
Language {data.language.id ? ( data.language.name ? ( {data.language.name} ) : ( {data.language.id} ) ) : ( - )}
Genre {data.genre.id ? ( data.genre.name ? ( {data.genre.name} ) : ( #{data.genre.id} ) ) : ( - )}
Max Players {data.maxPlayers}
Available Type {data.availabletypeId ?? -}
Without Load Screen {data.withoutLoadScreen ? "Yes" : "No"}
Without Inlay {data.withoutInlay ? "Yes" : "No"}
Issue {data.issueId ? #{data.issueId} : -}
People
Authors
{data.authors.length === 0 &&
Unknown
} {data.authors.length > 0 && (
    {data.authors.map((a) => (
  • {a.name}
  • ))}
)}
Publishers
{data.publishers.length === 0 &&
Unknown
} {data.publishers.length > 0 && (
    {data.publishers.map((p) => (
  • {p.name}
  • ))}
)}
Magazine References
{(!data.magazineRefs || data.magazineRefs.length === 0) &&
No magazine references recorded
} {data.magazineRefs && data.magazineRefs.length > 0 && (
{data.magazineRefs.map((m) => ( ))}
Magazine Issue Type Page Score
{m.magazineId ? ( {m.magazineName} ) : ( {m.magazineName} )} {m.issue.dateYear ? `${m.issue.dateYear} ` : ""} {m.issue.number ? `#${m.issue.number}` : ""} {m.issue.special ? ` (${m.issue.special})` : ""} {m.referencetypeName} {m.page > 0 ? m.page : "-"} {m.scoreGroup || "-"}
)}
Permalink Back to Explorer
Downloads
{(!data.downloadsFlat || data.downloadsFlat.length === 0) &&
No downloads
} {data.downloadsFlat && data.downloadsFlat.length > 0 && (
{data.downloadsFlat.map((d) => { const isHttp = d.link.startsWith("http://") || d.link.startsWith("https://"); return ( ); })}
Type Link Size MD5 Flags Details Comments
{d.type.name}
{isHttp ? ( {d.link} ) : ( {d.link} )} {d.localLink && ( Local Mirror )}
{typeof d.size === "number" ? d.size.toLocaleString() : "-"} {d.md5 ?? "-"}
{d.isDemo ? Demo : null} {d.scheme.name ? {d.scheme.name} : null} {d.source.name ? {d.source.name} : null} {d.case.name ? {d.case.name} : null}
{d.language.name && ( {d.language.name} )} {d.machinetype.name && ( {d.machinetype.name} )} {typeof d.year === "number" ? {d.year} : null} rel #{d.releaseSeq}
{d.comments ?? ""}
)}
Releases
{(!data.releases || data.releases.length === 0) &&
No releases recorded
} {data.releases && data.releases.length > 0 && (
{data.releases.map((r) => ( ))}
Release # Year Downloads
#{r.releaseSeq} {r.year ?? -} {r.downloads.length}
)}
Origins
{(!data.origins || data.origins.length === 0) &&
No origins recorded
} {data.origins && data.origins.length > 0 && (
{data.origins.map((o, idx) => { const dateParts = [o.date.year, o.date.month, o.date.day] .filter((v) => typeof v === "number" && Number.isFinite(v)) .map((v, i) => (i === 0 ? String(v) : String(v).padStart(2, "0"))); const dateText = dateParts.length ? dateParts.join("/") : "-"; return ( ); })}
Type Title Publication Issue Date
{o.type.name ?? o.type.id} {o.libraryTitle} {o.publication ?? -} {o.issue ? (
Issue #{o.issue.id} {o.issue.magazineId != null && ( {o.issue.magazineTitle ?? `Magazine #${o.issue.magazineId}`} )}
) : o.containerId ? ( Container #{o.containerId} ) : ( - )}
{dateText}
)}
Relations
{(!data.relations || data.relations.length === 0) &&
No relations recorded
} {data.relations && data.relations.length > 0 && (
{data.relations.map((r, idx) => ( ))}
Direction Type Entry
{r.direction === "from" ? "From" : "To"} {r.type.name ?? r.type.id} {r.entry.title ?? `Entry #${r.entry.id}`}
)}
Tags / Members
{(!data.tags || data.tags.length === 0) &&
No tags recorded
} {data.tags && data.tags.length > 0 && (
{data.tags.map((t) => ( ))}
Tag Type Category Member Seq Links
{t.name} {t.type.name ?? t.type.id} {t.category.name ?? (t.category.id != null ? `#${t.category.id}` : "-")} {t.memberSeq ?? -}
{t.link && ( Link )} {t.comments && {t.comments}} {!t.link && !t.comments && -}
)}
Ports
{(!data.ports || data.ports.length === 0) &&
No ports recorded
} {data.ports && data.ports.length > 0 && (
{data.ports.map((p) => ( ))}
Title Platform Official Link
{p.title ?? -} {p.platform.name ?? `#${p.platform.id}`} {p.isOfficial ? "Yes" : "No"} {p.linkSystem ? ( Link ) : ( - )}
)}
Remakes
{(!data.remakes || data.remakes.length === 0) &&
No remakes recorded
} {data.remakes && data.remakes.length > 0 && (
{data.remakes.map((r) => ( ))}
Title Platforms Years File Notes
{r.title} {r.platforms ?? -} {r.remakeYears ?? -} {r.fileLink ? ( File ) : ( - )} {r.remakeStatus ?? r.authors ?? -}
)}
Scores
{(!data.scores || data.scores.length === 0) &&
No scores recorded
} {data.scores && data.scores.length > 0 && (
{data.scores.map((s, idx) => ( ))}
Website Score Votes
{s.website.name ?? `#${s.website.id}`} {s.score} {s.votes}
)}
Notes
{(!data.notes || data.notes.length === 0) &&
No notes recorded
} {data.notes && data.notes.length > 0 && (
{data.notes.map((n) => ( ))}
Type Text
{n.type.name ?? n.type.id} {n.text}
)}
Aliases
{(!data.aliases || data.aliases.length === 0) &&
No aliases
} {data.aliases && data.aliases.length > 0 && (
{data.aliases.map((a, idx) => ( ))}
Release # Language Title
#{a.releaseSeq} {a.languageId} {a.title}
)}
Licenses
{(!data.licenses || data.licenses.length === 0) &&
No licenses linked
} {data.licenses && data.licenses.length > 0 && (
{data.licenses.map((l) => ( ))}
Name Type Official Links
{l.name} {l.type.name ?? l.type.id} {l.isOfficial ? "Yes" : "No"}
{l.linkWikipedia && ( Wikipedia )} {l.linkSite && ( Site )} {!l.linkWikipedia && !l.linkSite && -}
)}
Web links
{(!data.webrefs || data.webrefs.length === 0) &&
No web links
} {data.webrefs && data.webrefs.length > 0 && (
{data.webrefs.map((w, idx) => ( ))}
Website Language URL
{w.website.link ? ( {w.website.name} ) : ( {w.website.name} )} {w.languageId} {w.link}
)}
Files
{(!data.files || data.files.length === 0) &&
No files linked
} {data.files && data.files.length > 0 && (
{data.files.map((f) => { const isHttp = f.link.startsWith("http://") || f.link.startsWith("https://"); return ( ); })}
Type Link Size MD5 Comments
{f.type.name} {isHttp ? ( {f.link} ) : ( {f.link} )} {f.size != null ? new Intl.NumberFormat().format(f.size) : "-"} {f.md5 ?? "-"} {f.comments ?? ""}
)}
); }