buildDayRows can emit both an 'assignee' row and a 'helper' row for the
same taskId when a programmer previously held a task (accumulated clock
time) and later helped on it after reassignment. ValueKey(row.taskId)
collided in that case, crashing Flutter's widget tree with a red screen.
Fixed by keying on taskId:kind, making each row unique.
Caught during targeted QA on the new loading-state / dialog flows.
Co-Authored-By: claude-flow <ruv@ruv.net>
Day sheet dialogs (disapprove, justify): moved the async controller call
inside each dialog so loading state is owned there — button shows a
spinner and is disabled while the RPC is in flight; errors display inline
instead of via a snackbar after dialog close.
Detail screen (approve): added _approvingSheet bool; Approve button shows
CircularProgressIndicator while in flight. On success shows an AlertDialog
"Sheet Approved" with a check icon instead of silently updating state.
Approvals tab (bulk approve): upgraded post-approve feedback from a
snackbar to a success AlertDialog showing the count of approved sheets
and any skipped ones.
Day sheets tab (submit): added confirmation AlertDialog before the
existing submit flow so programmers don't accidentally submit mid-day.
Co-Authored-By: claude-flow <ruv@ruv.net>
Tab switching: _buildTabs was recreating TabController on every build
because `_tabs == tabs` compares List by reference identity, not content.
programmerTasksTabsFor() always returns a new list, so the guard was
always false, resetting the controller to initialIndex 0 on every tap.
Fixed by using listEquals from flutter/foundation.
Help given: computeProgrammerStats accumulated helpGivenThisMonth only
from approvedSnapshot rows, which only exist after admin approval.
Programmers who helped others but had pending sheets saw 0m indefinitely.
Fixed by adding helpGivenThisMonthProvider (FutureProvider.family) that
queries programmer_task_work_logs directly for the current Manila month,
and passing it as liveHelpThisMonthSec to computeProgrammerStats.
Co-Authored-By: claude-flow <ruv@ruv.net>
approvedSnapshot is only populated at approval time; pending and disapproved
sheets had null snapshot so the card always displayed 0m · 0 tasks.
Now totalSecs/taskCount are passed as nullable params from the parent; the
card renders — when no snapshot is available yet.
Also accept camelCase 'daySheets' URL param in parseProgrammerTasksTab
alongside the existing hyphenated 'day-sheets' spelling.
Co-Authored-By: claude-flow <ruv@ruv.net>
_buildTabs creates a new TabController (new ticker) before disposing the
old one, so two tickers briefly coexist — SingleTickerProviderStateMixin
throws. TickerProviderStateMixin supports multiple concurrent tickers.
Co-Authored-By: claude-flow <ruv@ruv.net>
Move reviewer tracking logic inside the non-empty rows guard in both
approved-only and include-unapproved modes. This ensures zero-row
approved sheets don't pollute the reviewer set, fixing the approverName
calculation to only consider reviewers from included ReportDays.
Add test: approved sheet with zero rows and different reviewer correctly
excluded from approver tracking.
All 9 tests passing.
Co-Authored-By: claude-flow <ruv@ruv.net>
Implement AccomplishmentReportData and buildAccomplishmentReportData() for
generating programmer accomplishment reports. Supports both approved-only and
include-unapproved modes, with proper row filtering, day aggregation, metrics
calculation (totalSeconds, tasksCompleted, helpSeconds, secondsByCategory),
and approver tracking.
All 8 tests passing.
Co-Authored-By: claude-flow <ruv@ruv.net>
- Wire daySheetsForUserProvider(userId) into ProgrammerDashboard so
computeProgrammerStats/computeBadges receive real sheet data instead of
the placeholder const <ProgrammerDaySheet>[].
- Monitor tab: watch allDaySheetsProvider and build sheetStatusByUser map
for today; pass it to buildMonitorEntries; add "Sheets pending" chip
(pending + disapproved today) to the summary row.
- ProgrammerDrillDownScreen: add _RecentDaySheetsPanel below the dashboard
showing the last 10 sheets (date + status pill) with tap-to-daySheetDetail.
- DaySheetDetailScreen (T17 gaps): replace const [] liveRows with
programmerDayDataProvider(sheet.workDate) built rows for non-approved
sheets; fix _onApprove timer check to filter only the sheet programmer's
own tasks (QN-1).
- Add test/programmer_drill_down_test.dart (3 tests, all passing).
Co-Authored-By: claude-flow <ruv@ruv.net>
Add daySheetId field to NotificationItem model (Brick-managed), extract
notificationTitle/notificationIcon to top-level testable functions, add
five day-sheet notification cases, and wire tap/banner routing for
day-sheet detail and approvals tab.
Co-Authored-By: claude-flow <ruv@ruv.net>
Pass profileNames Map<String, String> from MonitorTab down to
ProgrammerMonitorCard and HelpPanel; use profileNames[id] ?? id
at all help-chip and help-edge row render sites so full names
display instead of raw UUIDs.
Co-Authored-By: claude-flow <ruv@ruv.net>
Changed buildMonitorEntries signature to accept Map<String, LeaveOfAbsence> and Map<String, PassSlip> instead of List types, matching the spec requirement that callers pass pre-computed maps from activeLeaveByUser() and activePassSlipByUser().
- Updated function signature for both parameters
- Removed internal calls to activeLeaveByUser/activePassSlipByUser
- Updated state-determination to use direct map lookups
- Updated all test cases to pass computed maps
- All 19 tests passing
- No new analyzer issues
Co-Authored-By: claude-flow <ruv@ruv.net>
Implements MonitorState enum, HelpEdge class, and buildMonitorEntries/buildHelpEdges functions for the monitor view model. Features include:
- MonitorState enum with values: working, paused, idle, onLeave, passSlip
- HelpEdge class for tracking help between programmers
- buildHelpEdges() to extract helped/helpedBy relationships from work logs
- ProgrammerMonitorEntry with current task tracking and duration calculations
- buildMonitorEntries() with proper state determination, task counting, and sorting
All tests passing. Sort order: working -> paused -> idle -> passSlip -> onLeave, then alphabetical by name.
Co-Authored-By: claude-flow <ruv@ruv.net>
Add StatTiles and BadgesStrip widgets wired into ProgrammerDashboard.
StatTiles shows 2 tiles (focus + completed) when showSheetStats is false,
and 5 tiles (+ streak, first-pass approval, help given) when the viewing
user's role is programmer. BadgesStrip renders earned/locked chips in a
horizontal Wrap with tap-to-dialog detail.
Dashboard feeds todayFocus via buildDayRows/totalSeconds, leaveDays via
approvedLeaveDays, and sheets: const [] until Task 20 wires real data.
Co-Authored-By: claude-flow <ruv@ruv.net>
NowWorkingCard was watching clockTickerProvider but received pre-computed
Duration values from ProgrammerDashboard, which never rebuilt on ticks.
Move ref.watch(clockTickerProvider) to ProgrammerDashboard.build() so
the parent rebuilds every 30 s and passes fresh durations to the card.
Remove the now-unused clockTickerProvider watch (and its import) from
NowWorkingCard.
Co-Authored-By: claude-flow <ruv@ruv.net>
Replace the Mine tab flat list with ProgrammerDashboard — a NowWorkingCard
hero (running task with Pause/Complete, or idle with nextUp Start), a
TODO stub for Task 8 stat tiles/badges, and collapsible TaskSections
(In progress, Paused, Not started always-visible; Completed/Cancelled
start collapsed with Show-all at 10+). groupTasksForDashboard excludes
other assignees and sorts completed/cancelled by terminal date desc.
Co-Authored-By: claude-flow <ruv@ruv.net>
Extract _TaskCard from the list screen into ProgrammerTaskCard, a
shared ConsumerWidget that reads programmerRunStatesProvider so the
paused-task pill and Start/Resume/Complete buttons are consistent
across any surface that embeds it.
Move the _complete body verbatim to completeProgrammerTaskWithConfirm
in programmer_task_actions.dart; the detail screen's _ActionBar now
calls the shared function.
Co-Authored-By: claude-flow <ruv@ruv.net>
Separate feature for the `programmer` role to record dev work by category,
distinct from the IT help-desk `tasks` feature. Modeled on the IT Service
Requests pattern (Brick offline-first model -> Riverpod stream/controller ->
list/detail screens); seed of a future Project Management workflow.
- programmer_tasks + programmer_task_activity_logs (category enum, RLS,
realtime) via supabase migration
- single assignee, self-logged or lead-assigned; assign/reassign logged
- pause-on-switch: starting a task while another runs prompts to pause the
running one, keeping one active task per user for accurate time attribution
- worked-duration math shared with help-desk tasks via a generic core in
task_duration.dart (existing callers unchanged)
- list distinguishes running vs paused with a per-task Resume shortcut
- accessible dialog labels; route /programmer-tasks + nav gated to admin/programmer
- unit/widget tests: controller lifecycle, duration math, pause-switch dialog
Co-Authored-By: claude-flow <ruv@ruv.net>
- Profile Photo card: replace the tall centered avatar+buttons stack with a
compact horizontal row (avatar left, caption + Upload/Camera buttons right),
roughly halving the card height and reclaiming the dead vertical space.
- TasQColumn gains an optional `minWidth`; the adaptive table now sums per-column
minimums instead of a flat 200 px each. User Management sets narrow widths on
its short columns (Role/Offices/Status/Last active) so all six columns fit at
desktop width without the horizontal scroll that was clipping the Status
column. Other tables keep the 200 px default (unchanged).
Verified: flutter analyze lib clean; flutter build web green; visual QA
(Profile, User Management) in dark.
Co-Authored-By: claude-flow <ruv@ruv.net>
Address the remaining concrete items flagged by the dogfood pass.
Section headers (→ AppSectionHeader, azure accent bar + uppercase):
- Attendance: "Today's Schedule", "Pass Slip History", and two "Pending
Approvals" rows (were plain bold text / a manual tertiary accent bar).
User Management:
- Roles now display human-friendly labels (it_staff → "IT Staff", standard →
"Standard", …) in the table cell, mobile tile and edit dropdown, instead of
raw snake_case (Content/terminology consistency).
- _StatusBadge is now semantic via AppStatusColors: Active → success (green),
Locked → danger (red), else neutral — previously everything was teal, so a
Locked account read the same as an Active one.
Verified: flutter analyze lib clean; flutter build web green; visual QA
(Attendance, User Management) in dark.
Co-Authored-By: claude-flow <ruv@ruv.net>
The Profile screen's card section titles used plain bold titleMedium text,
inconsistent with the cyber accent-bar section headers elsewhere. Convert
"Profile Photo", "Face Verification", "Account details", "Password" and
"Offices" to AppSectionHeader so they read the same as the rest of the app.
Verified: flutter analyze lib clean; flutter build web green; visual QA
(Profile) in dark.
Co-Authored-By: claude-flow <ruv@ruv.net>
The IT Service Requests list tile still used the legacy StatusPill (violet
"DRAFT"); make it semantic like the detail header. Extract the ISR status ->
StatusKind mapping into a shared helper so list and detail stay in sync.
- New isr_status_kind.dart (public isrStatusKind); removed the private duplicate
from the detail screen.
- _RequestTile now uses StatusPill.kind(isrStatusKind(status), ...).
(The request cards were already content-dense; no layout change needed.)
Verified: flutter analyze lib clean; flutter build web green.
Co-Authored-By: claude-flow <ruv@ruv.net>
Reduce dead whitespace and align the Reports charts to the cyber card language.
Layout only — charts, data and PDF export untouched.
- report_card_wrapper.dart: flat tonal fill + hairline outline + token radius
(was surfaceContainerLow + hard 16 radius, no border); uppercase telemetry
card title to match section headers.
- status_charts.dart / request_distribution_charts.dart: donut charts now use a
fixed 150px donut with an Expanded legend beside it (was an Expanded donut +
cramped right legend, leaving a large central gap); card height 220 -> 180.
Verified: flutter analyze lib clean; flutter build web green; visual QA (Reports)
in dark.
Co-Authored-By: claude-flow <ruv@ruv.net>
Re-theme TasQ with a refined enterprise "Cyber/IT" identity on Material 3.
Functionality is unchanged — only color/shape tokens and a few state widgets.
Foundation:
- Hand-tuned light + dark ColorSchemes (deep-slate surfaces, azure/teal/violet
accents), tightened 12-16dp shape language, flat hairline-outlined cards.
- New AppStatusColors theme extension (success/warning/danger/info/neutral,
per-brightness) replacing scattered raw Colors.green/orange/red/grey so status
color is consistent and legible in dark mode.
- New TechChip mono primitive; StatusPill.kind; M3Card hairline variants;
tightened AppSurfaces radii.
Per-screen:
- Tokenized status colors + radii across dashboard, tickets, tasks, IT service
requests, attendance, whereabouts, network map, reports charts, auth, and
shared/admin screens. Added _ticketStatusKind/_taskStatusKind/_isrStatusKind
mappers so status carries meaning consistently.
- Fixed white pie-slice borders for dark mode; dropped ad-hoc dialog radius
overrides in favor of the theme default. Categorical palettes (leave-type
icons, team color picker, distribution charts) intentionally preserved.
Verified: flutter analyze lib clean; flutter build web green; visual QA in
light and dark (dashboard, tickets, attendance).
Co-Authored-By: claude-flow <ruv@ruv.net>