// Check-ins from the backend's JSON (wire.ts) to Context's view types (types.ts). import { toViewDay, viewHours } from "./adapt"; import type * as T from "./types"; import type * as W from "./wire"; const NO_LIMITS: T.CheckInLimits = { usedToday: 0, usedThisWeek: 0, maxPerDay: 1, maxPerWeek: 3, nextPossibleAt: null }; /** YCI-5. A clinic-added patient has no app, so no patient zone or hours: the clinic's zone stands in. */ export function windowFromWire(w: W.PlanTemplate["window"]): T.WindowRules { return { patientTimeZone: w.patientTimeZone ?? w.clinicTimeZone, clinicTimeZone: w.clinicTimeZone, clinicHours: viewHours(w.clinicHours), alertWatchHours: viewHours(w.alertWatchHours), dayStart: w.dayStart ?? "08:00", dayEnd: w.dayEnd ?? "20:00", // Quiet hours the patient turned off read as an empty span. quietHours: w.quietHours ?? { start: "00:00", end: "00:00" }, blockedTimes: (w.blockedTimes ?? []).map((b) => ({ day: b.day === null ? null : toViewDay(b.day), start: b.start, end: b.end, label: b.label ?? "" })), defaultExpiryHours: w.defaultExpiryHours, maxExpiryHours: w.maxExpiryHours, known: w.patientTimeZone !== null, }; } export const planFromWire = (w: W.PlanTemplate): T.CheckInPlanTemplate => ({ ...w, feelingFollowUps: w.feelingFollowUps ?? [], window: windowFromWire(w.window), limits: w.limits ?? NO_LIMITS, maxQuestions: w.maxQuestions ?? 10, }); export const noteFromWire = (n: W.CheckInNote): T.CheckInNote => ({ ...n, validation: n.validation ?? "matched", endedEarly: n.endedEarly ?? false, }); const TIERS = new Set(["get_help_now", "today", "this_week", "good_to_know"]); /** The snapshot, with the linked findings' tiers and the alerts already sent. */ export function checkInFromWire(w: W.CheckIn): T.CheckIn { const { script: _script, alerts, ...rest } = w; return { ...rest, plan: { ...w.plan, linkedTiers: (w.plan.linkedTiers ?? []).filter((tier): tier is T.Tier => TIERS.has(tier)) }, notes: w.notes.map(noteFromWire), alerts: (alerts ?? []).filter((a) => a.message).map((a) => ({ id: a.id, at: a.at, kind: a.kind ?? "alert", message: a.message! })), }; } export function eventFromWire(e: W.CheckInEvent): T.CheckInEvent { if (e.type === "note" || e.type === "note_updated") return { ...e, note: noteFromWire(e.note) }; return e; } export const updatesFromWire = (w: W.CheckInUpdates): T.CheckInUpdates => ({ events: w.events.map(eventFromWire), lastEventId: w.lastEventId });