105 lines
2.6 KiB
TypeScript
105 lines
2.6 KiB
TypeScript
// 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];
|