diff --git a/app/models/index.ts b/app/models/index.ts index 761a8db..ca2dfe2 100644 --- a/app/models/index.ts +++ b/app/models/index.ts @@ -4,3 +4,10 @@ export * from "./league"; export * from "./season"; export * from "./team"; 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"; diff --git a/app/models/participant-result.ts b/app/models/participant-result.ts new file mode 100644 index 0000000..1511647 --- /dev/null +++ b/app/models/participant-result.ts @@ -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 { + const db = database(); + const [result] = await db + .insert(schema.participantResults) + .values(data) + .returning(); + return result; +} + +export async function createManyParticipantResults( + data: NewParticipantResult[] +): Promise { + const db = database(); + return await db + .insert(schema.participantResults) + .values(data) + .returning(); +} + +export async function findParticipantResultById( + id: string +): Promise { + 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 { + 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 { + 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 +): Promise { + 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 { + const db = database(); + await db.delete(schema.participantResults).where(eq(schema.participantResults.id, id)); +} + +export async function deleteParticipantResultsBySportsSeasonId( + sportsSeasonId: string +): Promise { + 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 { + 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, + }); + } +} diff --git a/app/models/participant.ts b/app/models/participant.ts new file mode 100644 index 0000000..d008dfc --- /dev/null +++ b/app/models/participant.ts @@ -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 { + const db = database(); + const [participant] = await db + .insert(schema.participants) + .values(data) + .returning(); + return participant; +} + +export async function createManyParticipants(data: NewParticipant[]): Promise { + const db = database(); + return await db + .insert(schema.participants) + .values(data) + .returning(); +} + +export async function findParticipantById(id: string): Promise { + 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 { + 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 { + 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 +): Promise { + 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 { + const db = database(); + await db.delete(schema.participants).where(eq(schema.participants.id, id)); +} + +export async function copyParticipantsFromSeason( + sourceSportsSeasonId: string, + targetSportsSeasonId: string +): Promise { + // 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, + })) + ); +} diff --git a/app/models/season-sport.ts b/app/models/season-sport.ts new file mode 100644 index 0000000..477e699 --- /dev/null +++ b/app/models/season-sport.ts @@ -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 { + const db = database(); + const [link] = await db + .insert(schema.seasonSports) + .values({ + seasonId, + sportsSeasonId, + isRequired, + }) + .returning(); + return link; +} + +export async function linkMultipleSportsToSeason( + data: NewSeasonSport[] +): Promise { + const db = database(); + return await db + .insert(schema.seasonSports) + .values(data) + .returning(); +} + +export async function unlinkSportFromSeason( + seasonId: string, + sportsSeasonId: string +): Promise { + 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 { + 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 { + 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 { + 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 { + const db = database(); + await db.delete(schema.seasonSports).where(eq(schema.seasonSports.id, id)); +} + +export async function applySportsFromTemplate( + seasonId: string, + templateId: string +): Promise { + 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, + })) + ); +} diff --git a/app/models/season-template-sport.ts b/app/models/season-template-sport.ts new file mode 100644 index 0000000..948fee3 --- /dev/null +++ b/app/models/season-template-sport.ts @@ -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 { + const db = database(); + const [link] = await db + .insert(schema.seasonTemplateSports) + .values({ + templateId, + sportsSeasonId, + isRequired, + }) + .returning(); + return link; +} + +export async function addMultipleSportsToTemplate( + data: NewSeasonTemplateSport[] +): Promise { + const db = database(); + return await db + .insert(schema.seasonTemplateSports) + .values(data) + .returning(); +} + +export async function removeSportFromTemplate( + templateId: string, + sportsSeasonId: string +): Promise { + 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 { + 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 { + 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 { + 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 { + const db = database(); + await db.delete(schema.seasonTemplateSports).where(eq(schema.seasonTemplateSports.id, id)); +} diff --git a/app/models/season-template.ts b/app/models/season-template.ts new file mode 100644 index 0000000..c6f6638 --- /dev/null +++ b/app/models/season-template.ts @@ -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 { + const db = database(); + const [template] = await db + .insert(schema.seasonTemplates) + .values(data) + .returning(); + return template; +} + +export async function findSeasonTemplateById(id: string): Promise { + 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 { + 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 { + 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 { + const db = database(); + return await db.query.seasonTemplates.findMany({ + orderBy: (templates, { desc }) => [desc(templates.year)], + }); +} + +export async function updateSeasonTemplate( + id: string, + data: Partial +): Promise { + 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 { + return await updateSeasonTemplate(id, { isActive }); +} + +export async function deleteSeasonTemplate(id: string): Promise { + const db = database(); + await db.delete(schema.seasonTemplates).where(eq(schema.seasonTemplates.id, id)); +} diff --git a/app/models/season.ts b/app/models/season.ts index 28433bb..fa2ce26 100644 --- a/app/models/season.ts +++ b/app/models/season.ts @@ -6,6 +6,26 @@ export type Season = typeof schema.seasons.$inferSelect; export type NewSeason = typeof schema.seasons.$inferInsert; 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 { const db = database(); const [season] = await db @@ -77,3 +97,23 @@ export async function deleteSeason(id: string): Promise { const db = database(); await db.delete(schema.seasons).where(eq(schema.seasons.id, id)); } + +export async function findSeasonWithSportsSeasons( + id: string +): Promise { + 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; +} diff --git a/app/models/sport.ts b/app/models/sport.ts new file mode 100644 index 0000000..d4444cd --- /dev/null +++ b/app/models/sport.ts @@ -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 { + const db = database(); + const [sport] = await db + .insert(schema.sports) + .values(data) + .returning(); + return sport; +} + +export async function findSportById(id: string): Promise { + const db = database(); + return await db.query.sports.findFirst({ + where: eq(schema.sports.id, id), + }); +} + +export async function findSportBySlug(slug: string): Promise { + const db = database(); + return await db.query.sports.findFirst({ + where: eq(schema.sports.slug, slug), + }); +} + +export async function findAllSports(): Promise { + const db = database(); + return await db.query.sports.findMany({ + orderBy: (sports, { asc }) => [asc(sports.name)], + }); +} + +export async function findSportsByType(type: SportType): Promise { + 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 +): Promise { + 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 { + const db = database(); + await db.delete(schema.sports).where(eq(schema.sports.id, id)); +} diff --git a/app/models/sports-season.ts b/app/models/sports-season.ts new file mode 100644 index 0000000..defb811 --- /dev/null +++ b/app/models/sports-season.ts @@ -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 { + const db = database(); + const [sportsSeason] = await db + .insert(schema.sportsSeasons) + .values(data) + .returning(); + return sportsSeason; +} + +export async function findSportsSeasonById(id: string): Promise { + 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 { + 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 { + 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 { + 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 { + 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 +): Promise { + 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 { + return await updateSportsSeason(id, { status }); +} + +export async function deleteSportsSeason(id: string): Promise { + const db = database(); + await db.delete(schema.sportsSeasons).where(eq(schema.sportsSeasons.id, id)); +} + +export async function copyParticipantsFromPreviousSeason( + currentSeasonId: string, + previousSeasonId: string +): Promise { + 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, + })) + ); + } +} diff --git a/app/models/user.ts b/app/models/user.ts index 4265fe9..a8f3da8 100644 --- a/app/models/user.ts +++ b/app/models/user.ts @@ -106,3 +106,25 @@ export async function deleteUser(id: string): Promise { const db = database(); await db.delete(schema.users).where(eq(schema.users.id, id)); } + +export async function findAdmins(): Promise { + 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 { + const user = await findUserById(userId); + return user?.isAdmin ?? false; +} + +export async function isUserAdminByClerkId(clerkId: string): Promise { + const user = await findUserByClerkId(clerkId); + return user?.isAdmin ?? false; +} + +export async function setUserAdmin(userId: string, isAdmin: boolean): Promise { + return await updateUser(userId, { isAdmin }); +} diff --git a/database/schema.ts b/database/schema.ts index 810808c..b0bf947 100644 --- a/database/schema.ts +++ b/database/schema.ts @@ -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 export const users = pgTable("users", { @@ -9,6 +10,7 @@ export const users = pgTable("users", { firstName: varchar("first_name", { length: 255 }), lastName: varchar("last_name", { length: 255 }), imageUrl: varchar("image_url", { length: 512 }), + isAdmin: boolean("is_admin").notNull().default(false), createdAt: timestamp("created_at").defaultNow().notNull(), updatedAt: timestamp("updated_at").defaultNow().notNull(), }); @@ -21,6 +23,21 @@ export const seasonStatusEnum = pgEnum("season_status", [ "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", { id: uuid("id").primaryKey().defaultRandom(), name: varchar("name", { length: 255 }).notNull(), @@ -30,6 +47,16 @@ export const leagues = pgTable("leagues", { 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", { id: uuid("id").primaryKey().defaultRandom(), leagueId: uuid("league_id") @@ -37,6 +64,9 @@ export const seasons = pgTable("seasons", { .references(() => leagues.id, { onDelete: "cascade" }), year: integer("year").notNull(), 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(), 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 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], + }), +})); diff --git a/drizzle/0007_pink_nebula.sql b/drizzle/0007_pink_nebula.sql new file mode 100644 index 0000000..24f6903 --- /dev/null +++ b/drizzle/0007_pink_nebula.sql @@ -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 $$; diff --git a/drizzle/meta/0007_snapshot.json b/drizzle/meta/0007_snapshot.json new file mode 100644 index 0000000..b74b075 --- /dev/null +++ b/drizzle/meta/0007_snapshot.json @@ -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": {} + } +} \ No newline at end of file diff --git a/drizzle/meta/_journal.json b/drizzle/meta/_journal.json index b45ceda..fc685b4 100644 --- a/drizzle/meta/_journal.json +++ b/drizzle/meta/_journal.json @@ -50,6 +50,13 @@ "when": 1760241924414, "tag": "0006_needy_junta", "breakpoints": true + }, + { + "idx": 7, + "version": "7", + "when": 1760327817376, + "tag": "0007_pink_nebula", + "breakpoints": true } ] } \ No newline at end of file