Release 0.4.0

This commit is contained in:
hnzio committed 2026-10-21 23:52:05 +02:00
1 parent 7590be66a5
commit 4042fe6a64
24 files changed
+3570 -290

No files matched your search

+49 -94
View File
@@ -1,4 +1,5 @@
import { getDatabase } from './database.js';
import { getShow as getShowById, listShows } from './shows.js';
export type PreviewPiece = {
id: string;
@@ -104,109 +105,63 @@ export function getPieces(): PreviewPiece[] {
}));
}
type ShowRow = {
id: string;
title: string;
starts_at_utc: string;
twitch_title: string;
announcement_text: string;
status: string;
};
type SectionRow = {
id: string;
name: string;
category: string | null;
category_color: string | null;
explicit_duration_seconds: number | null;
};
type UsageRow = {
id: string;
show_section_id: string;
title_snapshot: string;
duration_seconds: number;
status: PreviewUsage['status'];
intro_snapshot: string;
moderation_snapshot: string;
transition_snapshot: string;
is_reserve: number;
};
export function getShow(): PreviewShow {
const database = getDatabase();
const show = database
.prepare(
`SELECT id, title, starts_at_utc, twitch_title, announcement_text, status
FROM shows ORDER BY starts_at_utc DESC LIMIT 1`
)
.get() as ShowRow | undefined;
export function getShow(showId?: string): PreviewShow {
const latest = showId ? null : listShows().find((show) => show.startsAtUtc !== null);
const show = getShowById(showId ?? latest?.id ?? '');
if (!show) throw new Error('No preview show found. Run npm run db:seed.');
const sectionRows = database
.prepare(
`SELECT s.id, s.name, c.name AS category, c.color AS category_color,
s.explicit_duration_seconds
FROM show_sections s
LEFT JOIN section_categories c ON c.id = s.category_id
WHERE s.show_id = ? ORDER BY s.position`
)
.all(show.id) as SectionRow[];
const usageRows = database
.prepare(
`SELECT id, show_section_id, title_snapshot, duration_seconds, status,
intro_snapshot, moderation_snapshot, transition_snapshot, is_reserve
FROM piece_usages WHERE show_section_id IN (
SELECT id FROM show_sections WHERE show_id = ?
) ORDER BY position`
)
.all(show.id) as UsageRow[];
const sections = sectionRows.map((section) => {
const usages = usageRows
.filter((usage) => usage.show_section_id === section.id)
.map((usage) => ({
const sections: PreviewSection[] = show.sections.map((section) => ({
id: section.id,
name: section.name,
category: section.category ?? 'Offen',
categoryColor: section.categoryColor ?? '#8b8f98',
durationSeconds: section.durationSeconds,
usages: section.usages.map((usage) => ({
id: usage.id,
title: usage.title,
durationSeconds: usage.durationSeconds,
status: usage.status,
intro: usage.intro,
moderation: usage.moderation,
transition: usage.transition,
isReserve: false
}))
}));
const reserveHost = sections[Math.min(1, sections.length - 1)];
if (reserveHost) {
reserveHost.usages.push(
...show.reserve.map((usage) => ({
id: usage.id,
title: usage.title_snapshot,
durationSeconds: usage.duration_seconds,
title: usage.title,
durationSeconds: usage.durationSeconds,
status: usage.status,
intro: usage.intro_snapshot,
moderation: usage.moderation_snapshot,
transition: usage.transition_snapshot,
isReserve: usage.is_reserve === 1
}));
const plannedUsages = usages.filter((usage) => !usage.isReserve);
return {
id: section.id,
name: section.name,
category: section.category ?? 'Offen',
categoryColor: section.category_color ?? '#8b8f98',
durationSeconds:
section.explicit_duration_seconds ??
plannedUsages.reduce((total, usage) => total + usage.durationSeconds, 0),
usages
};
});
intro: usage.intro,
moderation: usage.moderation,
transition: usage.transition,
isReserve: true
}))
);
}
return {
id: show.id,
title: show.title,
startsAtUtc: show.starts_at_utc,
startsAtBerlin: new Intl.DateTimeFormat('de-DE', {
timeZone: 'Europe/Berlin',
weekday: 'short',
day: '2-digit',
month: '2-digit',
year: 'numeric',
hour: '2-digit',
minute: '2-digit'
}).format(new Date(show.starts_at_utc)),
twitchTitle: show.twitch_title,
announcement: show.announcement_text,
startsAtUtc: show.startsAtUtc ?? '',
startsAtBerlin: show.startsAtUtc
? new Intl.DateTimeFormat('de-DE', {
timeZone: 'Europe/Berlin',
weekday: 'short',
day: '2-digit',
month: '2-digit',
year: 'numeric',
hour: '2-digit',
minute: '2-digit'
}).format(new Date(show.startsAtUtc))
: 'Termin offen',
twitchTitle: show.twitchTitle,
announcement: show.announcementText,
status: show.status,
sections,
totalDurationSeconds: sections.reduce((total, section) => total + section.durationSeconds, 0)
totalDurationSeconds: show.totalDurationSeconds
};
}