feat: add sports and participant models with admin user functionality

This commit is contained in:
Chris Parsons 2025-10-12 21:16:00 -07:00
parent e77625b627
commit dc727b6f3f
14 changed files with 2088 additions and 1 deletions

View file

@ -4,3 +4,10 @@ export * from "./league";
export * from "./season"; export * from "./season";
export * from "./team"; export * from "./team";
export * from "./commissioner"; export * from "./commissioner";
export * from "./sport";
export * from "./sports-season";
export * from "./participant";
export * from "./season-template";
export * from "./season-template-sport";
export * from "./season-sport";
export * from "./participant-result";

View file

@ -0,0 +1,156 @@
import { eq, and } from "drizzle-orm";
import { database } from "~/database/context";
import * as schema from "~/database/schema";
export type ParticipantResult = typeof schema.participantResults.$inferSelect;
export type NewParticipantResult = typeof schema.participantResults.$inferInsert;
export async function createParticipantResult(
data: NewParticipantResult
): Promise<ParticipantResult> {
const db = database();
const [result] = await db
.insert(schema.participantResults)
.values(data)
.returning();
return result;
}
export async function createManyParticipantResults(
data: NewParticipantResult[]
): Promise<ParticipantResult[]> {
const db = database();
return await db
.insert(schema.participantResults)
.values(data)
.returning();
}
export async function findParticipantResultById(
id: string
): Promise<ParticipantResult | undefined> {
const db = database();
return await db.query.participantResults.findFirst({
where: eq(schema.participantResults.id, id),
with: {
participant: true,
sportsSeason: {
with: {
sport: true,
},
},
},
});
}
export async function findParticipantResultByParticipantId(
participantId: string
): Promise<ParticipantResult | undefined> {
const db = database();
return await db.query.participantResults.findFirst({
where: eq(schema.participantResults.participantId, participantId),
with: {
participant: true,
sportsSeason: {
with: {
sport: true,
},
},
},
});
}
export async function findParticipantResultsBySportsSeasonId(
sportsSeasonId: string
): Promise<ParticipantResult[]> {
const db = database();
return await db.query.participantResults.findMany({
where: eq(schema.participantResults.sportsSeasonId, sportsSeasonId),
orderBy: (results, { asc }) => [asc(results.finalPosition)],
with: {
participant: true,
},
});
}
export async function updateParticipantResult(
id: string,
data: Partial<NewParticipantResult>
): Promise<ParticipantResult> {
const db = database();
const [result] = await db
.update(schema.participantResults)
.set({ ...data, updatedAt: new Date() })
.where(eq(schema.participantResults.id, id))
.returning();
return result;
}
export async function deleteParticipantResult(id: string): Promise<void> {
const db = database();
await db.delete(schema.participantResults).where(eq(schema.participantResults.id, id));
}
export async function deleteParticipantResultsBySportsSeasonId(
sportsSeasonId: string
): Promise<void> {
const db = database();
await db
.delete(schema.participantResults)
.where(eq(schema.participantResults.sportsSeasonId, sportsSeasonId));
}
/**
* Calculate points awarded based on final position
* 1st: 80, 2nd: 50, 3rd-4th: 30, 5th-8th: 20, 9th+: 0
*/
export function calculatePointsFromPosition(position: number | null): number {
if (position === null || position < 1) return 0;
if (position === 1) return 80;
if (position === 2) return 50;
if (position >= 3 && position <= 4) return 30;
if (position >= 5 && position <= 8) return 20;
return 0;
}
/**
* Set result with automatic point calculation
*/
export async function setParticipantResult(
participantId: string,
sportsSeasonId: string,
finalPosition: number,
qualifyingPoints?: number,
notes?: string
): Promise<ParticipantResult> {
const db = database();
const pointsAwarded = calculatePointsFromPosition(finalPosition);
// Check if result already exists
const existing = await db.query.participantResults.findFirst({
where: and(
eq(schema.participantResults.participantId, participantId),
eq(schema.participantResults.sportsSeasonId, sportsSeasonId)
),
});
if (existing) {
// Update existing result
return await updateParticipantResult(existing.id, {
finalPosition,
pointsAwarded,
qualifyingPoints: qualifyingPoints?.toString(),
notes,
});
} else {
// Create new result
return await createParticipantResult({
participantId,
sportsSeasonId,
finalPosition,
pointsAwarded,
qualifyingPoints: qualifyingPoints?.toString(),
notes,
});
}
}

101
app/models/participant.ts Normal file
View file

@ -0,0 +1,101 @@
import { eq } from "drizzle-orm";
import { database } from "~/database/context";
import * as schema from "~/database/schema";
export type Participant = typeof schema.participants.$inferSelect;
export type NewParticipant = typeof schema.participants.$inferInsert;
export async function createParticipant(data: NewParticipant): Promise<Participant> {
const db = database();
const [participant] = await db
.insert(schema.participants)
.values(data)
.returning();
return participant;
}
export async function createManyParticipants(data: NewParticipant[]): Promise<Participant[]> {
const db = database();
return await db
.insert(schema.participants)
.values(data)
.returning();
}
export async function findParticipantById(id: string): Promise<Participant | undefined> {
const db = database();
return await db.query.participants.findFirst({
where: eq(schema.participants.id, id),
with: {
sportsSeason: {
with: {
sport: true,
},
},
},
});
}
export async function findParticipantsBySportsSeasonId(sportsSeasonId: string): Promise<Participant[]> {
const db = database();
return await db.query.participants.findMany({
where: eq(schema.participants.sportsSeasonId, sportsSeasonId),
orderBy: (participants, { asc }) => [asc(participants.name)],
});
}
export async function findParticipantsByExternalId(
externalId: string
): Promise<Participant[]> {
const db = database();
return await db.query.participants.findMany({
where: eq(schema.participants.externalId, externalId),
with: {
sportsSeason: {
with: {
sport: true,
},
},
},
});
}
export async function updateParticipant(
id: string,
data: Partial<NewParticipant>
): Promise<Participant> {
const db = database();
const [participant] = await db
.update(schema.participants)
.set({ ...data, updatedAt: new Date() })
.where(eq(schema.participants.id, id))
.returning();
return participant;
}
export async function deleteParticipant(id: string): Promise<void> {
const db = database();
await db.delete(schema.participants).where(eq(schema.participants.id, id));
}
export async function copyParticipantsFromSeason(
sourceSportsSeasonId: string,
targetSportsSeasonId: string
): Promise<Participant[]> {
// Get all participants from source season
const sourceParticipants = await findParticipantsBySportsSeasonId(sourceSportsSeasonId);
// Insert them into the target season
if (sourceParticipants.length === 0) {
return [];
}
return await createManyParticipants(
sourceParticipants.map((p) => ({
sportsSeasonId: targetSportsSeasonId,
name: p.name,
shortName: p.shortName,
externalId: p.externalId,
}))
);
}

