# New on the floor screens (work queue, assignment board, attendance)

Audit sections: "Work queue" (QUEUE-1…19), "Assignment board" (BOARD-1…13), "Attendance" (ATT-1…9) and the route line from "Order stages: a better way to see them".
Tests: `tests/Feature/FloorRedesignTest.php` (16 tests). The whole suite was re-run and passed.

## Shared definitions (also used by the dashboard)

Code: `app/Support/FloorBuckets.php`.

| Word on screen | Rule |
| --- | --- |
| Waiting / not taken | lot stage `ready` with nobody assigned |
| Taken, not started | `ready` with `assigned_to` set |
| In progress | `in_progress` or `sent_out` (at a vendor) |
| On hold | `on_hold` |
| Waiting days in red | the job has waited **more than** `ageing_warn_days` days (Settings: "Warn when a stage waits more than (days)") |

## What is new

| # | Feature | Where | Why (audit ID) | How it was tested |
| --- | --- | --- | --- | --- |
| 1 | Shared bucket rules and waiting limit (`FloorBuckets::apply / of / isOverWaitingLimit`) | `app/Support/FloorBuckets.php` | Queue "In progress" count must match the dashboard (it counted taken jobs too: 1,252 vs 809) | Pest: tab counts, bucket mapping, limit 3 → 3 days not red, 4 red |
| 2 | Queue tab "In progress" now counts only in progress + at vendor; new tab **Taken** for taken-not-started work | Work queue | QUEUE-5 + shared definition | Pest: counts per tab; taken job shows under Taken, not In progress |
| 3 | Route line component: a dot per stage, done ticked, current filled (blue here, violet at vendor, amber on hold, red when waiting past the limit), "Step 3 of 6 · next Plating (Gold)"; hover a tick for who finished it and when | `resources/views/components/route-line.blade.php`, `app/Support/RouteLine.php`; queue cards and list rows | QUEUE-9, route line | Pest: step, total, states and text; Blade render; visual check |
| 4 | List by default on 1024 px+ screens, cards below; "Cards \| List" in words; choice kept in the address (`?view=`) and remembered per person (session); list toggle hidden below 768 px | Work queue | QUEUE-1, QUEUE-2, QUEUE-19 | Pest: setLayout remembers; visual check 1366 and 390 |
| 5 | One-line 40 px list rows: Order · Customer · Item · Qty · Stage · Next · Due · Waiting · With · Note · actions; sticky Order column and sticky actions column | Work queue | QUEUE-2 | Visual check |
| 6 | One control row: status segmented control, "Department: All (717)" picker, 320 px search, layout toggle | Work queue | QUEUE-3, QUEUE-5, QUEUE-19 | Visual check |
| 7 | Department counts follow the current tab and search | Work queue | QUEUE-4 | Visual check (counts change with tab) |
| 8 | Sort control "Rush first / Due date / Waiting longest / Order no." (`?sort=`) and "717 jobs" at the top | Work queue | QUEUE-12 | Pest: waiting and due sorts order rows |
| 9 | One priority badge (RUSH, else High / Urgent), RUSH = 4 px red left edge; neutral card border; red only for late and past the waiting limit | Queue, board (`queue/priority-badge.blade.php`) | QUEUE-6, QUEUE-7 | Visual check |
| 10 | Card layout: customer 13 px, "500 pcs · lot 1" on one line, variant as text, vendor neutral with shop icon, no department chip, note one line that expands, cards size to content | Work queue | QUEUE-8, QUEUE-10, QUEUE-18, QUEUE-19 | Visual check |
| 11 | One filled button for the expected next step (Waiting: Take; taken / started: Done), the other outlined (icon-only in list rows) | Work queue | QUEUE-11 | Pest (existing): worker sees Take, not Assign |
| 12 | "Select 40 shown"; 44 px tap area on phones | Work queue | QUEUE-13 | Pest: "Select 1 shown" for supervisor |
| 13 | **Bulk actions only for people who assign work** (`queue.assign`, existing permission): checkboxes, bulk bar and `bulkTake` / `bulkComplete` server calls | Work queue | Task brief (approved behaviour change) | Pest: worker bulkTake → 403, nothing assigned; supervisor succeeds |
| 14 | Done dialog: 576 px, "Mark done · Packing", bold context line (order · item · lot · qty), instructions in one note box, "Came in: 500 pcs" as text, pcs suffixes, live "500 + 0 = 500 pcs ✓" check, no star on Rejected (still required), button "Mark done". "Work done by" defaults to the assignee, else the signed-in person (was already so; kept). Validation unchanged | Work queue | QUEUE-14, QUEUE-15 | Pest: heading, sum line, performed_by = assignee, completes |
| 15 | "Assign" visible in list rows for supervisors; divider before the red "Send back / rework"; 44 px ⋯ trigger on phones | Work queue | QUEUE-17 | Visual check; Pest (existing) worker never sees Assign |
| 16 | Board: two panes, Unassigned sticky on the left (420 px) with its own search row, people table on the right (name · attendance · ready / started / at vendor · jobs and pieces with a bar against the department average · Give); expand a row for that person's jobs | Assignment board | BOARD-5, BOARD-6, BOARD-9, BOARD-12 | Visual check |
| 17 | Three attendance states on the board: Present, Absent / On leave, Not marked | Assignment board | BOARD-2 | Pest |
| 18 | Absent person holding work: red line "Absent · 62 jobs stuck" + "Move ready jobs to pool" with a confirmation stating the count (releases their not-started jobs in this department through `TakeStage::release`) | Assignment board | BOARD-3 | Pest: confirmation text, job back in pool |
| 19 | Give button always shown, grey until something is ticked, then "Give 3" | Assignment board | BOARD-4 | Visual check |
| 20 | Person job rows: order · item · qty · due (red if late) · priority badge · status badge; "Back to pool" tooltip and "Unassign" on hover | Assignment board | BOARD-7, BOARD-8 | Visual check |
| 21 | **Auto-assign now asks first**, with a dry-run preview ("Assign 155 Casting jobs to 3 present people?" and "Bina 52 → 104" per person); outlined button; in a ⋮ menu on phones. The preview follows `AutoAssign::rebalance()` rules exactly | Assignment board, `app/Support/AutoAssignPreview.php` | BOARD-10 | Pest: preview totals and per-person "after" equal what the real run assigns |
| 22 | Department picker with waiting counts (same control as the queue) | Assignment board | BOARD-11 | Visual check |
| 23 | Phone: "Waiting (155) \| People (6)" switch and a sticky "Give 3 to… ▾" bar | Assignment board | BOARD-13 | Visual check 390 px |
| 24 | **Attendance third state "Leave"** and a way back to "not marked" (click the selected state again). Stored as `status = 'leave'` in the existing `attendance.status` column (string(10)); **no migration needed**. Auto-assign only counts `in` as present, so absent, leave and not marked are all "not present" exactly as absent was | Attendance | ATT-1 | Pest: leave stored, clear deletes the row; leave person not eligible and their auto-assigned work is re-balanced |
| 25 | **"All absent" asks first**: "Mark 6 people in Casting absent? Their 155 waiting jobs will be reassigned." (says so when auto-assign is off or for a past day); grey outlined "All present / All absent" | Attendance | ATT-2, ATT-9 | Pest: confirmation text, everyone marked out |
| 26 | Present = pale green with dark green text (dark: green 20% with light green text); main button dark green | Attendance | ATT-3 | Visual check |
| 27 | One table grouped by department (sticky group rows with present/total), 36 px person rows with status and "marked by · time", name search | Attendance | ATT-4 | Visual check |
| 28 | People in two departments shown once, under the first department, "also Polishing" in grey | Attendance | ATT-5 | Pest |
| 29 | One summary line: day · present · absent · on leave · not marked · the button · "Auto-assign: off" | Attendance | ATT-6 | Visual check |
| 30 | Day switcher "‹ 01 Nov 2026 ›" (`?date=`); past days read-only unless the person has `admin.users` (existing permission); no future days; work is re-balanced only for today; "Weekly off" badge from setting `weekly_off_days` (default Sunday) | Attendance | ATT-7 | Pest: supervisor blocked (403) on yesterday, owner can correct yesterday |
| 31 | All attendance, board and queue text wrapped in `__()` | All three pages | ATT-8 | Strings listed in the hand-off |

