diff --git a/app/models/league.server.ts b/app/models/league.server.ts index 1e50fbf..ff5b17e 100644 --- a/app/models/league.server.ts +++ b/app/models/league.server.ts @@ -82,6 +82,21 @@ export async function getLeaguesByYear(year: League['year']) { }); } +export async function getLeagueCountsByYear() { + return prisma.league.groupBy({ + by: ['year'], + _count: { _all: true }, + }); +} + +export async function getLeagueCountForYear(year: League['year']) { + return prisma.league.count({ + where: { + year, + }, + }); +} + export async function updateLeague(league: Partial) { return prisma.league.update({ where: { diff --git a/app/models/season.server.ts b/app/models/season.server.ts index 9f094bf..0fc65e2 100644 --- a/app/models/season.server.ts +++ b/app/models/season.server.ts @@ -54,6 +54,14 @@ export async function updateSeason(season: Partial) { }); } +export async function deleteSeason(id: Season['id']) { + return prisma.season.delete({ + where: { + id, + }, + }); +} + export async function updateActiveSeason(id: Season['id']) { return prisma.$transaction([ prisma.season.updateMany({ diff --git a/app/routes/admin.season._index.tsx b/app/routes/admin.season._index.tsx index ba78623..0f6b476 100644 --- a/app/routes/admin.season._index.tsx +++ b/app/routes/admin.season._index.tsx @@ -7,8 +7,14 @@ import { } from 'remix-typedjson'; import Alert from '~/components/ui/Alert'; import Button from '~/components/ui/FlexSpotButton'; +import { + getLeagueCountForYear, + getLeagueCountsByYear, +} from '~/models/league.server'; import { createSeason, + deleteSeason, + getSeasonById, getSeasons, updateActiveSeason, updateSeason, @@ -30,8 +36,7 @@ export const action = async ({ request }: ActionFunctionArgs) => { switch (action) { case 'createSeason': { - //const year = new Date().getFullYear(); - const year = new Date('2024-04-01').getFullYear(); + const year = new Date().getFullYear(); const season = await createSeason({ year, isCurrent: false, @@ -45,6 +50,36 @@ export const action = async ({ request }: ActionFunctionArgs) => { message: `${season.year} season has been created`, }); } + case 'deleteSeason': { + const seasonId = formData.get('seasonId'); + if (typeof seasonId !== 'string') { + throw new Error(`Form not generated correctly.`); + } + + const season = await getSeasonById(seasonId); + if (!season) { + return typedjson({ message: 'Season not found.' }); + } + + if (season.isCurrent) { + return typedjson({ + message: `Cannot delete the active season.`, + }); + } + + const leagueCount = await getLeagueCountForYear(season.year); + if (leagueCount > 0) { + return typedjson({ + message: `Cannot delete a season that has leagues attached.`, + }); + } + + await deleteSeason(seasonId); + + return typedjson({ + message: `${season.year} season has been deleted`, + }); + } case 'setActive': { const seasonId = formData.get('seasonId'); if (typeof seasonId !== 'string') { @@ -123,11 +158,17 @@ export const loader = async ({ request }: LoaderFunctionArgs) => { const seasons = await getSeasons(); - return typedjson({ seasons }); + const leagueCounts = await getLeagueCountsByYear(); + const leagueCountsByYear: Record = {}; + for (const { year, _count } of leagueCounts) { + leagueCountsByYear[year] = _count._all; + } + + return typedjson({ seasons, leagueCountsByYear }); }; export default function SeasonIndex() { - const { seasons } = useTypedLoaderData(); + const { seasons, leagueCountsByYear } = useTypedLoaderData(); const actionData = useTypedActionData(); const navigation = useNavigation(); @@ -139,6 +180,7 @@ export default function SeasonIndex() { Year + Leagues Active? Open Registration? Open F²? @@ -157,9 +199,12 @@ export default function SeasonIndex() { isOpenForDFSSurvivor, } = season; + const leagueCount = leagueCountsByYear[year] ?? 0; + return ( {year} + {leagueCount} {isCurrent ? 'Yes' : 'No'} {isOpenForRegistration ? 'Yes' : 'No'} {isOpenForFSquared ? 'Yes' : 'No'} @@ -173,6 +218,27 @@ export default function SeasonIndex() { )} + {!isCurrent && leagueCount === 0 && ( +
+ + +
+ )} {isCurrent && ( <>