Provide admin tools to manage and resend DJ invitations easily

Implements invitation management features, including resending and manual user creation, via new API endpoints and React components.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 3a22ac80-cd1d-4441-9e36-f24fc2f4c3de
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/3478f7c3-db8c-4fca-9165-3adbdf1b5829/dbb6f90a-b277-4de1-a273-07d2fc2d56d1.jpg
This commit is contained in:
spliceboti
2025-07-10 00:46:13 +00:00
parent ec2ab0e9f4
commit 9945ecbca7
5 changed files with 461 additions and 20 deletions
+33
View File
@@ -42,7 +42,9 @@ import { eq, and, gte, lte, desc, asc, sql, inArray } from "drizzle-orm";
export interface IStorage {
// User operations (IMPORTANT: mandatory for Replit Auth)
getUser(id: string): Promise<User | undefined>;
getUserByEmail(email: string): Promise<User | undefined>;
upsertUser(user: UpsertUser): Promise<User>;
createUser(user: InsertUser): Promise<User>;
updateUser(id: string, updates: UpdateUser): Promise<User>;
getAllDJs(): Promise<User[]>;
deactivateUser(id: string): Promise<void>;
@@ -108,7 +110,10 @@ export interface IStorage {
// Invitation operations
createInvitation(invitation: InsertInvitation): Promise<Invitation>;
getInvitation(id: number): Promise<Invitation | undefined>;
getInvitationByToken(token: string): Promise<Invitation | undefined>;
updateInvitation(id: number, updates: Partial<InsertInvitation>): Promise<Invitation>;
deleteInvitation(id: number): Promise<void>;
markInvitationAsUsed(id: number): Promise<void>;
getActiveInvitations(): Promise<Invitation[]>;
@@ -134,6 +139,16 @@ export class DatabaseStorage implements IStorage {
return user;
}
async getUserByEmail(email: string): Promise<User | undefined> {
const [user] = await db.select().from(users).where(eq(users.email, email));
return user;
}
async createUser(userData: InsertUser): Promise<User> {
const [user] = await db.insert(users).values(userData).returning();
return user;
}
async upsertUser(userData: UpsertUser): Promise<User> {
const [user] = await db
.insert(users)
@@ -450,11 +465,29 @@ export class DatabaseStorage implements IStorage {
return newInvitation;
}
async getInvitation(id: number): Promise<Invitation | undefined> {
const [invitation] = await db.select().from(invitations).where(eq(invitations.id, id));
return invitation;
}
async getInvitationByToken(token: string): Promise<Invitation | undefined> {
const [invitation] = await db.select().from(invitations).where(eq(invitations.token, token));
return invitation;
}
async updateInvitation(id: number, updates: Partial<InsertInvitation>): Promise<Invitation> {
const [invitation] = await db
.update(invitations)
.set(updates)
.where(eq(invitations.id, id))
.returning();
return invitation;
}
async deleteInvitation(id: number): Promise<void> {
await db.delete(invitations).where(eq(invitations.id, id));
}
async markInvitationAsUsed(id: number): Promise<void> {
await db.update(invitations).set({ isUsed: true }).where(eq(invitations.id, id));
}