// Shared TypeScript types between client and server. // Type-only — safe to import from both sides without bundling runtime code. export type UserRole = "user" | "admin"; export type SubscriptionPlan = "trial" | "basic" | "pro"; export type SubscriptionStatus = | "trialing" | "active" | "past_due" | "canceled" | "expired"; export type QueueEntryStatus = | "waiting" | "called" | "in_consultation" | "done" | "absent" | "canceled"; export type AnalyticsEventType = | "patient_joined" | "patient_called" | "patient_done" | "patient_absent" | "queue_opened" | "queue_closed"; export interface PublicUser { id: number; email: string; name: string | null; role: UserRole; } export interface ClinicSummary { id: number; name: string; color: string | null; isQueueOpen: boolean; avgConsultationMinutes: number | null; } export interface PublicQueueEntry { id: number; ticketNumber: number; status: QueueEntryStatus; position: number; estimatedWaitMinutes: number | null; patientName: string | null; } // ─── Socket.io event payloads ──────────────────────────────────────────────── export interface QueueUpdatePayload { clinic: ClinicSummary | unknown; queue: PublicQueueEntry[]; callingNow: { ticketNumber: number; patientName: string | null } | null; waitingCount: number; } export interface PatientUpdatePayload { entry: { id: number; ticketNumber: number; status: QueueEntryStatus; position: number; estimatedWaitMinutes: number | null; }; position: number; estimatedWaitMinutes: number | null; callingNow: { ticketNumber: number; patientName: string | null } | null; waitingCount: number; } export interface PatientCalledPayload { ticketNumber: number; clinicId: number; } export interface QrRotatedPayload { qrToken: string; qrTokenExpiresAt: string | Date | null; } export const SOCKET_EVENTS = { // Doctor / display rooms QUEUE_UPDATE: "queue:update", QR_ROTATED: "qr:rotated", // Patient room PATIENT_UPDATE: "patient:update", PATIENT_CALLED: "patient:called", PATIENT_APPROACHING: "patient:approaching", PATIENT_ABSENT: "patient:absent", PATIENT_DONE: "patient:done", // Subscription topics CLINIC_SUBSCRIBE: "clinic:subscribe", CLINIC_UNSUBSCRIBE: "clinic:unsubscribe", DISPLAY_SUBSCRIBE: "display:subscribe", DISPLAY_UNSUBSCRIBE: "display:unsubscribe", PATIENT_SUBSCRIBE: "patient:subscribe", PATIENT_UNSUBSCRIBE: "patient:unsubscribe", } as const; export type SocketEventName = (typeof SOCKET_EVENTS)[keyof typeof SOCKET_EVENTS];