129
app/models/season-sport.ts Normal file
View file

@ -0,0 +1,129 @@
import { eq, and } from "drizzle-orm";
import { database } from "~/database/context";
import * as schema from "~/database/schema";
export type SeasonSport = typeof schema.seasonSports.$inferSelect;
export type NewSeasonSport = typeof schema.seasonSports.$inferInsert;
export async function linkSportToSeason(
seasonId: string,
sportsSeasonId: string,
isRequired: boolean = true
): Promise<SeasonSport> {
const db = database();
const [link] = await db
.insert(schema.seasonSports)
.values({
seasonId,
sportsSeasonId,
isRequired,
})
.returning();
return link;
}
export async function linkMultipleSportsToSeason(
data: NewSeasonSport[]
): Promise<SeasonSport[]> {
const db = database();
return await db
.insert(schema.seasonSports)
.values(data)
.returning();
}
export async function unlinkSportFromSeason(
seasonId: string,
sportsSeasonId: string
): Promise<void> {
const db = database();
await db
.delete(schema.seasonSports)
.where(
and(
eq(schema.seasonSports.seasonId, seasonId),
eq(schema.seasonSports.sportsSeasonId, sportsSeasonId)
)
);
}
export async function findSeasonSportsBySeasonId(
seasonId: string
): Promise<SeasonSport[]> {
const db = database();
return await db.query.seasonSports.findMany({
where: eq(schema.seasonSports.seasonId, seasonId),
with: {
sportsSeason: {
with: {
sport: true,
},
},
},
});
}
export async function findSeasonSportsBySportsSeasonId(
sportsSeasonId: string
): Promise<SeasonSport[]> {
const db = database();
return await db.query.seasonSports.findMany({
where: eq(schema.seasonSports.sportsSeasonId, sportsSeasonId),
with: {
season: {
with: {
league: true,
},
},
},
});
}
export async function updateSeasonSport(
seasonId: string,
sportsSeasonId: string,
isRequired: boolean
): Promise<SeasonSport> {
const db = database();
const [link] = await db
.update(schema.seasonSports)
.set({ isRequired })
.where(
and(
eq(schema.seasonSports.seasonId, seasonId),
eq(schema.seasonSports.sportsSeasonId, sportsSeasonId)
)
)
.returning();
return link;
}
export async function deleteSeasonSport(id: string): Promise<void> {
const db = database();
await db.delete(schema.seasonSports).where(eq(schema.seasonSports.id, id));
}
export async function applySportsFromTemplate(
seasonId: string,
templateId: string
): Promise<SeasonSport[]> {
const db = database();
// Get all sports from the template
const templateSports = await db.query.seasonTemplateSports.findMany({
where: eq(schema.seasonTemplateSports.templateId, templateId),
});
if (templateSports.length === 0) {
return [];
}
// Link them to the season
return await linkMultipleSportsToSeason(
templateSports.map((ts) => ({
seasonId,
sportsSeasonId: ts.sportsSeasonId,
isRequired: ts.isRequired,
}))
);
}

View file

@ -0,0 +1,100 @@
import { eq, and } from "drizzle-orm";
import { database } from "~/database/context";
import * as schema from "~/database/schema";
export type SeasonTemplateSport = typeof schema.seasonTemplateSports.$inferSelect;
export type NewSeasonTemplateSport = typeof schema.seasonTemplateSports.$inferInsert;
export async function addSportToTemplate(
templateId: string,
sportsSeasonId: string,
isRequired: boolean = true
): Promise<SeasonTemplateSport> {
const db = database();
const [link] = await db
.insert(schema.seasonTemplateSports)
.values({
templateId,
sportsSeasonId,
isRequired,
})
.returning();
return link;
}
export async function addMultipleSportsToTemplate(
data: NewSeasonTemplateSport[]
): Promise<SeasonTemplateSport[]> {
const db = database();
return await db
.insert(schema.seasonTemplateSports)
.values(data)
.returning();
}
export async function removeSportFromTemplate(
templateId: string,
sportsSeasonId: string
): Promise<void> {
const db = database();
await db
.delete(schema.seasonTemplateSports)
.where(
and(
eq(schema.seasonTemplateSports.templateId, templateId),
eq(schema.seasonTemplateSports.sportsSeasonId, sportsSeasonId)
)
);
}
export async function findSeasonTemplateSportsByTemplateId(
templateId: string
): Promise<SeasonTemplateSport[]> {
const db = database();
return await db.query.seasonTemplateSports.findMany({
where: eq(schema.seasonTemplateSports.templateId, templateId),
with: {
sportsSeason: {
with: {
sport: true,
},
},
},
});
}
export async function findSeasonTemplateSportsBySportsSeasonId(
sportsSeasonId: string
): Promise<SeasonTemplateSport[]> {
const db = database();
return await db.query.seasonTemplateSports.findMany({
where: eq(schema.seasonTemplateSports.sportsSeasonId, sportsSeasonId),
with: {
template: true,
},
});
}
export async function updateSeasonTemplateSport(
templateId: string,
sportsSeasonId: string,
isRequired: boolean
): Promise<SeasonTemplateSport> {
const db = database();
const [link] = await db
.update(schema.seasonTemplateSports)
.set({ isRequired })
.where(
and(
eq(schema.seasonTemplateSports.templateId, templateId),
eq(schema.seasonTemplateSports.sportsSeasonId, sportsSeasonId)
)
)
.returning();
return link;
}
export async function deleteSeasonTemplateSport(id: string): Promise<void> {
const db = database();
await db.delete(schema.seasonTemplateSports).where(eq(schema.seasonTemplateSports.id, id));
}

View file

