Imported from emanuelsavianu/dottemanuelsavianu.it (
RUAP/AGENTS.md). Install upstream withnpx skills add emanuelsavianu/dottemanuelsavianu.it --skill RUAP. Copyright stays with the author.
AGENTS.md — RUAP Attività Diurne
Entry point
RUAP/index.htmlloads<script type="module" src="js/events.js">- Modules under
RUAP/js/:config.js,core-utils.js,engine.js,events.js,holidays.js,renderers.js,state.js - Module DAG:
config → holidays → core-utils → state → renderers ← engine ← events— no cycles
Config
RUAP/config.js— doctors, 2 places (M.S.Savino,Subbiano), 2 slots (mat/pom, 6h each), initial assignmentsCONFIG.doctorshaspreferredPlace: string | null— null means flexible, can work anywhere- No doctors have
isPool: truecurrently — pool logic exists but unused
Monthly config update from JSON export
When the user provides a RUAP JSON export (e.g. agosto.json) to set as defaults:
- Doctors — merge
unavailPeriodsper doctor ID, add any new doctors (including new IDs likeOlivieri), updatemonthlyBudgetif changed - Assignments — replace the entire
assignmentsobject with the export's assignments - Keep
places,slots, and doctor definitions (name, preferredPlace, availability, weeklyHours, etc.) unchanged unless the export clearly overrides them
engine.js — allocation algorithm
pickDoctorForSlot()has 2 priority tiers: (1) doctors who prefer this place OR have nopreferredPlace(flexible), (2) doctors who prefer another place- Within each tier, doctors are sorted by fewest assigned hours first (
assignedInTarget[doc.id]) — distributes work equitably regardless of budget size - Doctors with
preferredPlace: nullare flexible — they share priority with doctors who prefer that sede - If
isDoctorAvailableForSlot()returns false (unavailability period, wrong shift slot, holiday, weekend) orgetEffectiveRemaining(doc) ≤ 0, the doctor is skipped - Pool doctors (
isPool: true) are only used when no primary doctor is available
DOM gotchas
- Calendar grid ID:
cal-grid(notcalendar-grid). - Calendar title:
cal-title. - Navigation buttons:
cal-prev/cal-nextneed JS-attached listeners (not inlineonclick). - Sidebar week scroll:
sidebar-week-prev/sidebar-week-nextalso need JS-attached listeners. renderAll()must callupdateGeneraButtonLabel()or the "Genera mese" button shows a stale month name.- Month view only renders Mon–Fri (5 cells per week). Holidays show "Chiuso". Never render Sat/Sun cells.
Bug-hunting checklist
- DOM ID mismatch —
cal-grid(notcalendar-grid),cal-title,cal-prev/cal-next. inMonthguard —createSlotButton()only attaches click handlers wheninMonth === true.stopPropagationchain —closeAssignDropdowndocument listener fires on any click; slot handlers must calle.stopPropagation()first.- Module import/export integrity — Every function used in
renderers.jsand referenced inevents.jsmust be exported/imported. Inlineonclickhandlers needwindow.*exposure. hiddenclass ordering — Tailwind'shiddensetsdisplay: none. Alwaysremove('hidden')AFTER positioning.- Re-render wipes direct listeners —
container.innerHTML = ''destroys child listeners. Prefer delegation over directaddEventListener. - Live binding
SLOTS/PLACES— ES module live bindings fromstate.js— propagate automatically afterreloadPlaces()/reloadSlots(). e.currentTargetin delegated handlers — When usingclosest('[data-slot-key]'), read from the found ancestor, note.currentTarget.- HTML→JS button wiring — Every
<button id>must have anel('id')listener inevents.jsoronclickreferencing awindow.*function. pointer-events-noneon toast —#toast-containerhaspointer-events-none. Confirmation toasts needpointer-events-auto.- Allocation skips doctors with no preferredPlace — If a doctor has
preferredPlace: nulland gets no shifts, checkpickDoctorForSlot()priority grouping. - Availability table defaults to checked —
renderAvailabilityTable()must render checkboxes as checked when the doctor has noavailability(new doctor); an unchecked save produces a doctor that can never be assigned. - Single-day unavailability — Mini month calendar in the doctor modal (
#unavail-calendar,renderUnavailCalendar()) toggles single days; stored as{from, to}withfrom === toindoctor.unavailPeriods, merged with range rows insaveDoctorFromModal(). Unavailable doctors appear in the dropdown's "eccezioni" list with afa-banicon (revealed byassign-exception-btn).
CDN dependencies
- jsPDF, html2canvas, XLSX (SheetJS) loaded from CDN in
RUAP/index.html. Not vendored. If CDN fails, features show a toast error.
Other instruction files
CLAUDE.mdin this directory — RUAP data schema, budget system, import/export format, generate algorithm