mirror of
https://github.com/temetro/temetro.git
synced 2026-08-26 02:17:22 +00:00
feat: patient blood type & phone + clinic location setting (v0.9.0)
Patient record: - Add `bloodType` and `phone` to the patient model (schema, canonical types on both backend + frontend, zod validation). `phone` is a demographic field (reception can read/write); `bloodType` is clinical PHI, redacted for the reception role. Surface both in the record sheet, chat summary card, and the add/edit patient form. Migration 0033. Clinic location: - New org-scoped `clinic_settings` table (address/city/country + optional lat/long), service, and routes: GET /api/clinic/settings (any clinician) and PUT /api/clinic/location (owner/admin). Edited in Settings → Signing → Clinic location. Consumed later by the wallet app. Migration 0034. i18n: - Translate all new keys into every shipped locale (en/de/fr/ar/so) and document the "translate into every locale" rule in frontend/CLAUDE.md. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,61 @@
|
||||
import { Router } from "express";
|
||||
import { z } from "zod";
|
||||
|
||||
import {
|
||||
requireAuth,
|
||||
requireOrg,
|
||||
requirePermission,
|
||||
} from "../middleware/auth.js";
|
||||
import { recordActivity } from "../services/activity.js";
|
||||
import * as clinicSettings from "../services/clinic-settings.js";
|
||||
|
||||
export const clinicRouter = Router();
|
||||
|
||||
clinicRouter.use(requireAuth, requireOrg);
|
||||
|
||||
// The clinic's settings (currently just its location). Readable by any
|
||||
// clinician so the app/UI can display the clinic address.
|
||||
clinicRouter.get(
|
||||
"/settings",
|
||||
requirePermission({ patient: ["read"] }),
|
||||
async (req, res, next) => {
|
||||
try {
|
||||
res.json(await clinicSettings.getClinicSettings(req.organizationId!));
|
||||
} catch (err) {
|
||||
next(err);
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
// Set the clinic's location — owner/admin only (gated on the org-update
|
||||
// statement, same as signing-key rotation / network toggle).
|
||||
const locationSchema = z.object({
|
||||
address: z.string().trim().max(200).default(""),
|
||||
city: z.string().trim().max(120).default(""),
|
||||
country: z.string().trim().max(120).default(""),
|
||||
latitude: z.number().min(-90).max(90).nullable().default(null),
|
||||
longitude: z.number().min(-180).max(180).nullable().default(null),
|
||||
});
|
||||
|
||||
clinicRouter.put(
|
||||
"/location",
|
||||
requirePermission({ organization: ["update"] }),
|
||||
async (req, res, next) => {
|
||||
try {
|
||||
const location = locationSchema.parse(req.body);
|
||||
const view = await clinicSettings.setClinicLocation(
|
||||
req.organizationId!,
|
||||
location,
|
||||
);
|
||||
await recordActivity({
|
||||
orgId: req.organizationId!,
|
||||
actor: { id: req.user!.id, name: req.user!.name },
|
||||
action: "Updated the clinic location",
|
||||
entityType: "settings",
|
||||
});
|
||||
res.json(view);
|
||||
} catch (err) {
|
||||
next(err);
|
||||
}
|
||||
},
|
||||
);
|
||||
Reference in New Issue
Block a user