@ -0,0 +1,88 @@
import { eq } from "drizzle-orm";
import { database } from "~/database/context";
import * as schema from "~/database/schema";
export type SeasonTemplate = typeof schema.seasonTemplates.$inferSelect;
export type NewSeasonTemplate = typeof schema.seasonTemplates.$inferInsert;
export async function createSeasonTemplate(data: NewSeasonTemplate): Promise<SeasonTemplate> {
const db = database();
const [template] = await db
.insert(schema.seasonTemplates)
.values(data)
.returning();
return template;
}
export async function findSeasonTemplateById(id: string): Promise<SeasonTemplate | undefined> {
const db = database();
return await db.query.seasonTemplates.findFirst({
where: eq(schema.seasonTemplates.id, id),
});
}
export async function findSeasonTemplateWithSportsSeasons(id: string) {
const db = database();
return await db.query.seasonTemplates.findFirst({
where: eq(schema.seasonTemplates.id, id),
with: {
seasonTemplateSports: {
with: {
sportsSeason: {
with: {
sport: true,
},
},
},
},
},
});
}
export async function findActiveSeasonTemplates(): Promise<SeasonTemplate[]> {
const db = database();
return await db.query.seasonTemplates.findMany({
where: eq(schema.seasonTemplates.isActive, true),
orderBy: (templates, { desc }) => [desc(templates.year)],
});
}
export async function findSeasonTemplatesByYear(year: number): Promise<SeasonTemplate[]> {
const db = database();
return await db.query.seasonTemplates.findMany({
where: eq(schema.seasonTemplates.year, year),
orderBy: (templates, { asc }) => [asc(templates.name)],
});
}
export async function findAllSeasonTemplates(): Promise<SeasonTemplate[]> {
const db = database();
return await db.query.seasonTemplates.findMany({
orderBy: (templates, { desc }) => [desc(templates.year)],
});
}
export async function updateSeasonTemplate(
id: string,
data: Partial<NewSeasonTemplate>
): Promise<SeasonTemplate> {
const db = database();
const [template] = await db
.update(schema.seasonTemplates)
.set({ ...data, updatedAt: new Date() })
.where(eq(schema.seasonTemplates.id, id))
.returning();
return template;
}
export async function setSeasonTemplateActive(
id: string,
isActive: boolean
): Promise<SeasonTemplate> {
return await updateSeasonTemplate(id, { isActive });
}
export async function deleteSeasonTemplate(id: string): Promise<void> {
const db = database();
await db.delete(schema.seasonTemplates).where(eq(schema.seasonTemplates.id, id));
}

View file

@ -6,6 +6,26 @@ export type Season = typeof schema.seasons.$inferSelect;
export type NewSeason = typeof schema.seasons.$inferInsert; export type NewSeason = typeof schema.seasons.$inferInsert;
export type SeasonStatus = "pre_draft" | "draft" | "active" | "completed"; export type SeasonStatus = "pre_draft" | "draft" | "active" | "completed";
export interface SeasonWithSportsSeasons extends Season {
seasonSports: Array<{
id: string;
isRequired: boolean;
sportsSeason: {
id: string;
name: string;
year: number;
status: string;
scoringType: string;
sport: {
id: string;
name: string;
type: string;
slug: string;
};
};
}>;
}
export async function createSeason(data: NewSeason): Promise<Season> { export async function createSeason(data: NewSeason): Promise<Season> {
const db = database(); const db = database();
const [season] = await db const [season] = await db
@ -77,3 +97,23 @@ export async function deleteSeason(id: string): Promise<void> {
const db = database(); const db = database();
await db.delete(schema.seasons).where(eq(schema.seasons.id, id)); await db.delete(schema.seasons).where(eq(schema.seasons.id, id));
} }
export async function findSeasonWithSportsSeasons(
id: string
): Promise<SeasonWithSportsSeasons | undefined> {
const db = database();
return await db.query.seasons.findFirst({
where: eq(schema.seasons.id, id),
with: {
seasonSports: {
with: {
sportsSeason: {
with: {
sport: true,
},
},
},
},
},
}) as SeasonWithSportsSeasons | undefined;
}

63
app/models/sport.ts Normal file
View file

@ -0,0 +1,63 @@
import { eq } from "drizzle-orm";
import { database } from "~/database/context";
import * as schema from "~/database/schema";
export type Sport = typeof schema.sports.$inferSelect;
export type NewSport = typeof schema.sports.$inferInsert;
export type SportType = "team" | "individual";
export async function createSport(data: NewSport): Promise<Sport> {
const db = database();
const [sport] = await db
.insert(schema.sports)
.values(data)
.returning();
return sport;
}
export async function findSportById(id: string): Promise<Sport | undefined> {
const db = database();
return await db.query.sports.findFirst({
where: eq(schema.sports.id, id),
});
}
export async function findSportBySlug(slug: string): Promise<Sport | undefined> {
const db = database();
return await db.query.sports.findFirst({
where: eq(schema.sports.slug, slug),
});
}
export async function findAllSports(): Promise<Sport[]> {
const db = database();
return await db.query.sports.findMany({
orderBy: (sports, { asc }) => [asc(sports.name)],
});
}
export async function findSportsByType(type: SportType): Promise<Sport[]> {
const db = database();
return await db.query.sports.findMany({
where: eq(schema.sports.type, type),
orderBy: (sports, { asc }) => [asc(sports.name)],
});
}
export async function updateSport(
id: string,
data: Partial<NewSport>
): Promise<Sport> {
const db = database();
const [sport] = await db
.update(schema.sports)
.set({ ...data, updatedAt: new Date() })
.where(eq(schema.sports.id, id))
.returning();
return sport;
}
export async function deleteSport(id: string): Promise<void> {
const db = database();
await db.delete(schema.sports).where(eq(schema.sports.id, id));
}

119
app/models/sports-season.ts Normal file
View file

@ -0,0 +1,119 @@
import { eq } from "drizzle-orm";
import { database } from "~/database/context";
import * as schema from "~/database/schema";
export type SportsSeason = typeof schema.sportsSeasons.$inferSelect;
export type NewSportsSeason = typeof schema.sportsSeasons.$inferInsert;
export type SportsSeasonStatus = "upcoming" | "active" | "completed";
export type ScoringType = "playoffs" | "regular_season" | "majors";
export async function createSportsSeason(data: NewSportsSeason): Promise<SportsSeason> {
const db = database();
const [sportsSeason] = await db
.insert(schema.sportsSeasons)
.values(data)
.returning();
return sportsSeason;
}
export async function findSportsSeasonById(id: string): Promise<SportsSeason | undefined> {
const db = database();
return await db.query.sportsSeasons.findFirst({
where: eq(schema.sportsSeasons.id, id),
with: {
sport: true,
},
});
}
export async function findSportsSeasonsBySportId(sportId: string): Promise<SportsSeason[]> {
const db = database();
return await db.query.sportsSeasons.findMany({
where: eq(schema.sportsSeasons.sportId, sportId),
orderBy: (sportsSeasons, { desc }) => [desc(sportsSeasons.year)],
with: {
sport: true,
},
});
}
export async function findSportsSeasonsByYear(year: number): Promise<SportsSeason[]> {
const db = database();
return await db.query.sportsSeasons.findMany({
where: eq(schema.sportsSeasons.year, year),
orderBy: (sportsSeasons, { asc }) => [asc(sportsSeasons.name)],
with: {
sport: true,
},
});
}
export async function findSportsSeasonsByStatus(status: SportsSeasonStatus): Promise<SportsSeason[]> {
const db = database();
return await db.query.sportsSeasons.findMany({
where: eq(schema.sportsSeasons.status, status),
orderBy: (sportsSeasons, { desc }) => [desc(sportsSeasons.year)],
with: {
sport: true,
},
});
}
export async function findAllSportsSeasons(): Promise<SportsSeason[]> {
const db = database();
return await db.query.sportsSeasons.findMany({
orderBy: (sportsSeasons, { desc, asc }) => [desc(sportsSeasons.year), asc(sportsSeasons.name)],
with: {
sport: true,
},
});
}
export async function updateSportsSeason(
id: string,
data: Partial<NewSportsSeason>
): Promise<SportsSeason> {
const db = database();
const [sportsSeason] = await db
.update(schema.sportsSeasons)
.set({ ...data, updatedAt: new Date() })
.where(eq(schema.sportsSeasons.id, id))
.returning();
return sportsSeason;
}
export async function updateSportsSeasonStatus(
id: string,
status: SportsSeasonStatus
): Promise<SportsSeason> {
return await updateSportsSeason(id, { status });
}
export async function deleteSportsSeason(id: string): Promise<void> {
const db = database();
await db.delete(schema.sportsSeasons).where(eq(schema.sportsSeasons.id, id));
}
export async function copyParticipantsFromPreviousSeason(
currentSeasonId: string,
previousSeasonId: string
): Promise<void> {
const db = database();
// Get all participants from previous season
const previousParticipants = await db.query.participants.findMany({
where: eq(schema.participants.sportsSeasonId, previousSeasonId),
});
// Insert them into the current season
if (previousParticipants.length > 0) {
await db.insert(schema.participants).values(
previousParticipants.map((p) => ({
sportsSeasonId: currentSeasonId,
name: p.name,
shortName: p.shortName,
externalId: p.externalId,
}))
);
}
}

View file

@ -106,3 +106,25 @@ export async function deleteUser(id: string): Promise<void> {
const db = database(); const db = database();
await db.delete(schema.users).where(eq(schema.users.id, id)); await db.delete(schema.users).where(eq(schema.users.id, id));
} }
export async function findAdmins(): Promise<User[]> {
const db = database();
return await db.query.users.findMany({
where: eq(schema.users.isAdmin, true),
orderBy: (users, { asc }) => [asc(users.displayName)],
});
}
export async function isUserAdmin(userId: string): Promise<boolean> {
const user = await findUserById(userId);
return user?.isAdmin ?? false;
}
export async function isUserAdminByClerkId(clerkId: string): Promise<boolean> {
const user = await findUserByClerkId(clerkId);
return user?.isAdmin ?? false;
}
export async function setUserAdmin(userId: string, isAdmin: boolean): Promise<User> {
return await updateUser(userId, { isAdmin });
}

