Files
TKB_plan/docs/plans/2026-04-22-half-cell-marks-design.md
Docker Config Backup 3d306e641c feat: add Kropáček Ondřej + May–Jul feature work (half-cell marks, copy/paste, exports, roles)
New worker: Kropáček Ondřej (TKB, part-time student) inserted between
Dvořák Václav and Vondrák Pavel in data.json, the full-month Excel
template (new row 13, everything below shifted) and the docházka
template (13 person rows). Not added to the harmonogram/CIS roster —
he has no CIS personal number.

Also checkpoints the uncommitted work deployed to production between
May and July 2026:
- half-cell day/night preference marks (color + text per half)
- cell copy/paste (Ctrl+C/V, context menu), incl. from info rows
- light/dark theme toggle, TKB people filter, 162 filter
- full-month Excel export (template) and harmonogram export for CIS
- docházka export: half-time workers, retired flag, contractor handling
- third login role "cis" (viewer + export access)
- retired flag hides a person from UI/FPD while keeping past data

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-17 13:02:52 +02:00

4.3 KiB
Raw Blame History

Half-cell day/night preference marks — Design

Date: 2026-04-22 Status: approved, ready to implement

Problem

In the original Excel schedule, each day cell was split horizontally (left = night, right = day). Users marked preferences/obstacles by filling the appropriate half with a color before shift planning began.

In the current app, each day = one cell. Users can only express day-vs-night preferences via cell comments (small blue triangle), which is not visual at a glance and therefore "annoying."

Multiple users have requested restoring the Excel behavior.

Decisions

  1. Coexist with shifts — preference marks stay visible after a shift is assigned (so we can see whether we honored or violated the request).
  2. Free color from palette — same flexibility as the existing whole-cell color picker; semantics are user-defined.
  3. Horizontal split: left = night, right = day — matches the original Excel.
  4. Visual when shift is assigned: corner triangles — full shift color fills the cell; small ~8×8 px triangles in the bottom corners indicate the marks (bottom-left = night, bottom-right = day).
  5. Toggle in context menu — segmented control Celá | Noční | Denní above the color palette selects which field the next color click updates.

Data model

CellValue (in types.ts) gains two optional fields:

interface CellValue {
  v?: string
  color?: string        // existing — full-cell background
  dayColor?: string     // NEW — right half / day mark
  nightColor?: string   // NEW — left half / night mark
}

The change is purely additive. Existing JSON files load unchanged.

Rendering rules

State Look
empty + no marks empty (current)
dayColor and/or nightColor set, no shift left half = nightColor, right half = dayColor (each independent; missing half = transparent or color fallback)
shift assigned, no marks full shift color (current)
shift assigned + marks full shift color + 8 px triangles: bottom-left = night, bottom-right = day

Priority for picking renderer:

  1. If dayColor || nightColor → split-half mode
  2. Else if color → full-cell color (current behavior)
  3. Else → empty

Interaction

Right-click cell → existing context menu, with new segmented toggle above the color palette:

Barva:
  [ Celá ] [ Noční ] [ Denní ]    ← default: Celá
  ● ● ● ● ● ● ● [Bez barvy]
  • Toggle selects target field (color, nightColor, dayColor)
  • Color click writes only to the selected target
  • "Bez barvy" clears only the selected target
  • Three fields are independent

Drag-and-drop

Half marks are tied to the day, not the shift. When a user drags a shift cell:

  • Only v (and color of the shift) moves to the destination
  • dayColor / nightColor stay on both source and destination days

Compare / diff view

Differences in dayColor / nightColor count as cell changes — render the same orange "modified" border as for value changes.

Filters

  • "Color only" filter (rainbow dot) — also hides cells whose only content is dayColor / nightColor (no v)
  • Hidden value filter (e.g. hide "A") — hides the cell entirely including marks (marks are auxiliary)

Scope

Half-mark editing is available on:

  • ✅ Person cells (Pohotovost TKB / Pohotovost IT)
  • ✅ Info rows (TKB / SAZLT / Metro / D8)
  • ❌ PMS columns (month-end summary, doesn't make sense)

Read-only

Existing isReadOnly guard handles viewer mode automatically. Viewers see marks but cannot edit.

Out of scope (phase 1)

  • Excel export/import — original template has no clean representation; round-trip would lose marks. Documented as a known limitation; revisit if users request it.
  • PDF export — will render half marks using same rules (no extra work expected).

Files to change

  1. web/src/types.ts — extend CellValue
  2. web/src/useScheduleState.ts — add setCellHalfColor(personId, dayIdx, target, color) reducer + undo support
  3. web/src/ScheduleTable.tsx — render split halves / corner triangles in PersonRow and renderInfoRowCells
  4. web/src/ContextMenu.tsx — add segmented toggle, route color clicks to selected target
  5. web/src/cellColors.ts — no change

Estimate: ~150 LoC across 4 files plus minimal CSS.