Files
DJ-Management-Tool/shared/schema.ts
T
spliceboti 60b5735588 Add user management for activation, deactivation, and deletion
Introduce API endpoints and storage methods for setting user passwords, soft deactivation (hiding availability), and hard deletion (removing all associated future data).

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 3a22ac80-cd1d-4441-9e36-f24fc2f4c3de
Replit-Commit-Checkpoint-Type: intermediate_checkpoint
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/3478f7c3-db8c-4fca-9165-3adbdf1b5829/3a22ac80-cd1d-4441-9e36-f24fc2f4c3de/gBqmpbl
2025-09-12 20:36:14 +00:00

342 lines
11 KiB
TypeScript

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<typeof insertUserSchema>;
export type User = typeof users.$inferSelect;
export type InsertUser = z.infer<typeof insertUserSchema>;
export type UpdateUser = z.infer<typeof updateUserSchema>;
export type EventType = typeof eventTypes.$inferSelect;
export type InsertEventType = z.infer<typeof insertEventTypeSchema>;
export type UpdateEventType = z.infer<typeof updateEventTypeSchema>;
export type ScheduleTemplate = typeof scheduleTemplates.$inferSelect;
export type InsertScheduleTemplate = z.infer<typeof insertScheduleTemplateSchema>;
export type UpdateScheduleTemplate = z.infer<typeof updateScheduleTemplateSchema>;
export type ScheduleTemplateSlot = typeof scheduleTemplateSlots.$inferSelect;
export type InsertScheduleTemplateSlot = z.infer<typeof insertScheduleTemplateSlotSchema>;
export type Event = typeof events.$inferSelect;
export type InsertEvent = z.infer<typeof insertEventSchema>;
export type UpdateEvent = z.infer<typeof updateEventSchema>;
export type SocialLink = typeof socialLinks.$inferSelect;
export type InsertSocialLink = z.infer<typeof insertSocialLinkSchema>;
export type Availability = typeof availability.$inferSelect;
export type InsertAvailability = z.infer<typeof insertAvailabilitySchema>;
export type SlotEligibility = typeof slotEligibility.$inferSelect;
export type InsertSlotEligibility = z.infer<typeof insertSlotEligibilitySchema>;
export type RemovalRequest = typeof removalRequests.$inferSelect;
export type InsertRemovalRequest = z.infer<typeof insertRemovalRequestSchema>;
export type UpdateRemovalRequest = z.infer<typeof updateRemovalRequestSchema>;
export type Invitation = typeof invitations.$inferSelect;
export type InsertInvitation = z.infer<typeof insertInvitationSchema>;