songs page init

This commit is contained in:
2026-02-06 08:20:42 -08:00
parent 323c7c7f77
commit 0531a1f5c0
5 changed files with 520 additions and 1 deletions

78
src/routes/songs/+page.ts Normal file
View File

@@ -0,0 +1,78 @@
import { z } from "zod";
import type { SongFilters } from "$lib/db/client-db";
import { db, ensureSeeded, getSongsWithFilters } from "$lib/db/client-db";
import {
SongCategoryMap,
SongTypeMap,
SongTypeReverseMap,
} from "$lib/utils/amq";
import type { PageLoad } from "./$types";
const SearchSchema = z
.object({
q: z.string().optional(), // song name
artist: z.string().optional(), // artist name
anime: z.string().optional(), // anime mainName
type: z
.string()
.optional()
.transform((s) => {
if (!s) return undefined;
return s
.split(",")
.map((t) => SongTypeMap[t.trim().toUpperCase()])
.filter((n) => n !== undefined);
}),
gpm: z
.string()
.optional()
.transform((s) => (s ? parseInt(s, 10) : undefined)), // global percent min
gpx: z
.string()
.optional()
.transform((s) => (s ? parseInt(s, 10) : undefined)), // global percent max
cat: z
.string()
.optional()
.transform((s) => (s ? parseInt(s, 10) : undefined)), // category
})
.strict();
export const load: PageLoad = async ({ url, fetch, depends }) => {
depends("clientdb:songs");
const parsed = SearchSchema.safeParse(
Object.fromEntries(url.searchParams.entries()),
);
const filters: SongFilters = {};
if (parsed.success) {
if (parsed.data.q) filters.songName = parsed.data.q;
if (parsed.data.artist) filters.artistName = parsed.data.artist;
if (parsed.data.anime) filters.animeName = parsed.data.anime;
if (parsed.data.type && parsed.data.type.length > 0)
filters.songTypes = parsed.data.type;
if (parsed.data.gpm !== undefined)
filters.globalPercentMin = parsed.data.gpm;
if (parsed.data.gpx !== undefined)
filters.globalPercentMax = parsed.data.gpx;
if (parsed.data.cat !== undefined) filters.category = parsed.data.cat;
}
// Client-only DB: on the server `db` is null, so return [] and let hydration re-run load in browser.
if (!db) {
return {
filters: parsed.success ? parsed.data : {}, // Return original parsed data for form state
songRows: [],
};
}
await ensureSeeded({ fetch });
const songRows = await getSongsWithFilters(db, filters);
return {
filters: parsed.success ? parsed.data : {}, // Return original parsed data for form state
songRows,
};
};