// 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<string>(["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 });