Malatang part-time shift-patching tool - two rush blocks and a dead valley, stitched into a weekly rota from students' scattered availability
You are a senior front-end engineer. Build me (the scheduling
supervisor of a malatang shop) a single-file HTML shift-patching tool:
no external dependencies, no build step, save as .html and open by
double-click, works in mobile browsers, all computation local.
Tool name: Part-Time Shift Patch
1. People library (add/edit/delete, persisted in localStorage)
- One record per part-timer: name, availability windows (multiple
entries of "weekday + start-end," e.g. Mon 16:00-21:30), weekly
hour cap, minimum shift length (hours, default 3), notes
(class-schedule changes, etc.)
- A "pause scheduling" flag (leave someone out for a month without
deleting the record)
2. Demand table (per weekday x time block)
- Blocks are mine to define; defaults: lunch 10:30-14:00, valley
14:00-17:00, dinner 17:00-21:30
- Headcount per block per day, set separately (weekdays and weekends
usually differ)
- Valley defaults to 1-2 people, adjustable per day
3. One-click patch (the core button)
- Rules, executed in order:
1. Assign a block only to someone whose availability fully covers
it. Availability spanning block boundaries (e.g. 16:00-21:30
crossing late valley into dinner) may be split into consecutive
blocks for the same person with no gap
2. Never exceed a person's weekly cap; at the cap they drop out
of further patching
3. Skip any shift shorter than that person's minimum shift length
(not worth the trip)
4. If two same-day shifts for one person sit less than 1 hour
apart, merge them or keep only one
5. Within the hard rules above, spread shifts evenly (avoid one
person working six days while another gets one); when more
people are available than needed, prefer whoever has the
fewest scheduled hours this week
- Cells that cannot be filled (demand exists, nobody available) stay
empty and red, and a list below the grid shows weekday / block /
how many heads short
4. Rota output
- Week view: rows = people, columns = days, cells show shift times
and block
- Weekly hour totals per person, shown next to their cap
- Two flag types: yellow = hours below their running average, or
below a "promised minimum" I've marked; red = coverage gap
- "Export text" button: a plain-text weekly rota (one line per
person) to copy straight into the group chat
5. Acceptance tests (self-test all four before delivering)
1. Enter one person "available only Tue/Thu after 17:00," cap 8
hours, dinner demand 2 every day - they appear only Tue/Thu
dinners and drop out automatically once the cap is reached
2. Lunch demand 3 every day with only 2 people available - those
cells turn red and the gap list shows "lunch short 1" per day
3. One person available 16:00-21:30, valley needs 1, dinner needs
2 - they get one continuous valley-then-dinner shift, seamless
4. Clear localStorage and reload - an empty-state prompt appears,
not an error
Interface: primarily single-screen, stacked vertically on phones;
oversized buttons and text - this gets used in stolen minutes on
the shop floor, not at a desk.
Constraints:
- No CDNs, fonts, or icon libraries - fully offline
- No accounts, no cloud sync - localStorage is the only storage
- No pre-filled "industry headcounts" - every demand number comes
from me
- No built-in labor-law numbers - caps and minimums are all entered
by me; the tool executes my rules and makes no compliance
judgments of its own
Why it is written this way
Patching part-timers at a malatang shop is not the scheduling problem a convenience store or a bubble-tea shop has: demand concentrates into two rush blocks under four hours each with a dead valley between, and student availability almost never lines up cleanly with those blocks - "after 4" straddles valley and dinner, "weekends all day" covers all three. Filling a generic weekly grid by hand is a constrained crossword puzzle every single week. The heart of this tool is handing rule 1 - "full coverage to be assignable, spanning may be split seamlessly" - to code, leaving the human to deal only with what comes out red.
The red cells are the tool's most important output - more important than the rota itself. The list of unpatchable slots is precisely the supervisor's to-do list: recruit, negotiate availability, or cover it personally. If the tool quietly filled impossible cells with a "best-effort" person, the gap would become invisible - so the design leaves them empty and red rather than silently degrading.
Minimum shift length is a per-person field, not a global setting, because it is really a negotiated term: one student who lives nearby will come for 3 hours; someone riding 40 minutes of transit each way is losing money on anything under 4. Get this parameter wrong and people quietly stop coming - part-timers rarely quit over wages, they quit over "the trip wasn't worth it."
The even-spread rule (prefer whoever has the fewest hours this week) is baked in because the most morale-corrosive thing in a part-time crew is not having few shifts but "why does she get six days while I get one." Even spread isn't always optimal - skill levels differ - so it sits after the hard rules as a default tendency, not a law; the supervisor can still hand-tune before exporting.
"No built-in labor-law numbers" is deliberate. Part-time hour rules differ by jurisdiction, and a tool that remembers the law on the user's behalf is overstepping and a liability. The supervisor enters the caps; the code executes them. Compliance judgment stays with the human, arithmetic with the machine.
Variables
| Variable | Notes |
|---|---|
| Time blocks | The shop's own block layout; default lunch / valley / dinner. Delivery-heavy shops add a late-night block |
| Minimum shift length | Negotiated floor per person [hours]; default 3, or 4 for anyone with a long commute |
| Weekly hour cap | Per-person weekly ceiling [hours]; for students, their own preference and local rules decide |
| Promised minimum hours | A guaranteed shift count agreed at hiring; drives the yellow flag. Leave blank if never promised |