Include commissioner leagues in user's active leagues (#8)

* Show leagues where user is a member regardless of team assignment

The homepage now uses a union query to show leagues where the user
either has a team in the current season OR is a commissioner. Previously,
commissioners without a team could not see their leagues on the homepage.

https://claude.ai/code/session_01E3ugKTfatkEc5TcDGXvHiW

* Fix stale empty state card title in home route

Update 'No Active Leagues' to 'No Leagues' to match the updated
description which is now about membership rather than active seasons.

https://claude.ai/code/session_01E3ugKTfatkEc5TcDGXvHiW

* Fix union import: use two queries with JS deduplication

drizzle-orm 0.36.x does not export a standalone union() function.
Replace with two awaited queries merged via a Map (dedup by id),
then sorted by createdAt descending in JS.

https://claude.ai/code/session_01E3ugKTfatkEc5TcDGXvHiW

---------

Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
Chris Parsons 2026-02-20 10:28:37 -08:00 committed by GitHub
parent 8c9b131c00
commit 47b69ce9cf
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 31 additions and 16 deletions

View file

@ -71,23 +71,38 @@ export async function findLeaguesWithActiveSeasonsByUserId(
): Promise<League[]> {
const db = database();
// Query to find all leagues where user has a team in the current season
const leagues = await db
.selectDistinct({
id: schema.leagues.id,
name: schema.leagues.name,
createdBy: schema.leagues.createdBy,
currentSeasonId: schema.leagues.currentSeasonId,
isPublicDraftBoard: schema.leagues.isPublicDraftBoard,
createdAt: schema.leagues.createdAt,
updatedAt: schema.leagues.updatedAt,
})
const leagueFields = {
id: schema.leagues.id,
name: schema.leagues.name,
createdBy: schema.leagues.createdBy,
currentSeasonId: schema.leagues.currentSeasonId,
isPublicDraftBoard: schema.leagues.isPublicDraftBoard,
createdAt: schema.leagues.createdAt,
updatedAt: schema.leagues.updatedAt,
};
// Leagues where user has a team in the current season
const leaguesWithTeam = await db
.select(leagueFields)
.from(schema.leagues)
.innerJoin(schema.teams, eq(schema.teams.seasonId, schema.leagues.currentSeasonId))
.where(eq(schema.teams.ownerId, userId))
.orderBy(desc(schema.leagues.createdAt));
.where(eq(schema.teams.ownerId, userId));
return leagues;
// Leagues where user is a commissioner (with or without a team)
const leaguesAsCommissioner = await db
.select(leagueFields)
.from(schema.leagues)
.innerJoin(schema.commissioners, eq(schema.commissioners.leagueId, schema.leagues.id))
.where(eq(schema.commissioners.userId, userId));
// Deduplicate by id in case user is both a commissioner and has a team, then sort
const leagueMap = new Map<string, League>();
for (const league of [...leaguesWithTeam, ...leaguesAsCommissioner]) {
leagueMap.set(league.id, league);
}
return [...leagueMap.values()].sort(
(a, b) => b.createdAt.getTime() - a.createdAt.getTime()
);
}
/**

View file

@ -92,9 +92,9 @@ export default function Home({ loaderData }: Route.ComponentProps) {
{leagues.length === 0 ? (
<Card>
<CardHeader>
<CardTitle>No Active Leagues</CardTitle>
<CardTitle>No Leagues</CardTitle>
<CardDescription>
You don't have any teams in leagues with active seasons yet
You aren't a member of any leagues yet
</CardDescription>
</CardHeader>
<CardContent>