diff --git a/app/admin/page.tsx b/app/admin/page.tsx index cf6addd..5dece73 100644 --- a/app/admin/page.tsx +++ b/app/admin/page.tsx @@ -21,6 +21,7 @@ interface Genre { id: number; name: string; subtitle?: string; + active: boolean; _count?: { songs: number; }; @@ -66,9 +67,11 @@ export default function AdminPage() { const [genres, setGenres] = useState([]); const [newGenreName, setNewGenreName] = useState(''); const [newGenreSubtitle, setNewGenreSubtitle] = useState(''); + const [newGenreActive, setNewGenreActive] = useState(true); const [editingGenreId, setEditingGenreId] = useState(null); const [editGenreName, setEditGenreName] = useState(''); const [editGenreSubtitle, setEditGenreSubtitle] = useState(''); + const [editGenreActive, setEditGenreActive] = useState(true); // Specials state const [specials, setSpecials] = useState([]); @@ -200,11 +203,16 @@ export default function AdminPage() { const res = await fetch('/api/genres', { method: 'POST', headers: getAuthHeaders(), - body: JSON.stringify({ name: newGenreName, subtitle: newGenreSubtitle }), + body: JSON.stringify({ + name: newGenreName, + subtitle: newGenreSubtitle, + active: newGenreActive + }), }); if (res.ok) { setNewGenreName(''); setNewGenreSubtitle(''); + setNewGenreActive(true); fetchGenres(); } else { alert('Failed to create genre'); @@ -215,6 +223,7 @@ export default function AdminPage() { setEditingGenreId(genre.id); setEditGenreName(genre.name); setEditGenreSubtitle(genre.subtitle || ''); + setEditGenreActive(genre.active !== undefined ? genre.active : true); }; const saveEditedGenre = async () => { @@ -225,7 +234,8 @@ export default function AdminPage() { body: JSON.stringify({ id: editingGenreId, name: editGenreName, - subtitle: editGenreSubtitle + subtitle: editGenreSubtitle, + active: editGenreActive }), }); if (res.ok) { @@ -978,7 +988,7 @@ export default function AdminPage() { {/* Genre Management */}

Manage Genres

-
+
+
{genres.map(genre => (
Subtitle setEditGenreSubtitle(e.target.value)} className="form-input" style={{ width: '300px' }} />
+
+ +
diff --git a/app/api/genres/route.ts b/app/api/genres/route.ts index c80145f..cc47664 100644 --- a/app/api/genres/route.ts +++ b/app/api/genres/route.ts @@ -27,7 +27,7 @@ export async function POST(request: Request) { if (authError) return authError; try { - const { name, subtitle } = await request.json(); + const { name, subtitle, active } = await request.json(); if (!name || typeof name !== 'string') { return NextResponse.json({ error: 'Invalid name' }, { status: 400 }); @@ -36,7 +36,8 @@ export async function POST(request: Request) { const genre = await prisma.genre.create({ data: { name: name.trim(), - subtitle: subtitle ? subtitle.trim() : null + subtitle: subtitle ? subtitle.trim() : null, + active: active !== undefined ? active : true }, }); @@ -76,7 +77,7 @@ export async function PUT(request: Request) { if (authError) return authError; try { - const { id, name, subtitle } = await request.json(); + const { id, name, subtitle, active } = await request.json(); if (!id) { return NextResponse.json({ error: 'Missing id' }, { status: 400 }); @@ -86,7 +87,8 @@ export async function PUT(request: Request) { where: { id: Number(id) }, data: { ...(name && { name: name.trim() }), - subtitle: subtitle ? subtitle.trim() : null // Allow clearing subtitle if empty string passed? Or just update if provided? Let's assume null/empty string clears it. + subtitle: subtitle ? subtitle.trim() : null, + ...(active !== undefined && { active }) }, }); diff --git a/app/page.tsx b/app/page.tsx index 056e451..d52748a 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -9,7 +9,10 @@ const prisma = new PrismaClient(); export default async function Home() { const dailyPuzzle = await getOrCreateDailyPuzzle(null); // Global puzzle - const genres = await prisma.genre.findMany({ orderBy: { name: 'asc' } }); + const genres = await prisma.genre.findMany({ + where: { active: true }, + orderBy: { name: 'asc' } + }); const specials = await prisma.special.findMany({ orderBy: { name: 'asc' } }); const now = new Date(); diff --git a/prisma/migrations/20251124231438_add_genre_active_field/migration.sql b/prisma/migrations/20251124231438_add_genre_active_field/migration.sql new file mode 100644 index 0000000..6a8dd5e --- /dev/null +++ b/prisma/migrations/20251124231438_add_genre_active_field/migration.sql @@ -0,0 +1,15 @@ +-- RedefineTables +PRAGMA defer_foreign_keys=ON; +PRAGMA foreign_keys=OFF; +CREATE TABLE "new_Genre" ( + "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, + "name" TEXT NOT NULL, + "subtitle" TEXT, + "active" BOOLEAN NOT NULL DEFAULT true +); +INSERT INTO "new_Genre" ("id", "name", "subtitle") SELECT "id", "name", "subtitle" FROM "Genre"; +DROP TABLE "Genre"; +ALTER TABLE "new_Genre" RENAME TO "Genre"; +CREATE UNIQUE INDEX "Genre_name_key" ON "Genre"("name"); +PRAGMA foreign_keys=ON; +PRAGMA defer_foreign_keys=OFF; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 6b398c2..c3ba97b 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -30,6 +30,7 @@ model Genre { id Int @id @default(autoincrement()) name String @unique subtitle String? + active Boolean @default(true) songs Song[] dailyPuzzles DailyPuzzle[] }