## Notes

- New setting key read (no UI yet): `weekly_off_days` (array of weekday numbers, 0 = Sunday). Default `[0]` when not set.
- No new permissions, no new migrations.
- Board load figures are per department on screen (jobs and pieces in this department), the department average is over people in the department who hold work.
- `Queue::routeInfo()` is kept for compatibility; new code uses `App\Support\RouteLine`.

## QA fixes (01 Nov), group X

| # | Feature | Where | Why (audit ID) | How it was tested |
|---|---------|-------|----------------|-------------------|
| 32 | Open ⋯ menu in the list sits above the sticky actions column of the rows below (the cell holding an open dropdown is raised to z-30) | Work queue, List | QA-X1 (P0) | Pest `…open menu above the sticky column (QA-X1, X2)`; screenshot 1366 light with the menu open |
| 33 | List fits 1,086 px at 1366 with no sideways scroll: fixed column widths (`table-fixed` + colgroup), Stage ≤ 200 px with truncation and a tooltip, Next merged into the Stage cell ("Packing → Dispatch"), Note shown as an amber icon with the text in a tooltip, priority/rush as a 16 px icon with tooltip, Due shown as date only (red when late, "Late" in the tooltip), "Send out" (tooltip "Send to vendor") as the compact vendor button; below 1,086 px it scrolls with a shadow on the sticky columns while more is hidden | Work queue, List | QA-X2 | Measured in Chromium: table 1086 px in a 1086 px box; Pest |
| 34 | First layout decided server-side: nothing remembered → List, or Cards when the user agent is a phone/tablet (`Queue::defaultLayout()`); new `$layoutAuto` flag lets the browser refine once (List from 1024 px, Cards below) without remembering it | Work queue | QA-X3 | Pest `picks the list for a new desktop user…` |
| 35 | Edge fade + chevron on the status tabs when they overflow (phones), tabs scroll sideways | Work queue (the board's Waiting/People switch and attendance have no overflowing tabs) | QA-X4 | Screenshot 390 light |
| 36 | Board Unassigned: item on line 1, customer (12 px grey) on line 2; pane 412 px (480 px on 2xl) | Assignment board | QA-X5 | Screenshots 1366 light/dark |
| 37 | Board people: zero Ready/Started/Vendor shown as "–"; Give column fixed width so ticking a job no longer shifts columns; phone shows attendance badge and load under the name and keeps Ready/Started/Vendor/Give on screen ("+ 3" button, word in tooltip) | Assignment board | QA-X5 | Screenshots 390 and 1366 |
| 38 | "Auto-assign now" disabled with tooltip "Auto-assign is off in Settings" when the mode is off (desktop button and phone menu item) | Assignment board | QA-X5 | Pest `disables Auto-assign with a reason when it is off` |
| 39 | Attendance "All present / All absent" are 24 px (36 px on phones) so they fit the group row; dark "Not marked" text gray-400 (≥ 4.5:1) | Attendance | QA-X6 | Screenshot 1366 dark |
| 40 | Dark "pcs"/"sets" unit text gray-400 (≥ 4.5:1) on the board and the queue list | Assignment board, Work queue | QA-X7 | Screenshot 1366 dark |
| 41 | Done dialog: instructions shown as read-only text in the amber note box (Html component), not an input | Work queue › Done | QA-X8 | Pest `shows the Done dialog instructions as an amber note` |
