This commit is contained in:
2026-08-22 23:10:29 +00:00
parent b1a45e1306
commit a916a2098f
-116
View File
@@ -1,116 +0,0 @@
import type { Database } from "@/integrations/supabase/types";
export type PlanType = Database["public"]["Enums"]["plan_type"];
export type PlanStatus = Database["public"]["Enums"]["plan_status"];
export type GoalStatus = Database["public"]["Enums"]["plan_goal_status"];
export type MeetingType = Database["public"]["Enums"]["plan_meeting_type"];
export const PLAN_TYPE_LABEL: Record<PlanType, string> = {
iep: "IEP",
section_504: "504 Plan",
};
export const PLAN_STATUS_LABEL: Record<PlanStatus, string> = {
draft: "Draft",
active: "Active",
archived: "Archived",
};
export const GOAL_STATUS_LABEL: Record<GoalStatus, string> = {
not_started: "Not started",
in_progress: "In progress",
met: "Met",
not_met: "Not met",
discontinued: "Discontinued",
};
export const MEETING_TYPE_LABEL: Record<MeetingType, string> = {
initial: "Initial",
annual_review: "Annual review",
reevaluation: "Re-evaluation",
eligibility: "Eligibility",
amendment: "Amendment",
other: "Other",
};
export const ACCOMMODATION_CATEGORIES = [
{ value: "instructional", label: "Instructional" },
{ value: "environmental", label: "Environmental" },
{ value: "assessment", label: "Assessment / testing" },
{ value: "behavioral", label: "Behavioral" },
{ value: "other", label: "Other" },
];
export const accommodationLabel = (v: string) =>
ACCOMMODATION_CATEGORIES.find((c) => c.value === v)?.label ?? v;
// ── Compliance clocks ───────────────────────────────────────────────────────
// A date within this many days counts as "due soon" rather than merely upcoming.
export const DUE_SOON_DAYS = 30;
export type ComplianceState = "none" | "ok" | "due_soon" | "overdue";
// "YYYY-MM-DD" through `new Date()` parses as UTC midnight, which lands on the
// previous day for anyone west of Greenwich. Build a local date instead.
function parseISODate(d: string): Date {
const [y, m, day] = d.split("-").map(Number);
return new Date(y, m - 1, day);
}
export function daysUntil(date: string | null | undefined, today = new Date()): number | null {
if (!date) return null;
const midnight = new Date(today.getFullYear(), today.getMonth(), today.getDate());
return Math.round((parseISODate(date).getTime() - midnight.getTime()) / 86_400_000);
}
export function complianceState(
date: string | null | undefined,
today = new Date(),
): ComplianceState {
const d = daysUntil(date, today);
if (d === null) return "none";
if (d < 0) return "overdue";
if (d <= DUE_SOON_DAYS) return "due_soon";
return "ok";
}
// EmbraceIEP shows overdue dates in red italics; due-soon gets an amber warning.
export const COMPLIANCE_CLASS: Record<ComplianceState, string> = {
none: "text-muted-foreground",
ok: "text-foreground",
due_soon: "text-amber-600 font-medium",
overdue: "text-destructive font-semibold italic",
};
export function complianceLabel(state: ComplianceState, days: number | null): string {
switch (state) {
case "overdue":
return `${Math.abs(days ?? 0)} day${Math.abs(days ?? 0) === 1 ? "" : "s"} overdue`;
case "due_soon":
return days === 0 ? "Due today" : `Due in ${days} day${days === 1 ? "" : "s"}`;
case "ok":
return "On track";
default:
return "Not set";
}
}
export const formatDate = (d: string | null | undefined) =>
d ? parseISODate(d).toLocaleDateString() : "—";
// Default compliance clocks when a plan takes effect: annual review at +1 year,
// re-evaluation at +3 years (the IDEA triennial). Both are editable afterwards.
export function defaultReviewDates(effective: string): { annual: string; reeval: string } {
const iso = (dt: Date) =>
`${dt.getFullYear()}-${String(dt.getMonth() + 1).padStart(2, "0")}-${String(dt.getDate()).padStart(2, "0")}`;
const base = parseISODate(effective);
const annual = new Date(base);
annual.setFullYear(annual.getFullYear() + 1);
const reeval = new Date(base);
reeval.setFullYear(reeval.getFullYear() + 3);
return { annual: iso(annual), reeval: iso(reeval) };
}
export const todayISO = () => {
const t = new Date();
return `${t.getFullYear()}-${String(t.getMonth() + 1).padStart(2, "0")}-${String(t.getDate()).padStart(2, "0")}`;
};