diff --git a/.importlinter b/.importlinter index d964dc3c..ac2796ba 100644 --- a/.importlinter +++ b/.importlinter @@ -13,6 +13,7 @@ name = Modules may reach each other ONLY through contracts.py type = forbidden source_modules = modules.placement + modules.elm modules.directory modules.accesscontrol forbidden_modules = @@ -21,6 +22,11 @@ forbidden_modules = modules.placement.selectors modules.placement.api modules.placement.domain + modules.elm.models + modules.elm.services + modules.elm.selectors + modules.elm.api + modules.elm.domain modules.directory.models modules.directory.services modules.directory.api @@ -38,6 +44,7 @@ type = forbidden source_modules = # Every module's domain, not just the first one written. modules.placement.domain + modules.elm.domain forbidden_modules = django rest_framework @@ -66,3 +73,13 @@ layers = modules.placement.selectors modules.placement.models modules.placement.domain + +[importlinter:contract:elm-layers] +name = Layering inside elm +type = layers +layers = + modules.elm.api + modules.elm.services + modules.elm.selectors + modules.elm.models + modules.elm.domain diff --git a/client/src/app/registry.ts b/client/src/app/registry.ts index e76d32bf..62a76ddf 100644 --- a/client/src/app/registry.ts +++ b/client/src/app/registry.ts @@ -17,4 +17,9 @@ export const MODULE_REGISTRY: Record = { basePath: "/placement", load: () => import("../modules/placement/routes"), }, + elm: { + code: "elm", + basePath: "/elm", + load: () => import("../modules/elm/routes"), + }, }; diff --git a/client/src/modules/elm/pages/AdminPage.tsx b/client/src/modules/elm/pages/AdminPage.tsx new file mode 100644 index 00000000..8e59c34f --- /dev/null +++ b/client/src/modules/elm/pages/AdminPage.tsx @@ -0,0 +1,72 @@ +import React from "react"; +import { + Card, + Title, + Table, + Badge, + Button, + Stack, + Text, + Group, + TextInput, + Select, +} from "@mantine/core"; + +export default function AdminPage() { + const holidays = [ + { date: "2026-01-26", name: "Republic Day", type: "closed" }, + { date: "2026-03-25", name: "Holi", type: "closed" }, + { date: "2026-04-14", name: "Ambedkar Jayanti", type: "restricted" }, + { date: "2026-08-15", name: "Independence Day", type: "closed" }, + { date: "2026-10-02", name: "Gandhi Jayanti", type: "closed" }, + ]; + + return ( + + Leave Administration & Calendars + + Maintain annual holiday calendars, publish Restricted Holidays (RH), and execute year-end processing. + + + + + Published Holiday Calendar (2026) + + + + + + + Date + Holiday Name + Type + + + + {holidays.map((h) => ( + + {h.date} + {h.name} + + + {h.type === "closed" ? "Closed Holiday" : "Restricted Holiday (RH)"} + + + + ))} + +
+
+ + + Year-End Leave Ledger Processing (EVT-01) + + Lapses unused CL/RH/SCL, converts Faculty VL to EL at 2:1 ratio, and carries forward EL/COL to next calendar year. + + + +
+ ); +} diff --git a/client/src/modules/elm/pages/ApplyLeavePage.tsx b/client/src/modules/elm/pages/ApplyLeavePage.tsx new file mode 100644 index 00000000..20819a26 --- /dev/null +++ b/client/src/modules/elm/pages/ApplyLeavePage.tsx @@ -0,0 +1,151 @@ +import React, { useState } from "react"; +import { + Card, + Title, + TextInput, + Select, + Button, + Stack, + Text, + Checkbox, + Group, + Textarea, + Notification, +} from "@mantine/core"; + +export default function ApplyLeavePage() { + const [category, setCategory] = useState("CL"); + const [startDate, setStartDate] = useState(""); + const [endDate, setEndDate] = useState(""); + const [isHalfDay, setIsHalfDay] = useState(false); + const [halfDayPeriod, setHalfDayPeriod] = useState("first_half"); + const [reason, setReason] = useState(""); + const [leavingStation, setLeavingStation] = useState(false); + const [stationAddress, setStationAddress] = useState(""); + const [emergencyPhone, setEmergencyPhone] = useState(""); + const [substituteId, setSubstituteId] = useState(""); + const [submitted, setSubmitted] = useState(false); + + const handleSubmit = (e: React.FormEvent) => { + e.preventDefault(); + setSubmitted(true); + }; + + return ( + + Apply for Leave + + Submit a new leave application with role-based routing and substitute nomination. + + + {submitted && ( + setSubmitted(false)}> + Your leave application has been submitted for review. + + )} + + +
+ + + )} + + )} + +