Modified by www.SourceFiles.app
This commit is contained in:
@@ -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")}`;
|
||||
};
|
||||
Reference in New Issue
Block a user