feat: sort admin sports seasons by status, sport name, then year (#286)
Active seasons sort first, then upcoming, then completed. Within each status group, seasons sort by sport name alphabetically then year ascending. Fixes return type of findAllSportsSeasons to reflect the included sport/participants relations, removing the cast in the loader. Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
68b2e070e6
commit
dc879e3033
3 changed files with 52 additions and 15 deletions
|
|
@ -36,9 +36,9 @@ const pastStart = "2020-01-01";
|
|||
const pastEnd = "2020-12-31";
|
||||
|
||||
const mockSeasons = [
|
||||
{ id: "season-1", name: "2025 NBA Playoffs", draftOn: today, draftOff: future, year: 2025 },
|
||||
{ id: "season-2", name: "2025 F1 Season", draftOn: today, draftOff: future, year: 2025 },
|
||||
{ id: "season-3", name: "2024 Old Golf", draftOn: pastStart, draftOff: pastEnd, year: 2024 },
|
||||
{ id: "season-1", name: "2025 NBA Playoffs", draftOn: today, draftOff: future, year: 2025, status: "upcoming", sport: { name: "NBA" } },
|
||||
{ id: "season-2", name: "2025 F1 Season", draftOn: today, draftOff: future, year: 2025, status: "upcoming", sport: { name: "F1" } },
|
||||
{ id: "season-3", name: "2024 Old Golf", draftOn: pastStart, draftOff: pastEnd, year: 2024, status: "completed", sport: { name: "Golf" } },
|
||||
];
|
||||
|
||||
function makeMockDb(seasons: typeof mockSeasons) {
|
||||
|
|
@ -61,6 +61,39 @@ describe("findAllSportsSeasons", () => {
|
|||
const result = await findAllSportsSeasons();
|
||||
expect(result).toHaveLength(3);
|
||||
});
|
||||
|
||||
it("sorts active before upcoming before completed", async () => {
|
||||
const seasons = [
|
||||
{ id: "s1", name: "Completed", draftOn: pastStart, draftOff: pastEnd, year: 2024, status: "completed", sport: { name: "Sport" } },
|
||||
{ id: "s2", name: "Active", draftOn: today, draftOff: future, year: 2025, status: "active", sport: { name: "Sport" } },
|
||||
{ id: "s3", name: "Upcoming", draftOn: today, draftOff: future, year: 2026, status: "upcoming", sport: { name: "Sport" } },
|
||||
];
|
||||
vi.mocked(database).mockReturnValue(makeMockDb(seasons) as never);
|
||||
const result = await findAllSportsSeasons();
|
||||
expect(result.map((s) => s.status)).toEqual(["active", "upcoming", "completed"]);
|
||||
});
|
||||
|
||||
it("sorts by sport name alphabetically within the same status", async () => {
|
||||
const seasons = [
|
||||
{ id: "s1", name: "Zebra Season", draftOn: today, draftOff: future, year: 2025, status: "active", sport: { name: "Zebra" } },
|
||||
{ id: "s2", name: "Apple Season", draftOn: today, draftOff: future, year: 2025, status: "active", sport: { name: "Apple" } },
|
||||
{ id: "s3", name: "Mango Season", draftOn: today, draftOff: future, year: 2025, status: "active", sport: { name: "Mango" } },
|
||||
];
|
||||
vi.mocked(database).mockReturnValue(makeMockDb(seasons) as never);
|
||||
const result = await findAllSportsSeasons();
|
||||
expect(result.map((s) => s.sport.name)).toEqual(["Apple", "Mango", "Zebra"]);
|
||||
});
|
||||
|
||||
it("sorts by year ascending within the same status and sport name", async () => {
|
||||
const seasons = [
|
||||
{ id: "s1", name: "NFL 2026", draftOn: today, draftOff: future, year: 2026, status: "upcoming", sport: { name: "NFL" } },
|
||||
{ id: "s2", name: "NFL 2024", draftOn: today, draftOff: future, year: 2024, status: "upcoming", sport: { name: "NFL" } },
|
||||
{ id: "s3", name: "NFL 2025", draftOn: today, draftOff: future, year: 2025, status: "upcoming", sport: { name: "NFL" } },
|
||||
];
|
||||
vi.mocked(database).mockReturnValue(makeMockDb(seasons) as never);
|
||||
const result = await findAllSportsSeasons();
|
||||
expect(result.map((s) => s.year)).toEqual([2024, 2025, 2026]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("findDraftableSportsSeasons", () => {
|
||||
|
|
|
|||
|
|
@ -15,6 +15,9 @@ export type NewSportsSeason = typeof schema.sportsSeasons.$inferInsert;
|
|||
export type SportsSeasonWithSport = SportsSeason & {
|
||||
sport: typeof schema.sports.$inferSelect;
|
||||
};
|
||||
export type SportsSeasonListItem = SportsSeasonWithSport & {
|
||||
participants: Array<{ id: string }>;
|
||||
};
|
||||
export type SportsSeasonStatus = "upcoming" | "active" | "completed";
|
||||
export type ScoringType = "playoffs" | "regular_season" | "majors";
|
||||
|
||||
|
|
@ -85,10 +88,9 @@ export async function findSportsSeasonsByStatus(status: SportsSeasonStatus): Pro
|
|||
});
|
||||
}
|
||||
|
||||
export async function findAllSportsSeasons(): Promise<SportsSeason[]> {
|
||||
export async function findAllSportsSeasons(): Promise<SportsSeasonListItem[]> {
|
||||
const db = database();
|
||||
return await db.query.sportsSeasons.findMany({
|
||||
orderBy: (sportsSeasons, { desc, asc }) => [desc(sportsSeasons.year), asc(sportsSeasons.name)],
|
||||
const results = await db.query.sportsSeasons.findMany({
|
||||
with: {
|
||||
sport: true,
|
||||
participants: {
|
||||
|
|
@ -98,6 +100,16 @@ export async function findAllSportsSeasons(): Promise<SportsSeason[]> {
|
|||
},
|
||||
},
|
||||
});
|
||||
|
||||
const statusOrder: Record<SportsSeasonStatus, number> = { active: 0, upcoming: 1, completed: 2 };
|
||||
|
||||
return results.sort((a, b) => {
|
||||
const statusDiff = statusOrder[a.status] - statusOrder[b.status];
|
||||
if (statusDiff !== 0) return statusDiff;
|
||||
const sportNameDiff = a.sport.name.localeCompare(b.sport.name);
|
||||
if (sportNameDiff !== 0) return sportNameDiff;
|
||||
return a.year - b.year;
|
||||
});
|
||||
}
|
||||
|
||||
export async function findDraftableSportsSeasons(): Promise<SportsSeason[]> {
|
||||
|
|
|
|||
|
|
@ -27,15 +27,7 @@ export function meta(): Route.MetaDescriptors {
|
|||
|
||||
export async function loader() {
|
||||
const sportsSeasons = await findAllSportsSeasons();
|
||||
// Type assertion since we know the sport and participants relations are included from the model
|
||||
return {
|
||||
sportsSeasons: sportsSeasons as Array<
|
||||
typeof sportsSeasons[0] & {
|
||||
sport: { id: string; name: string; type: string; slug: string };
|
||||
participants: Array<{ id: string }>;
|
||||
}
|
||||
>
|
||||
};
|
||||
return { sportsSeasons };
|
||||
}
|
||||
|
||||
export default function AdminSportsSeasons({ loaderData }: Route.ComponentProps) {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue