Add movies & TV tracker: movies schema, Netflix/Letterboxd/Plex/JSON/recs importers, TMDB matching, stats, owner visibility

This commit is contained in:
2026-10-26 00:31:23 +00:00
parent 75571bbfe0
commit 71e015d1d0
28 changed files with 42754 additions and 14 deletions

View File

@@ -10,5 +10,9 @@
<p class="mb-10 text-[var(--site-muted)]">
Personal data I keep track of: games, money, houses, books, prices, animals and lists.
</p>
<CatalogGrid items={visibleTrackers(data.isOwner, data.inactiveGames)} variant="tracker" wide />
<CatalogGrid
items={visibleTrackers(data.isOwner, data.inactiveGames, data.hiddenTrackers)}
variant="tracker"
wide
/>
</div>

View File

@@ -0,0 +1,52 @@
import { error, fail } from '@sveltejs/kit';
import { isOwner, requireOwner } from '#lib/server/owner.js';
import {
addTitle,
deleteRec,
deleteTitle,
getVisibility,
loadRecs,
loadStats,
loadTitles,
setVisibility,
updateTitle
} from '#lib/server/movies/site.js';
import type { Actions, PageServerLoad } from './$types';
// Movies & TV: public by default; the owner's visibility switch can make it owner-only.
export const load: PageServerLoad = async (event) => {
const owner = isOwner(event);
const visibility = await getVisibility();
if (visibility === 'private' && !owner) error(404, 'Not found');
if (owner) event.setHeaders({ 'cache-control': 'private, no-store' });
const [titles, stats, recs] = await Promise.all([loadTitles(), loadStats(), loadRecs()]);
return {
owner,
visibility,
titles,
stats,
recs,
seo: {
title: 'Movies & TV tracker',
description:
'The movies and TV shows we watch: what we are watching, ratings, rewatches and stats per month, genre and platform.'
}
};
};
type Result = { ok: true; id?: number } | { ok: false; message: string };
const run =
(fn: (form: FormData) => Promise<Result>) => async (event: Parameters<Actions[string]>[0]) => {
requireOwner(event);
const res = await fn(await event.request.formData());
if (!res.ok) return fail(400, { message: res.message });
return res;
};
export const actions: Actions = {
update: run(updateTitle),
add: run(addTitle),
delete: run(deleteTitle),
deleteRec: run(deleteRec),
visibility: run(setVisibility)
};

File diff suppressed because it is too large Load Diff