diff --git a/src/app/zxdb/entries/[id]/EntryDetail.tsx b/src/app/zxdb/entries/[id]/EntryDetail.tsx index f6b685a..50e9348 100644 --- a/src/app/zxdb/entries/[id]/EntryDetail.tsx +++ b/src/app/zxdb/entries/[id]/EntryDetail.tsx @@ -22,6 +22,14 @@ export type EntryDetailData = { linkSite?: string | null; comments?: string | null; }[]; + origins?: { + type: { id: string; name: string | null }; + libraryTitle: string; + publication: string | null; + containerId: number | null; + issueId: number | null; + date: { year: number | null; month: number | null; day: number | null }; + }[]; // extra fields for richer details maxPlayers?: number; availabletypeId?: string | null; @@ -340,6 +348,53 @@ export default function EntryDetailClient({ data }: { data: EntryDetailData | nu
+
+
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 ( + + + + + + + + ); + })} + +
TypeTitlePublicationIssueDate
{o.type.name ?? o.type.id}{o.libraryTitle}{o.publication ?? -} + {o.issueId ? ( + #{o.issueId} + ) : o.containerId ? ( + #{o.containerId} + ) : ( + - + )} + {dateText}
+
+ )} +
+ +
+ {/* Aliases (alternative titles) */}
Aliases
diff --git a/src/app/zxdb/labels/[id]/LabelDetail.tsx b/src/app/zxdb/labels/[id]/LabelDetail.tsx index bc95b70..9f71d4d 100644 --- a/src/app/zxdb/labels/[id]/LabelDetail.tsx +++ b/src/app/zxdb/labels/[id]/LabelDetail.tsx @@ -9,6 +9,7 @@ type Label = { id: number; name: string; labeltypeId: string | null; + labeltypeName: string | null; permissions: { website: { id: number; name: string; link?: string | null }; type: { id: string; name: string | null }; @@ -49,7 +50,11 @@ export default function LabelDetailClient({ id, initial, initialTab, initialQ }:

{initial.label.name}

- {initial.label.labeltypeId ?? "?"} + + {initial.label.labeltypeName + ? `${initial.label.labeltypeName} (${initial.label.labeltypeId ?? "?"})` + : (initial.label.labeltypeId ?? "?")} +
diff --git a/src/server/repo/zxdb.ts b/src/server/repo/zxdb.ts index ab2e8c2..6fe6e3a 100644 --- a/src/server/repo/zxdb.ts +++ b/src/server/repo/zxdb.ts @@ -8,6 +8,7 @@ import { searchByAliases, searchByOrigins, labels, + labeltypes, authors, publishers, languages, @@ -31,6 +32,7 @@ import { licensors, permissions, permissiontypes, + origintypes, webrefs, websites, magazines, @@ -297,6 +299,14 @@ export interface EntryDetail { linkSite?: string | null; comments?: string | null; }[]; + origins?: { + type: { id: string; name: string | null }; + libraryTitle: string; + publication: string | null; + containerId: number | null; + issueId: number | null; + date: { year: number | null; month: number | null; day: number | null }; + }[]; // Additional entry fields for richer details maxPlayers?: number; availabletypeId?: string | null; @@ -559,6 +569,17 @@ export async function getEntryById(id: number): Promise { linkSite: string | null; comments: string | null; }[] = []; + let originRows: { + libraryTitle: string; + origintypeId: string; + origintypeName: string | null; + containerId: number | string | null; + issueId: number | string | null; + dateYear: number | string | null; + dateMonth: number | string | null; + dateDay: number | string | null; + publication: string | null; + }[] = []; try { aliasRows = await db .select({ releaseSeq: aliases.releaseSeq, languageId: aliases.languageId, title: aliases.title }) @@ -591,6 +612,24 @@ export async function getEntryById(id: number): Promise { .where(eq(relatedlicenses.entryId, id)); licenseRows = rows as typeof licenseRows; } catch {} + try { + const rows = await db + .select({ + libraryTitle: searchByOrigins.libraryTitle, + origintypeId: searchByOrigins.origintypeId, + origintypeName: origintypes.name, + containerId: searchByOrigins.containerId, + issueId: searchByOrigins.issueId, + dateYear: searchByOrigins.dateYear, + dateMonth: searchByOrigins.dateMonth, + dateDay: searchByOrigins.dateDay, + publication: searchByOrigins.publication, + }) + .from(searchByOrigins) + .leftJoin(origintypes, eq(origintypes.id, searchByOrigins.origintypeId)) + .where(eq(searchByOrigins.entryId, id)); + originRows = rows as typeof originRows; + } catch {} return { id: base.id, @@ -610,6 +649,18 @@ export async function getEntryById(id: number): Promise { linkSite: l.linkSite ?? null, comments: l.comments ?? null, })), + origins: originRows.map((o) => ({ + type: { id: o.origintypeId, name: o.origintypeName ?? null }, + libraryTitle: o.libraryTitle, + publication: o.publication ?? null, + containerId: o.containerId != null ? Number(o.containerId) : null, + issueId: o.issueId != null ? Number(o.issueId) : null, + date: { + year: o.dateYear != null ? Number(o.dateYear) : null, + month: o.dateMonth != null ? Number(o.dateMonth) : null, + day: o.dateDay != null ? Number(o.dateDay) : null, + }, + })), maxPlayers: (base.maxPlayers) ?? undefined, availabletypeId: (base.availabletypeId) ?? undefined, withoutLoadScreen: (base.withoutLoadScreen) ?? undefined, @@ -651,6 +702,7 @@ export async function getEntryById(id: number): Promise { // ----- Labels ----- export interface LabelDetail extends LabelSummary { + labeltypeName: string | null; permissions: { website: { id: number; name: string; link?: string | null }; type: { id: string; name: string | null }; @@ -709,7 +761,17 @@ export async function searchLabels(params: LabelSearchParams): Promise { - const rows = await db.select().from(labels).where(eq(labels.id, id)).limit(1); + const rows = await db + .select({ + id: labels.id, + name: labels.name, + labeltypeId: labels.labeltypeId, + labeltypeName: labeltypes.name, + }) + .from(labels) + .leftJoin(labeltypes, eq(labeltypes.id, labels.labeltypeId)) + .where(eq(labels.id, id)) + .limit(1); const base = rows[0]; if (!base) return null; @@ -770,6 +832,7 @@ export async function getLabelById(id: number): Promise { id: base.id, name: base.name, labeltypeId: base.labeltypeId, + labeltypeName: base.labeltypeName ?? null, permissions: permissionRows.map((p) => ({ website: { id: Number(p.websiteId), name: p.websiteName, link: p.websiteLink ?? null }, type: { id: p.permissiontypeId, name: p.permissiontypeName ?? null },