mirror of
https://github.com/temetro/temetro.git
synced 2026-08-11 19:18:03 +00:00
feat: org-scoped appointments backend, wire appointments page
Add the appointments table, validation, service and CRUD routes (/api/appointments, RBAC-gated) and the matching frontend data module. The appointments page now loads and persists real data; KPIs are computed from it and the schedule/calendar anchor to the real current date. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,35 @@
|
||||
import { index, pgTable, text, timestamp, uuid } from "drizzle-orm/pg-core";
|
||||
|
||||
import type { AppointmentStatus } from "../../types/appointment.js";
|
||||
import { organization, user } from "./auth.js";
|
||||
|
||||
// One row per scheduled visit, scoped to a clinic (organization). Patient
|
||||
// identity is denormalized (name/initials/file number) so the schedule renders
|
||||
// without joining; `date`/`time` are stored as plain strings to match the UI's
|
||||
// local-date model exactly (no timezone drift).
|
||||
export const appointments = pgTable(
|
||||
"appointments",
|
||||
{
|
||||
id: uuid("id").primaryKey().defaultRandom(),
|
||||
organizationId: text("organization_id")
|
||||
.notNull()
|
||||
.references(() => organization.id, { onDelete: "cascade" }),
|
||||
patientFileNumber: text("patient_file_number").notNull().default(""),
|
||||
patientName: text("patient_name").notNull(),
|
||||
patientInitials: text("patient_initials").notNull(),
|
||||
date: text("date").notNull(), // YYYY-MM-DD
|
||||
time: text("time").notNull(), // HH:mm
|
||||
type: text("type").notNull(),
|
||||
provider: text("provider").notNull(),
|
||||
status: text("status").$type<AppointmentStatus>().notNull(),
|
||||
createdBy: text("created_by").references(() => user.id, {
|
||||
onDelete: "set null",
|
||||
}),
|
||||
createdAt: timestamp("created_at").defaultNow().notNull(),
|
||||
updatedAt: timestamp("updated_at")
|
||||
.defaultNow()
|
||||
.$onUpdate(() => new Date())
|
||||
.notNull(),
|
||||
},
|
||||
(t) => [index("appointments_org_date_idx").on(t.organizationId, t.date)],
|
||||
);
|
||||
@@ -1,3 +1,4 @@
|
||||
export * from "./auth.js";
|
||||
export * from "./patients.js";
|
||||
export * from "./notes.js";
|
||||
export * from "./appointments.js";
|
||||
|
||||
Reference in New Issue
Block a user