View file

@ -1,4 +1,5 @@
import { integer, pgTable, varchar, uuid, timestamp, pgEnum } from "drizzle-orm/pg-core"; import { integer, pgTable, varchar, uuid, timestamp, pgEnum, boolean, text, date, decimal } from "drizzle-orm/pg-core";
import { relations } from "drizzle-orm";
// Users table - synced from Clerk // Users table - synced from Clerk
export const users = pgTable("users", { export const users = pgTable("users", {
@ -9,6 +10,7 @@ export const users = pgTable("users", {
firstName: varchar("first_name", { length: 255 }), firstName: varchar("first_name", { length: 255 }),
lastName: varchar("last_name", { length: 255 }), lastName: varchar("last_name", { length: 255 }),
imageUrl: varchar("image_url", { length: 512 }), imageUrl: varchar("image_url", { length: 512 }),
isAdmin: boolean("is_admin").notNull().default(false),
createdAt: timestamp("created_at").defaultNow().notNull(), createdAt: timestamp("created_at").defaultNow().notNull(),
updatedAt: timestamp("updated_at").defaultNow().notNull(), updatedAt: timestamp("updated_at").defaultNow().notNull(),
}); });
@ -21,6 +23,21 @@ export const seasonStatusEnum = pgEnum("season_status", [
"completed", "completed",
]); ]);
// Sports Tables - Enums
export const sportTypeEnum = pgEnum("sport_type", ["team", "individual"]);
export const sportsSeasonStatusEnum = pgEnum("sports_season_status", [
"upcoming",
"active",
"completed",
]);
export const scoringTypeEnum = pgEnum("scoring_type", [
"playoffs",
"regular_season",
"majors",
]);
export const leagues = pgTable("leagues", { export const leagues = pgTable("leagues", {
id: uuid("id").primaryKey().defaultRandom(), id: uuid("id").primaryKey().defaultRandom(),
name: varchar("name", { length: 255 }).notNull(), name: varchar("name", { length: 255 }).notNull(),
@ -30,6 +47,16 @@ export const leagues = pgTable("leagues", {
updatedAt: timestamp("updated_at").defaultNow().notNull(), updatedAt: timestamp("updated_at").defaultNow().notNull(),
}); });
export const seasonTemplates = pgTable("season_templates", {
id: uuid("id").primaryKey().defaultRandom(),
name: varchar("name", { length: 255 }).notNull(),
description: text("description"),
year: integer("year").notNull(),
isActive: boolean("is_active").notNull().default(true),
createdAt: timestamp("created_at").defaultNow().notNull(),
updatedAt: timestamp("updated_at").defaultNow().notNull(),
});
export const seasons = pgTable("seasons", { export const seasons = pgTable("seasons", {
id: uuid("id").primaryKey().defaultRandom(), id: uuid("id").primaryKey().defaultRandom(),
leagueId: uuid("league_id") leagueId: uuid("league_id")
@ -37,6 +64,9 @@ export const seasons = pgTable("seasons", {
.references(() => leagues.id, { onDelete: "cascade" }), .references(() => leagues.id, { onDelete: "cascade" }),
year: integer("year").notNull(), year: integer("year").notNull(),
status: seasonStatusEnum("status").notNull().default("pre_draft"), status: seasonStatusEnum("status").notNull().default("pre_draft"),
templateId: uuid("template_id")
.references(() => seasonTemplates.id, { onDelete: "set null" }),
flexSpots: integer("flex_spots").notNull().default(0),
createdAt: timestamp("created_at").defaultNow().notNull(), createdAt: timestamp("created_at").defaultNow().notNull(),
updatedAt: timestamp("updated_at").defaultNow().notNull(), updatedAt: timestamp("updated_at").defaultNow().notNull(),
}); });
@ -60,3 +90,156 @@ export const commissioners = pgTable("commissioners", {
userId: varchar("user_id", { length: 255 }).notNull(), // Clerk user ID userId: varchar("user_id", { length: 255 }).notNull(), // Clerk user ID
createdAt: timestamp("created_at").defaultNow().notNull(), createdAt: timestamp("created_at").defaultNow().notNull(),
}); });
// Sports Tables
export const sports = pgTable("sports", {
id: uuid("id").primaryKey().defaultRandom(),
name: varchar("name", { length: 255 }).notNull(),
type: sportTypeEnum("type").notNull(),
slug: varchar("slug", { length: 255 }).notNull().unique(),
description: text("description"),
createdAt: timestamp("created_at").defaultNow().notNull(),
updatedAt: timestamp("updated_at").defaultNow().notNull(),
});
export const sportsSeasons = pgTable("sports_seasons", {
id: uuid("id").primaryKey().defaultRandom(),
sportId: uuid("sport_id")
.notNull()
.references(() => sports.id, { onDelete: "cascade" }),
name: varchar("name", { length: 255 }).notNull(),
year: integer("year").notNull(),
startDate: date("start_date"),
endDate: date("end_date"),
status: sportsSeasonStatusEnum("status").notNull().default("upcoming"),
scoringType: scoringTypeEnum("scoring_type").notNull(),
createdAt: timestamp("created_at").defaultNow().notNull(),
updatedAt: timestamp("updated_at").defaultNow().notNull(),
});
export const participants = pgTable("participants", {
id: uuid("id").primaryKey().defaultRandom(),
sportsSeasonId: uuid("sports_season_id")
.notNull()
.references(() => sportsSeasons.id, { onDelete: "cascade" }),
name: varchar("name", { length: 255 }).notNull(),
shortName: varchar("short_name", { length: 100 }),
externalId: varchar("external_id", { length: 255 }),
createdAt: timestamp("created_at").defaultNow().notNull(),
updatedAt: timestamp("updated_at").defaultNow().notNull(),
});
export const seasonTemplateSports = pgTable("season_template_sports", {
id: uuid("id").primaryKey().defaultRandom(),
templateId: uuid("template_id")
.notNull()
.references(() => seasonTemplates.id, { onDelete: "cascade" }),
sportsSeasonId: uuid("sports_season_id")
.notNull()
.references(() => sportsSeasons.id, { onDelete: "cascade" }),
isRequired: boolean("is_required").notNull().default(true),
createdAt: timestamp("created_at").defaultNow().notNull(),
});
export const seasonSports = pgTable("season_sports", {
id: uuid("id").primaryKey().defaultRandom(),
seasonId: uuid("season_id")
.notNull()
.references(() => seasons.id, { onDelete: "cascade" }),
sportsSeasonId: uuid("sports_season_id")
.notNull()
.references(() => sportsSeasons.id, { onDelete: "cascade" }),
isRequired: boolean("is_required").notNull().default(true),
createdAt: timestamp("created_at").defaultNow().notNull(),
});
export const participantResults = pgTable("participant_results", {
id: uuid("id").primaryKey().defaultRandom(),
participantId: uuid("participant_id")
.notNull()
.references(() => participants.id, { onDelete: "cascade" }),
sportsSeasonId: uuid("sports_season_id")
.notNull()
.references(() => sportsSeasons.id, { onDelete: "cascade" }),
finalPosition: integer("final_position"),
pointsAwarded: integer("points_awarded").notNull().default(0),
qualifyingPoints: decimal("qualifying_points", { precision: 10, scale: 2 }),
notes: text("notes"),
createdAt: timestamp("created_at").defaultNow().notNull(),
updatedAt: timestamp("updated_at").defaultNow().notNull(),
});
// Relations
export const sportsRelations = relations(sports, ({ many }) => ({
sportsSeasons: many(sportsSeasons),
}));
export const sportsSeasonsRelations = relations(sportsSeasons, ({ one, many }) => ({
sport: one(sports, {
fields: [sportsSeasons.sportId],
references: [sports.id],
}),
participants: many(participants),
seasonTemplateSports: many(seasonTemplateSports),
seasonSports: many(seasonSports),
participantResults: many(participantResults),
}));
export const participantsRelations = relations(participants, ({ one, many }) => ({
sportsSeason: one(sportsSeasons, {
fields: [participants.sportsSeasonId],
references: [sportsSeasons.id],
}),
results: many(participantResults),
}));
export const seasonTemplatesRelations = relations(seasonTemplates, ({ many }) => ({
seasonTemplateSports: many(seasonTemplateSports),
seasons: many(seasons),
}));
export const seasonTemplateSportsRelations = relations(seasonTemplateSports, ({ one }) => ({
template: one(seasonTemplates, {
fields: [seasonTemplateSports.templateId],
references: [seasonTemplates.id],
}),
sportsSeason: one(sportsSeasons, {
fields: [seasonTemplateSports.sportsSeasonId],
references: [sportsSeasons.id],
}),
}));
export const seasonsRelations = relations(seasons, ({ one, many }) => ({
league: one(leagues, {
fields: [seasons.leagueId],
references: [leagues.id],
}),
template: one(seasonTemplates, {
fields: [seasons.templateId],
references: [seasonTemplates.id],
}),
teams: many(teams),
seasonSports: many(seasonSports),
}));
export const seasonSportsRelations = relations(seasonSports, ({ one }) => ({
season: one(seasons, {
fields: [seasonSports.seasonId],
references: [seasons.id],
}),
sportsSeason: one(sportsSeasons, {
fields: [seasonSports.sportsSeasonId],
references: [sportsSeasons.id],
}),
}));
export const participantResultsRelations = relations(participantResults, ({ one }) => ({
participant: one(participants, {
fields: [participantResults.participantId],
references: [participants.id],
}),
sportsSeason: one(sportsSeasons, {
fields: [participantResults.sportsSeasonId],
references: [sportsSeasons.id],
}),
}));

View file

@ -0,0 +1,131 @@
CREATE TYPE "public"."scoring_type" AS ENUM('playoffs', 'regular_season', 'majors');--> statement-breakpoint
CREATE TYPE "public"."sport_type" AS ENUM('team', 'individual');--> statement-breakpoint
CREATE TYPE "public"."sports_season_status" AS ENUM('upcoming', 'active', 'completed');--> statement-breakpoint
CREATE TABLE IF NOT EXISTS "participant_results" (
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
"participant_id" uuid NOT NULL,
"sports_season_id" uuid NOT NULL,
"final_position" integer,
"points_awarded" integer DEFAULT 0 NOT NULL,
"qualifying_points" numeric(10, 2),
"notes" text,
"created_at" timestamp DEFAULT now() NOT NULL,
"updated_at" timestamp DEFAULT now() NOT NULL
);
--> statement-breakpoint
CREATE TABLE IF NOT EXISTS "participants" (
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
"sports_season_id" uuid NOT NULL,
"name" varchar(255) NOT NULL,
"short_name" varchar(100),
"external_id" varchar(255),
"created_at" timestamp DEFAULT now() NOT NULL,
"updated_at" timestamp DEFAULT now() NOT NULL
);
--> statement-breakpoint
CREATE TABLE IF NOT EXISTS "season_sports" (
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
"season_id" uuid NOT NULL,
"sports_season_id" uuid NOT NULL,
"is_required" boolean DEFAULT true NOT NULL,
"created_at" timestamp DEFAULT now() NOT NULL
);
--> statement-breakpoint
CREATE TABLE IF NOT EXISTS "season_template_sports" (
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
"template_id" uuid NOT NULL,
"sports_season_id" uuid NOT NULL,
"is_required" boolean DEFAULT true NOT NULL,
"created_at" timestamp DEFAULT now() NOT NULL
);
--> statement-breakpoint
CREATE TABLE IF NOT EXISTS "season_templates" (
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
"name" varchar(255) NOT NULL,
"description" text,
"year" integer NOT NULL,
"is_active" boolean DEFAULT true NOT NULL,
"created_at" timestamp DEFAULT now() NOT NULL,
"updated_at" timestamp DEFAULT now() NOT NULL
);
--> statement-breakpoint
CREATE TABLE IF NOT EXISTS "sports" (
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
"name" varchar(255) NOT NULL,
"type" "sport_type" NOT NULL,
"slug" varchar(255) NOT NULL,
"description" text,
"created_at" timestamp DEFAULT now() NOT NULL,
"updated_at" timestamp DEFAULT now() NOT NULL,
CONSTRAINT "sports_slug_unique" UNIQUE("slug")
);
--> statement-breakpoint
CREATE TABLE IF NOT EXISTS "sports_seasons" (
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
"sport_id" uuid NOT NULL,
"name" varchar(255) NOT NULL,
"year" integer NOT NULL,
"start_date" date,
"end_date" date,
"status" "sports_season_status" DEFAULT 'upcoming' NOT NULL,
"scoring_type" "scoring_type" NOT NULL,
"created_at" timestamp DEFAULT now() NOT NULL,
"updated_at" timestamp DEFAULT now() NOT NULL
);
--> statement-breakpoint
ALTER TABLE "seasons" ADD COLUMN "template_id" uuid;--> statement-breakpoint
ALTER TABLE "seasons" ADD COLUMN "flex_spots" integer DEFAULT 0 NOT NULL;--> statement-breakpoint
ALTER TABLE "users" ADD COLUMN "is_admin" boolean DEFAULT false NOT NULL;--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "participant_results" ADD CONSTRAINT "participant_results_participant_id_participants_id_fk" FOREIGN KEY ("participant_id") REFERENCES "public"."participants"("id") ON DELETE cascade ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "participant_results" ADD CONSTRAINT "participant_results_sports_season_id_sports_seasons_id_fk" FOREIGN KEY ("sports_season_id") REFERENCES "public"."sports_seasons"("id") ON DELETE cascade ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "participants" ADD CONSTRAINT "participants_sports_season_id_sports_seasons_id_fk" FOREIGN KEY ("sports_season_id") REFERENCES "public"."sports_seasons"("id") ON DELETE cascade ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "season_sports" ADD CONSTRAINT "season_sports_season_id_seasons_id_fk" FOREIGN KEY ("season_id") REFERENCES "public"."seasons"("id") ON DELETE cascade ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "season_sports" ADD CONSTRAINT "season_sports_sports_season_id_sports_seasons_id_fk" FOREIGN KEY ("sports_season_id") REFERENCES "public"."sports_seasons"("id") ON DELETE cascade ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "season_template_sports" ADD CONSTRAINT "season_template_sports_template_id_season_templates_id_fk" FOREIGN KEY ("template_id") REFERENCES "public"."season_templates"("id") ON DELETE cascade ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "season_template_sports" ADD CONSTRAINT "season_template_sports_sports_season_id_sports_seasons_id_fk" FOREIGN KEY ("sports_season_id") REFERENCES "public"."sports_seasons"("id") ON DELETE cascade ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "sports_seasons" ADD CONSTRAINT "sports_seasons_sport_id_sports_id_fk" FOREIGN KEY ("sport_id") REFERENCES "public"."sports"("id") ON DELETE cascade ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "seasons" ADD CONSTRAINT "seasons_template_id_season_templates_id_fk" FOREIGN KEY ("template_id") REFERENCES "public"."season_templates"("id") ON DELETE set null ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;

View file

@ -0,0 +1,941 @@
{
"id": "462e431e-4517-4a02-b4e9-80c82c1b2c9f",
"prevId": "afd92b21-6a89-4b8c-80ac-414a320db897",
"version": "7",
"dialect": "postgresql",
"tables": {
"public.commissioners": {
"name": "commissioners",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "uuid",
"primaryKey": true,
"notNull": true,
"default": "gen_random_uuid()"
},
"league_id": {
"name": "league_id",
"type": "uuid",
"primaryKey": false,
"notNull": true
},
"user_id": {
"name": "user_id",
"type": "varchar(255)",
"primaryKey": false,
"notNull": true
},
"created_at": {
"name": "created_at",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {},
"foreignKeys": {
"commissioners_league_id_leagues_id_fk": {
"name": "commissioners_league_id_leagues_id_fk",
"tableFrom": "commissioners",
"tableTo": "leagues",
"columnsFrom": [
"league_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.leagues": {
"name": "leagues",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "uuid",
"primaryKey": true,
"notNull": true,
"default": "gen_random_uuid()"
},
"name": {
"name": "name",
"type": "varchar(255)",
"primaryKey": false,
"notNull": true
},
"created_by": {
"name": "created_by",
"type": "varchar(255)",
"primaryKey": false,
"notNull": true
},
"current_season_id": {
"name": "current_season_id",
"type": "uuid",
"primaryKey": false,
"notNull": false
},
"created_at": {
"name": "created_at",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"updated_at": {
"name": "updated_at",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.participant_results": {
"name": "participant_results",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "uuid",
"primaryKey": true,
"notNull": true,
"default": "gen_random_uuid()"
},
"participant_id": {
"name": "participant_id",
"type": "uuid",
"primaryKey": false,
"notNull": true
},
"sports_season_id": {
"name": "sports_season_id",
"type": "uuid",
"primaryKey": false,
"notNull": true
},
"final_position": {
"name": "final_position",
"type": "integer",
"primaryKey": false,
"notNull": false
},
"points_awarded": {
"name": "points_awarded",
"type": "integer",
"primaryKey": false,
"notNull": true,
"default": 0
},
"qualifying_points": {
"name": "qualifying_points",
"type": "numeric(10, 2)",
"primaryKey": false,
"notNull": false
},
"notes": {
"name": "notes",
"type": "text",
"primaryKey": false,
"notNull": false
},
"created_at": {
"name": "created_at",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"updated_at": {
"name": "updated_at",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {},
"foreignKeys": {
"participant_results_participant_id_participants_id_fk": {
"name": "participant_results_participant_id_participants_id_fk",
"tableFrom": "participant_results",
"tableTo": "participants",
"columnsFrom": [
"participant_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
},
"participant_results_sports_season_id_sports_seasons_id_fk": {
"name": "participant_results_sports_season_id_sports_seasons_id_fk",
"tableFrom": "participant_results",
"tableTo": "sports_seasons",
"columnsFrom": [
"sports_season_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.participants": {
"name": "participants",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "uuid",
"primaryKey": true,
"notNull": true,
"default": "gen_random_uuid()"
},
"sports_season_id": {
"name": "sports_season_id",
"type": "uuid",
"primaryKey": false,
"notNull": true
},
"name": {
"name": "name",
"type": "varchar(255)",
"primaryKey": false,
"notNull": true
},
"short_name": {
"name": "short_name",
"type": "varchar(100)",
"primaryKey": false,
"notNull": false
},
"external_id": {
"name": "external_id",
"type": "varchar(255)",
"primaryKey": false,
"notNull": false
},
"created_at": {
"name": "created_at",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"updated_at": {
"name": "updated_at",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {},
"foreignKeys": {
"participants_sports_season_id_sports_seasons_id_fk": {
"name": "participants_sports_season_id_sports_seasons_id_fk",
"tableFrom": "participants",
"tableTo": "sports_seasons",
"columnsFrom": [
"sports_season_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.season_sports": {
"name": "season_sports",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "uuid",
"primaryKey": true,
"notNull": true,
"default": "gen_random_uuid()"
},
"season_id": {
"name": "season_id",
"type": "uuid",
"primaryKey": false,
"notNull": true
},
"sports_season_id": {
"name": "sports_season_id",
"type": "uuid",
"primaryKey": false,
"notNull": true
},
"is_required": {
"name": "is_required",
"type": "boolean",
"primaryKey": false,
"notNull": true,
"default": true
},
"created_at": {
"name": "created_at",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {},
"foreignKeys": {
"season_sports_season_id_seasons_id_fk": {
"name": "season_sports_season_id_seasons_id_fk",
"tableFrom": "season_sports",
"tableTo": "seasons",
"columnsFrom": [
"season_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
},
"season_sports_sports_season_id_sports_seasons_id_fk": {
"name": "season_sports_sports_season_id_sports_seasons_id_fk",
"tableFrom": "season_sports",
"tableTo": "sports_seasons",
"columnsFrom": [
"sports_season_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.season_template_sports": {
"name": "season_template_sports",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "uuid",
"primaryKey": true,
"notNull": true,
"default": "gen_random_uuid()"
},
"template_id": {
"name": "template_id",
"type": "uuid",
"primaryKey": false,
"notNull": true
},
"sports_season_id": {
"name": "sports_season_id",
"type": "uuid",
"primaryKey": false,
"notNull": true
},
"is_required": {
"name": "is_required",
"type": "boolean",
"primaryKey": false,
"notNull": true,
"default": true
},
"created_at": {
"name": "created_at",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {},
"foreignKeys": {
"season_template_sports_template_id_season_templates_id_fk": {
"name": "season_template_sports_template_id_season_templates_id_fk",
"tableFrom": "season_template_sports",
"tableTo": "season_templates",
"columnsFrom": [
"template_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
},
"season_template_sports_sports_season_id_sports_seasons_id_fk": {
"name": "season_template_sports_sports_season_id_sports_seasons_id_fk",
"tableFrom": "season_template_sports",
"tableTo": "sports_seasons",
"columnsFrom": [
"sports_season_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.season_templates": {
"name": "season_templates",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "uuid",
"primaryKey": true,
"notNull": true,
"default": "gen_random_uuid()"
},
"name": {
"name": "name",
"type": "varchar(255)",
"primaryKey": false,
"notNull": true
},
"description": {
"name": "description",
"type": "text",
"primaryKey": false,
"notNull": false
},
"year": {
"name": "year",
"type": "integer",
"primaryKey": false,
"notNull": true
},
"is_active": {
"name": "is_active",
"type": "boolean",
"primaryKey": false,
"notNull": true,
"default": true
},
"created_at": {
"name": "created_at",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"updated_at": {
"name": "updated_at",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.seasons": {
"name": "seasons",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "uuid",
"primaryKey": true,
"notNull": true,
"default": "gen_random_uuid()"
},
"league_id": {
"name": "league_id",
"type": "uuid",
"primaryKey": false,
"notNull": true
},
"year": {
"name": "year",
"type": "integer",
"primaryKey": false,
"notNull": true
},
"status": {
"name": "status",
"type": "season_status",
"typeSchema": "public",
"primaryKey": false,
"notNull": true,
"default": "'pre_draft'"
},
"template_id": {
"name": "template_id",
"type": "uuid",
"primaryKey": false,
"notNull": false
},
"flex_spots": {
"name": "flex_spots",
"type": "integer",
"primaryKey": false,
"notNull": true,
"default": 0
},
"created_at": {
"name": "created_at",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"updated_at": {
"name": "updated_at",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {},
"foreignKeys": {
"seasons_league_id_leagues_id_fk": {
"name": "seasons_league_id_leagues_id_fk",
"tableFrom": "seasons",
"tableTo": "leagues",
"columnsFrom": [
"league_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
},
"seasons_template_id_season_templates_id_fk": {
"name": "seasons_template_id_season_templates_id_fk",
"tableFrom": "seasons",
"tableTo": "season_templates",
"columnsFrom": [
"template_id"
],
"columnsTo": [
"id"
],
"onDelete": "set null",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.sports": {
"name": "sports",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "uuid",
"primaryKey": true,
"notNull": true,
"default": "gen_random_uuid()"
},
"name": {
"name": "name",
"type": "varchar(255)",
"primaryKey": false,
"notNull": true
},
"type": {
"name": "type",
"type": "sport_type",
"typeSchema": "public",
"primaryKey": false,
"notNull": true
},
"slug": {
"name": "slug",
"type": "varchar(255)",
"primaryKey": false,
"notNull": true
},
"description": {
"name": "description",
"type": "text",
"primaryKey": false,
"notNull": false
},
"created_at": {
"name": "created_at",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"updated_at": {
"name": "updated_at",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {
"sports_slug_unique": {
"name": "sports_slug_unique",
"nullsNotDistinct": false,
"columns": [
"slug"
]
}
},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.sports_seasons": {
"name": "sports_seasons",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "uuid",
"primaryKey": true,
"notNull": true,
"default": "gen_random_uuid()"
},
"sport_id": {
"name": "sport_id",
"type": "uuid",
"primaryKey": false,
"notNull": true
},
"name": {
"name": "name",
"type": "varchar(255)",
"primaryKey": false,
"notNull": true
},
"year": {
"name": "year",
"type": "integer",
"primaryKey": false,
"notNull": true
},
"start_date": {
"name": "start_date",
"type": "date",
"primaryKey": false,
"notNull": false
},
"end_date": {
"name": "end_date",
"type": "date",
"primaryKey": false,
"notNull": false
},
"status": {
"name": "status",
"type": "sports_season_status",
"typeSchema": "public",
"primaryKey": false,
"notNull": true,
"default": "'upcoming'"
},
"scoring_type": {
"name": "scoring_type",
"type": "scoring_type",
"typeSchema": "public",
"primaryKey": false,
"notNull": true
},
"created_at": {
"name": "created_at",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"updated_at": {
"name": "updated_at",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {},
"foreignKeys": {
"sports_seasons_sport_id_sports_id_fk": {
"name": "sports_seasons_sport_id_sports_id_fk",
"tableFrom": "sports_seasons",
"tableTo": "sports",
"columnsFrom": [
"sport_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.teams": {
"name": "teams",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "uuid",
"primaryKey": true,
"notNull": true,
"default": "gen_random_uuid()"
},
"season_id": {
"name": "season_id",
"type": "uuid",
"primaryKey": false,
"notNull": true
},
"name": {
"name": "name",
"type": "varchar(255)",
"primaryKey": false,
"notNull": true
},
"owner_id": {
"name": "owner_id",
"type": "varchar(255)",
"primaryKey": false,
"notNull": false
},
"created_at": {
"name": "created_at",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"updated_at": {
"name": "updated_at",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {},
"foreignKeys": {
"teams_season_id_seasons_id_fk": {
"name": "teams_season_id_seasons_id_fk",
"tableFrom": "teams",
"tableTo": "seasons",
"columnsFrom": [
"season_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.users": {
"name": "users",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "uuid",
"primaryKey": true,
"notNull": true,
"default": "gen_random_uuid()"
},
"clerk_id": {
"name": "clerk_id",
"type": "varchar(255)",
"primaryKey": false,
"notNull": true
},
"email": {
"name": "email",
"type": "varchar(255)",
"primaryKey": false,
"notNull": true
},
"display_name": {
"name": "display_name",
"type": "varchar(255)",
"primaryKey": false,
"notNull": false
},
"first_name": {
"name": "first_name",
"type": "varchar(255)",
"primaryKey": false,
"notNull": false
},
"last_name": {
"name": "last_name",
"type": "varchar(255)",
"primaryKey": false,
"notNull": false
},
"image_url": {
"name": "image_url",
"type": "varchar(512)",
"primaryKey": false,
"notNull": false
},
"is_admin": {
"name": "is_admin",
"type": "boolean",
"primaryKey": false,
"notNull": true,
"default": false
},
"created_at": {
"name": "created_at",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"updated_at": {
"name": "updated_at",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {
"users_clerk_id_unique": {
"name": "users_clerk_id_unique",
"nullsNotDistinct": false,
"columns": [
"clerk_id"
]
}
},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
}
},
"enums": {
"public.scoring_type": {
"name": "scoring_type",
"schema": "public",
"values": [
"playoffs",
"regular_season",
"majors"
]
},
"public.season_status": {
"name": "season_status",
"schema": "public",
"values": [
"pre_draft",
"draft",
"active",
"completed"
]
},
"public.sport_type": {
"name": "sport_type",
"schema": "public",
"values": [
"team",
"individual"
]
},
"public.sports_season_status": {
"name": "sports_season_status",
"schema": "public",
"values": [
"upcoming",
"active",
"completed"
]
}
},
"schemas": {},
"sequences": {},
"roles": {},
"policies": {},
"views": {},
"_meta": {
"columns": {},
"schemas": {},
"tables": {}
}
}

View file

@ -50,6 +50,13 @@
"when": 1760241924414, "when": 1760241924414,
"tag": "0006_needy_junta", "tag": "0006_needy_junta",
"breakpoints": true "breakpoints": true
},
{
"idx": 7,
"version": "7",
"when": 1760327817376,
"tag": "0007_pink_nebula",
"breakpoints": true
} }
] ]
} }