import { pgTable, text, varchar, timestamp, jsonb, index, serial, boolean, integer, date, time, pgEnum, } from "drizzle-orm/pg-core"; import { relations } from "drizzle-orm"; import { createInsertSchema } from "drizzle-zod"; import { z } from "zod"; // Session storage table. // (IMPORTANT) This table is mandatory for Replit Auth, don't drop it. export const sessions = pgTable( "sessions", { sid: varchar("sid").primaryKey(), sess: jsonb("sess").notNull(), expire: timestamp("expire").notNull(), }, (table) => [index("IDX_session_expire").on(table.expire)], ); // User roles enum export const userRoleEnum = pgEnum("user_role", ["dj", "admin"]); // User storage table. // (IMPORTANT) This table is mandatory for Replit Auth, don't drop it. export const users = pgTable("users", { id: varchar("id").primaryKey().notNull(), email: varchar("email").unique(), firstName: varchar("first_name"), lastName: varchar("last_name"), profileImageUrl: varchar("profile_image_url"), displayName: varchar("display_name"), role: userRoleEnum("role").default("dj").notNull(), isActive: boolean("is_active").default(true).notNull(), maxEventsPerMonth: integer("max_events_per_month").default(2).notNull(), password: varchar("password"), tempPassword: varchar("temp_password"), needsPasswordChange: boolean("needs_password_change").default(false), createdAt: timestamp("created_at").defaultNow(), updatedAt: timestamp("updated_at").defaultNow(), }); // Event types table export const eventTypes = pgTable("event_types", { id: serial("id").primaryKey(), name: varchar("name").notNull(), description: text("description"), isActive: boolean("is_active").default(true).notNull(), createdAt: timestamp("created_at").defaultNow(), }); // Schedule templates table export const scheduleTemplates = pgTable("schedule_templates", { id: serial("id").primaryKey(), name: varchar("name").notNull(), description: text("description"), isActive: boolean("is_active").default(true).notNull(), createdAt: timestamp("created_at").defaultNow(), }); // Schedule template slots table export const scheduleTemplateSlots = pgTable("schedule_template_slots", { id: serial("id").primaryKey(), templateId: integer("template_id").references(() => scheduleTemplates.id).notNull(), dayOfWeek: integer("day_of_week").notNull(), // 0=Sunday, 1=Monday, etc. startTime: time("start_time").notNull(), endTime: time("end_time").notNull(), eventTypeId: integer("event_type_id").references(() => eventTypes.id).notNull(), createdAt: timestamp("created_at").defaultNow(), }); // Events table export const events = pgTable("events", { id: serial("id").primaryKey(), name: varchar("name").notNull(), eventTypeId: integer("event_type_id").references(() => eventTypes.id).notNull(), djId: varchar("dj_id").references(() => users.id).notNull(), date: date("date").notNull(), startTime: time("start_time").notNull(), endTime: time("end_time").notNull(), locationName: varchar("location_name").notNull(), locationAddress: text("location_address"), description: text("description"), isAssignedByAdmin: boolean("is_assigned_by_admin").default(false).notNull(), templateSlotId: integer("template_slot_id").references(() => scheduleTemplateSlots.id), createdAt: timestamp("created_at").defaultNow(), updatedAt: timestamp("updated_at").defaultNow(), }); // DJ social links table export const socialLinks = pgTable("social_links", { id: serial("id").primaryKey(), djId: varchar("dj_id").references(() => users.id).notNull(), label: varchar("label").notNull(), url: varchar("url").notNull(), createdAt: timestamp("created_at").defaultNow(), }); // DJ availability table export const availability = pgTable("availability", { id: serial("id").primaryKey(), djId: varchar("dj_id").references(() => users.id).notNull(), startDate: date("start_date").notNull(), endDate: date("end_date").notNull(), reason: text("reason"), createdAt: timestamp("created_at").defaultNow(), }); // DJ slot eligibility table export const slotEligibility = pgTable("slot_eligibility", { id: serial("id").primaryKey(), djId: varchar("dj_id").references(() => users.id).notNull(), templateSlotId: integer("template_slot_id").references(() => scheduleTemplateSlots.id).notNull(), isEligible: boolean("is_eligible").default(true).notNull(), createdAt: timestamp("created_at").defaultNow(), }); // Event removal requests table export const removalRequests = pgTable("removal_requests", { id: serial("id").primaryKey(), eventId: integer("event_id").references(() => events.id).notNull(), djId: varchar("dj_id").references(() => users.id).notNull(), reason: text("reason"), status: varchar("status").default("pending").notNull(), // pending, approved, denied reviewedBy: varchar("reviewed_by").references(() => users.id), reviewedAt: timestamp("reviewed_at"), createdAt: timestamp("created_at").defaultNow(), }); // DJ invitations table export const invitations = pgTable("invitations", { id: serial("id").primaryKey(), email: varchar("email").notNull(), token: varchar("token").notNull().unique(), name: varchar("name").notNull(), isUsed: boolean("is_used").default(false).notNull(), expiresAt: timestamp("expires_at").notNull(), createdBy: varchar("created_by").references(() => users.id).notNull(), createdAt: timestamp("created_at").defaultNow(), }); // Relations export const userRelations = relations(users, ({ many }) => ({ events: many(events), socialLinks: many(socialLinks), availability: many(availability), slotEligibility: many(slotEligibility), removalRequests: many(removalRequests), invitations: many(invitations), })); export const eventTypeRelations = relations(eventTypes, ({ many }) => ({ events: many(events), templateSlots: many(scheduleTemplateSlots), })); export const scheduleTemplateRelations = relations(scheduleTemplates, ({ many }) => ({ slots: many(scheduleTemplateSlots), })); export const scheduleTemplateSlotRelations = relations(scheduleTemplateSlots, ({ one, many }) => ({ template: one(scheduleTemplates, { fields: [scheduleTemplateSlots.templateId], references: [scheduleTemplates.id], }), eventType: one(eventTypes, { fields: [scheduleTemplateSlots.eventTypeId], references: [eventTypes.id], }), events: many(events), eligibility: many(slotEligibility), })); export const eventRelations = relations(events, ({ one, many }) => ({ dj: one(users, { fields: [events.djId], references: [users.id], }), eventType: one(eventTypes, { fields: [events.eventTypeId], references: [eventTypes.id], }), templateSlot: one(scheduleTemplateSlots, { fields: [events.templateSlotId], references: [scheduleTemplateSlots.id], }), removalRequests: many(removalRequests), })); export const socialLinkRelations = relations(socialLinks, ({ one }) => ({ dj: one(users, { fields: [socialLinks.djId], references: [users.id], }), })); export const availabilityRelations = relations(availability, ({ one }) => ({ dj: one(users, { fields: [availability.djId], references: [users.id], }), })); export const slotEligibilityRelations = relations(slotEligibility, ({ one }) => ({ dj: one(users, { fields: [slotEligibility.djId], references: [users.id], }), templateSlot: one(scheduleTemplateSlots, { fields: [slotEligibility.templateSlotId], references: [scheduleTemplateSlots.id], }), })); export const removalRequestRelations = relations(removalRequests, ({ one }) => ({ event: one(events, { fields: [removalRequests.eventId], references: [events.id], }), dj: one(users, { fields: [removalRequests.djId], references: [users.id], }), reviewer: one(users, { fields: [removalRequests.reviewedBy], references: [users.id], }), })); export const invitationRelations = relations(invitations, ({ one }) => ({ createdBy: one(users, { fields: [invitations.createdBy], references: [users.id], }), })); // Insert schemas export const insertUserSchema = createInsertSchema(users).omit({ createdAt: true, updatedAt: true, }); export const insertEventTypeSchema = createInsertSchema(eventTypes).omit({ id: true, createdAt: true, }); export const insertScheduleTemplateSchema = createInsertSchema(scheduleTemplates).omit({ id: true, createdAt: true, }); export const insertScheduleTemplateSlotSchema = createInsertSchema(scheduleTemplateSlots).omit({ id: true, createdAt: true, }); export const insertEventSchema = createInsertSchema(events).omit({ id: true, createdAt: true, updatedAt: true, }); export const insertSocialLinkSchema = createInsertSchema(socialLinks).omit({ id: true, createdAt: true, }); export const insertAvailabilitySchema = createInsertSchema(availability).omit({ id: true, createdAt: true, }); export const insertSlotEligibilitySchema = createInsertSchema(slotEligibility).omit({ id: true, createdAt: true, }); export const insertRemovalRequestSchema = createInsertSchema(removalRequests).omit({ id: true, createdAt: true, }); export const insertInvitationSchema = createInsertSchema(invitations).omit({ id: true, createdAt: true, }); // Update schemas export const updateUserSchema = insertUserSchema.partial(); export const updateEventSchema = insertEventSchema.partial(); export const updateEventTypeSchema = insertEventTypeSchema.partial(); export const updateScheduleTemplateSchema = insertScheduleTemplateSchema.partial(); export const updateRemovalRequestSchema = insertRemovalRequestSchema.partial(); // Type exports export type UpsertUser = z.infer; export type User = typeof users.$inferSelect; export type InsertUser = z.infer; export type UpdateUser = z.infer; export type EventType = typeof eventTypes.$inferSelect; export type InsertEventType = z.infer; export type UpdateEventType = z.infer; export type ScheduleTemplate = typeof scheduleTemplates.$inferSelect; export type InsertScheduleTemplate = z.infer; export type UpdateScheduleTemplate = z.infer; export type ScheduleTemplateSlot = typeof scheduleTemplateSlots.$inferSelect; export type InsertScheduleTemplateSlot = z.infer; export type Event = typeof events.$inferSelect; export type InsertEvent = z.infer; export type UpdateEvent = z.infer; export type SocialLink = typeof socialLinks.$inferSelect; export type InsertSocialLink = z.infer; export type Availability = typeof availability.$inferSelect; export type InsertAvailability = z.infer; export type SlotEligibility = typeof slotEligibility.$inferSelect; export type InsertSlotEligibility = z.infer; export type RemovalRequest = typeof removalRequests.$inferSelect; export type InsertRemovalRequest = z.infer; export type UpdateRemovalRequest = z.infer; export type Invitation = typeof invitations.$inferSelect; export type InsertInvitation = z.infer;