@open-mercato/core 0.7.1-develop.7178.1.ab93fbaf4e → 0.7.1-develop.7180.1.9717fbbb43
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +2 -2
- package/dist/generated/entities/staff_time_entry/index.js +14 -0
- package/dist/generated/entities/staff_time_entry/index.js.map +2 -2
- package/dist/generated/entities/staff_time_entry_tag/index.js +15 -0
- package/dist/generated/entities/staff_time_entry_tag/index.js.map +7 -0
- package/dist/generated/entities/staff_time_project/index.js +16 -0
- package/dist/generated/entities/staff_time_project/index.js.map +2 -2
- package/dist/generated/entities/staff_time_report/index.js +57 -0
- package/dist/generated/entities/staff_time_report/index.js.map +7 -0
- package/dist/generated/entities/staff_time_report_entry/index.js +27 -0
- package/dist/generated/entities/staff_time_report_entry/index.js.map +7 -0
- package/dist/generated/entities/staff_time_report_event/index.js +21 -0
- package/dist/generated/entities/staff_time_report_event/index.js.map +7 -0
- package/dist/generated/entities/staff_time_report_project/index.js +15 -0
- package/dist/generated/entities/staff_time_report_project/index.js.map +7 -0
- package/dist/generated/entities/staff_time_tag/index.js +21 -0
- package/dist/generated/entities/staff_time_tag/index.js.map +7 -0
- package/dist/generated/entities/staff_time_task/index.js +37 -0
- package/dist/generated/entities/staff_time_task/index.js.map +7 -0
- package/dist/generated/entities/staff_time_task_comment/index.js +21 -0
- package/dist/generated/entities/staff_time_task_comment/index.js.map +7 -0
- package/dist/generated/entities/staff_time_task_status/index.js +29 -0
- package/dist/generated/entities/staff_time_task_status/index.js.map +7 -0
- package/dist/generated/entities/staff_time_task_tag/index.js +15 -0
- package/dist/generated/entities/staff_time_task_tag/index.js.map +7 -0
- package/dist/generated/entities.ids.generated.js +11 -1
- package/dist/generated/entities.ids.generated.js.map +2 -2
- package/dist/generated/entity-fields-registry.js +149 -0
- package/dist/generated/entity-fields-registry.js.map +2 -2
- package/dist/helpers/integration/timesheetFixtures.js +7 -0
- package/dist/helpers/integration/timesheetFixtures.js.map +2 -2
- package/dist/modules/auth/cli.js +16 -0
- package/dist/modules/auth/cli.js.map +2 -2
- package/dist/modules/auth/lib/backendChrome.js +1 -0
- package/dist/modules/auth/lib/backendChrome.js.map +2 -2
- package/dist/modules/customer_accounts/lib/customerRoleAcls.js +44 -0
- package/dist/modules/customer_accounts/lib/customerRoleAcls.js.map +7 -0
- package/dist/modules/customer_accounts/setup.js +1 -28
- package/dist/modules/customer_accounts/setup.js.map +2 -2
- package/dist/modules/data_sync/api/options.js +2 -0
- package/dist/modules/data_sync/api/options.js.map +2 -2
- package/dist/modules/data_sync/backend/data-sync/page.js +39 -17
- package/dist/modules/data_sync/backend/data-sync/page.js.map +2 -2
- package/dist/modules/data_sync/lib/start-controls.js +42 -0
- package/dist/modules/data_sync/lib/start-controls.js.map +7 -0
- package/dist/modules/staff/acl.js +9 -1
- package/dist/modules/staff/acl.js.map +2 -2
- package/dist/modules/staff/ai-agents.js +142 -0
- package/dist/modules/staff/ai-agents.js.map +7 -0
- package/dist/modules/staff/ai-tools/time-tracking-pack.js +348 -0
- package/dist/modules/staff/ai-tools/time-tracking-pack.js.map +7 -0
- package/dist/modules/staff/ai-tools/types.js +54 -0
- package/dist/modules/staff/ai-tools/types.js.map +7 -0
- package/dist/modules/staff/ai-tools.js +8 -0
- package/dist/modules/staff/ai-tools.js.map +7 -0
- package/dist/modules/staff/analytics.js +84 -1
- package/dist/modules/staff/analytics.js.map +2 -2
- package/dist/modules/staff/api/guards.js +37 -3
- package/dist/modules/staff/api/guards.js.map +2 -2
- package/dist/modules/staff/api/leave-requests/accept/route.js +1 -3
- package/dist/modules/staff/api/leave-requests/accept/route.js.map +2 -2
- package/dist/modules/staff/api/leave-requests/reject/route.js +1 -3
- package/dist/modules/staff/api/leave-requests/reject/route.js.map +2 -2
- package/dist/modules/staff/api/portal/time-reports/[id]/route.js +131 -0
- package/dist/modules/staff/api/portal/time-reports/[id]/route.js.map +7 -0
- package/dist/modules/staff/api/portal/time-reports/route.js +179 -0
- package/dist/modules/staff/api/portal/time-reports/route.js.map +7 -0
- package/dist/modules/staff/api/team-members/self/route.js +1 -3
- package/dist/modules/staff/api/team-members/self/route.js.map +2 -2
- package/dist/modules/staff/api/team-members/tags/assign/route.js +1 -3
- package/dist/modules/staff/api/team-members/tags/assign/route.js.map +2 -2
- package/dist/modules/staff/api/team-members/tags/unassign/route.js +1 -3
- package/dist/modules/staff/api/team-members/tags/unassign/route.js.map +2 -2
- package/dist/modules/staff/api/timesheets/_shared/withTimesheetInterceptors.js +174 -0
- package/dist/modules/staff/api/timesheets/_shared/withTimesheetInterceptors.js.map +7 -0
- package/dist/modules/staff/api/timesheets/access-requests/route.js +226 -0
- package/dist/modules/staff/api/timesheets/access-requests/route.js.map +7 -0
- package/dist/modules/staff/api/timesheets/my-projects/[projectId]/route.js +15 -8
- package/dist/modules/staff/api/timesheets/my-projects/[projectId]/route.js.map +2 -2
- package/dist/modules/staff/api/timesheets/my-projects/route.js +13 -1
- package/dist/modules/staff/api/timesheets/my-projects/route.js.map +2 -2
- package/dist/modules/staff/api/timesheets/my-work/myWorkAggregate.js +42 -0
- package/dist/modules/staff/api/timesheets/my-work/myWorkAggregate.js.map +7 -0
- package/dist/modules/staff/api/timesheets/my-work/route.js +383 -0
- package/dist/modules/staff/api/timesheets/my-work/route.js.map +7 -0
- package/dist/modules/staff/api/timesheets/projects/kpis/route.js +14 -2
- package/dist/modules/staff/api/timesheets/projects/kpis/route.js.map +2 -2
- package/dist/modules/staff/api/timesheets/reports/[id]/close/route.js +168 -0
- package/dist/modules/staff/api/timesheets/reports/[id]/close/route.js.map +7 -0
- package/dist/modules/staff/api/timesheets/reports/[id]/export/route.js +246 -0
- package/dist/modules/staff/api/timesheets/reports/[id]/export/route.js.map +7 -0
- package/dist/modules/staff/api/timesheets/reports/[id]/sheet/route.js +183 -0
- package/dist/modules/staff/api/timesheets/reports/[id]/sheet/route.js.map +7 -0
- package/dist/modules/staff/api/timesheets/reports/[id]/unlock/route.js +164 -0
- package/dist/modules/staff/api/timesheets/reports/[id]/unlock/route.js.map +7 -0
- package/dist/modules/staff/api/timesheets/reports/preview/route.js +360 -0
- package/dist/modules/staff/api/timesheets/reports/preview/route.js.map +7 -0
- package/dist/modules/staff/api/timesheets/reports/route.js +316 -0
- package/dist/modules/staff/api/timesheets/reports/route.js.map +7 -0
- package/dist/modules/staff/api/timesheets/reports/shared.js +63 -0
- package/dist/modules/staff/api/timesheets/reports/shared.js.map +7 -0
- package/dist/modules/staff/api/timesheets/settings/reapply-rounding/route.js +164 -0
- package/dist/modules/staff/api/timesheets/settings/reapply-rounding/route.js.map +7 -0
- package/dist/modules/staff/api/timesheets/settings/rounding-impact/route.js +168 -0
- package/dist/modules/staff/api/timesheets/settings/rounding-impact/route.js.map +7 -0
- package/dist/modules/staff/api/timesheets/settings/route.js +199 -0
- package/dist/modules/staff/api/timesheets/settings/route.js.map +7 -0
- package/dist/modules/staff/api/timesheets/tags/access.js +76 -0
- package/dist/modules/staff/api/timesheets/tags/access.js.map +7 -0
- package/dist/modules/staff/api/timesheets/tags/entry-assignments/route.js +235 -0
- package/dist/modules/staff/api/timesheets/tags/entry-assignments/route.js.map +7 -0
- package/dist/modules/staff/api/timesheets/tags/route.js +160 -0
- package/dist/modules/staff/api/timesheets/tags/route.js.map +7 -0
- package/dist/modules/staff/api/timesheets/tags/task-assignments/route.js +233 -0
- package/dist/modules/staff/api/timesheets/tags/task-assignments/route.js.map +7 -0
- package/dist/modules/staff/api/timesheets/task-statuses/route.js +188 -0
- package/dist/modules/staff/api/timesheets/task-statuses/route.js.map +7 -0
- package/dist/modules/staff/api/timesheets/tasks/[id]/comments/route.js +399 -0
- package/dist/modules/staff/api/timesheets/tasks/[id]/comments/route.js.map +7 -0
- package/dist/modules/staff/api/timesheets/tasks/[id]/status/route.js +210 -0
- package/dist/modules/staff/api/timesheets/tasks/[id]/status/route.js.map +7 -0
- package/dist/modules/staff/api/timesheets/tasks/route.js +333 -0
- package/dist/modules/staff/api/timesheets/tasks/route.js.map +7 -0
- package/dist/modules/staff/api/timesheets/time-entries/[id]/duplicate/route.js +228 -0
- package/dist/modules/staff/api/timesheets/time-entries/[id]/duplicate/route.js.map +7 -0
- package/dist/modules/staff/api/timesheets/time-entries/[id]/segments/[segmentId]/route.js +29 -10
- package/dist/modules/staff/api/timesheets/time-entries/[id]/segments/[segmentId]/route.js.map +2 -2
- package/dist/modules/staff/api/timesheets/time-entries/[id]/segments/route.js +31 -18
- package/dist/modules/staff/api/timesheets/time-entries/[id]/segments/route.js.map +2 -2
- package/dist/modules/staff/api/timesheets/time-entries/[id]/timer-start/route.js +21 -7
- package/dist/modules/staff/api/timesheets/time-entries/[id]/timer-start/route.js.map +2 -2
- package/dist/modules/staff/api/timesheets/time-entries/[id]/timer-stop/route.js +27 -7
- package/dist/modules/staff/api/timesheets/time-entries/[id]/timer-stop/route.js.map +2 -2
- package/dist/modules/staff/api/timesheets/time-entries/bulk/route.js +215 -32
- package/dist/modules/staff/api/timesheets/time-entries/bulk/route.js.map +2 -2
- package/dist/modules/staff/api/timesheets/time-entries/copy-day/route.js +378 -0
- package/dist/modules/staff/api/timesheets/time-entries/copy-day/route.js.map +7 -0
- package/dist/modules/staff/api/timesheets/time-entries/overlaps/route.js +340 -0
- package/dist/modules/staff/api/timesheets/time-entries/overlaps/route.js.map +7 -0
- package/dist/modules/staff/api/timesheets/time-entries/route.js +238 -26
- package/dist/modules/staff/api/timesheets/time-entries/route.js.map +2 -2
- package/dist/modules/staff/api/timesheets/time-entries/start-timer/route.js +23 -8
- package/dist/modules/staff/api/timesheets/time-entries/start-timer/route.js.map +2 -2
- package/dist/modules/staff/api/timesheets/time-projects/[id]/change-currency/route.js +209 -0
- package/dist/modules/staff/api/timesheets/time-projects/[id]/change-currency/route.js.map +7 -0
- package/dist/modules/staff/api/timesheets/time-projects/[id]/employees/route.js +59 -2
- package/dist/modules/staff/api/timesheets/time-projects/[id]/employees/route.js.map +2 -2
- package/dist/modules/staff/api/timesheets/time-projects/route.js +264 -22
- package/dist/modules/staff/api/timesheets/time-projects/route.js.map +2 -2
- package/dist/modules/staff/backend/staff/time-tracking/board/page.js +110 -0
- package/dist/modules/staff/backend/staff/time-tracking/board/page.js.map +7 -0
- package/dist/modules/staff/backend/staff/time-tracking/board/page.meta.js +18 -0
- package/dist/modules/staff/backend/staff/time-tracking/board/page.meta.js.map +7 -0
- package/dist/modules/staff/backend/staff/time-tracking/entries/page.js +981 -0
- package/dist/modules/staff/backend/staff/time-tracking/entries/page.js.map +7 -0
- package/dist/modules/staff/backend/staff/time-tracking/entries/page.meta.js +18 -0
- package/dist/modules/staff/backend/staff/time-tracking/entries/page.meta.js.map +7 -0
- package/dist/modules/staff/backend/staff/time-tracking/page.js +583 -0
- package/dist/modules/staff/backend/staff/time-tracking/page.js.map +7 -0
- package/dist/modules/staff/backend/staff/time-tracking/page.meta.js +15 -0
- package/dist/modules/staff/backend/staff/time-tracking/page.meta.js.map +7 -0
- package/dist/modules/staff/backend/staff/time-tracking/projects/[id]/board/page.js +65 -0
- package/dist/modules/staff/backend/staff/time-tracking/projects/[id]/board/page.js.map +7 -0
- package/dist/modules/staff/backend/staff/time-tracking/projects/[id]/board/page.meta.js +16 -0
- package/dist/modules/staff/backend/staff/time-tracking/projects/[id]/board/page.meta.js.map +7 -0
- package/dist/modules/staff/backend/staff/time-tracking/projects/[id]/edit/page.js +229 -0
- package/dist/modules/staff/backend/staff/time-tracking/projects/[id]/edit/page.js.map +7 -0
- package/dist/modules/staff/backend/staff/time-tracking/projects/[id]/edit/page.meta.js +16 -0
- package/dist/modules/staff/backend/staff/time-tracking/projects/[id]/edit/page.meta.js.map +7 -0
- package/dist/modules/staff/backend/staff/time-tracking/projects/[id]/page.js +1014 -0
- package/dist/modules/staff/backend/staff/time-tracking/projects/[id]/page.js.map +7 -0
- package/dist/modules/staff/backend/staff/time-tracking/projects/[id]/page.meta.js +16 -0
- package/dist/modules/staff/backend/staff/time-tracking/projects/[id]/page.meta.js.map +7 -0
- package/dist/modules/staff/backend/staff/time-tracking/projects/create/page.js +97 -0
- package/dist/modules/staff/backend/staff/time-tracking/projects/create/page.js.map +7 -0
- package/dist/modules/staff/backend/staff/time-tracking/projects/create/page.meta.js +16 -0
- package/dist/modules/staff/backend/staff/time-tracking/projects/create/page.meta.js.map +7 -0
- package/dist/modules/staff/backend/staff/time-tracking/projects/page.js +1040 -0
- package/dist/modules/staff/backend/staff/time-tracking/projects/page.js.map +7 -0
- package/dist/modules/staff/backend/staff/time-tracking/projects/page.meta.js +19 -0
- package/dist/modules/staff/backend/staff/time-tracking/projects/page.meta.js.map +7 -0
- package/dist/modules/staff/backend/staff/time-tracking/projects/projectFormConfig.js +353 -0
- package/dist/modules/staff/backend/staff/time-tracking/projects/projectFormConfig.js.map +7 -0
- package/dist/modules/staff/backend/staff/time-tracking/reports/[id]/page.js +457 -0
- package/dist/modules/staff/backend/staff/time-tracking/reports/[id]/page.js.map +7 -0
- package/dist/modules/staff/backend/staff/time-tracking/reports/[id]/page.meta.js +16 -0
- package/dist/modules/staff/backend/staff/time-tracking/reports/[id]/page.meta.js.map +7 -0
- package/dist/modules/staff/backend/staff/time-tracking/reports/create/page.js +697 -0
- package/dist/modules/staff/backend/staff/time-tracking/reports/create/page.js.map +7 -0
- package/dist/modules/staff/backend/staff/time-tracking/reports/create/page.meta.js +16 -0
- package/dist/modules/staff/backend/staff/time-tracking/reports/create/page.meta.js.map +7 -0
- package/dist/modules/staff/backend/staff/time-tracking/reports/page.js +174 -0
- package/dist/modules/staff/backend/staff/time-tracking/reports/page.js.map +7 -0
- package/dist/modules/staff/backend/staff/time-tracking/reports/page.meta.js +18 -0
- package/dist/modules/staff/backend/staff/time-tracking/reports/page.meta.js.map +7 -0
- package/dist/modules/staff/backend/staff/time-tracking/settings/page.js +546 -0
- package/dist/modules/staff/backend/staff/time-tracking/settings/page.js.map +7 -0
- package/dist/modules/staff/backend/staff/time-tracking/settings/page.meta.js +18 -0
- package/dist/modules/staff/backend/staff/time-tracking/settings/page.meta.js.map +7 -0
- package/dist/modules/staff/backend/staff/time-tracking/timesheet/GridView.js +710 -0
- package/dist/modules/staff/backend/staff/time-tracking/timesheet/GridView.js.map +7 -0
- package/dist/modules/staff/backend/staff/time-tracking/timesheet/page.js +646 -0
- package/dist/modules/staff/backend/staff/time-tracking/timesheet/page.js.map +7 -0
- package/dist/modules/staff/backend/staff/time-tracking/timesheet/page.meta.js +18 -0
- package/dist/modules/staff/backend/staff/time-tracking/timesheet/page.meta.js.map +7 -0
- package/dist/modules/staff/backend/staff/timesheets/page.js +4 -793
- package/dist/modules/staff/backend/staff/timesheets/page.js.map +2 -2
- package/dist/modules/staff/backend/staff/timesheets/page.meta.js +2 -7
- package/dist/modules/staff/backend/staff/timesheets/page.meta.js.map +2 -2
- package/dist/modules/staff/backend/staff/timesheets/projects/[id]/edit/page.js +5 -136
- package/dist/modules/staff/backend/staff/timesheets/projects/[id]/edit/page.js.map +2 -2
- package/dist/modules/staff/backend/staff/timesheets/projects/[id]/edit/page.meta.js +1 -7
- package/dist/modules/staff/backend/staff/timesheets/projects/[id]/edit/page.meta.js.map +2 -2
- package/dist/modules/staff/backend/staff/timesheets/projects/[id]/page.js +5 -445
- package/dist/modules/staff/backend/staff/timesheets/projects/[id]/page.js.map +3 -3
- package/dist/modules/staff/backend/staff/timesheets/projects/[id]/page.meta.js +1 -7
- package/dist/modules/staff/backend/staff/timesheets/projects/[id]/page.meta.js.map +2 -2
- package/dist/modules/staff/backend/staff/timesheets/projects/create/page.js +4 -76
- package/dist/modules/staff/backend/staff/timesheets/projects/create/page.js.map +2 -2
- package/dist/modules/staff/backend/staff/timesheets/projects/create/page.meta.js +1 -7
- package/dist/modules/staff/backend/staff/timesheets/projects/create/page.meta.js.map +2 -2
- package/dist/modules/staff/backend/staff/timesheets/projects/page.js +4 -613
- package/dist/modules/staff/backend/staff/timesheets/projects/page.js.map +2 -2
- package/dist/modules/staff/backend/staff/timesheets/projects/page.meta.js +2 -17
- package/dist/modules/staff/backend/staff/timesheets/projects/page.meta.js.map +2 -2
- package/dist/modules/staff/ce.js +40 -0
- package/dist/modules/staff/ce.js.map +2 -2
- package/dist/modules/staff/cli.js +166 -1
- package/dist/modules/staff/cli.js.map +2 -2
- package/dist/modules/staff/commands/index.js +5 -0
- package/dist/modules/staff/commands/index.js.map +2 -2
- package/dist/modules/staff/commands/timesheets-entries.js +569 -21
- package/dist/modules/staff/commands/timesheets-entries.js.map +3 -3
- package/dist/modules/staff/commands/timesheets-projects.js +450 -7
- package/dist/modules/staff/commands/timesheets-projects.js.map +2 -2
- package/dist/modules/staff/commands/timesheets-reports.js +1036 -0
- package/dist/modules/staff/commands/timesheets-reports.js.map +7 -0
- package/dist/modules/staff/commands/timesheets-tags.js +1015 -0
- package/dist/modules/staff/commands/timesheets-tags.js.map +7 -0
- package/dist/modules/staff/commands/timesheets-task-comments.js +438 -0
- package/dist/modules/staff/commands/timesheets-task-comments.js.map +7 -0
- package/dist/modules/staff/commands/timesheets-task-statuses.js +723 -0
- package/dist/modules/staff/commands/timesheets-task-statuses.js.map +7 -0
- package/dist/modules/staff/commands/timesheets-tasks.js +834 -0
- package/dist/modules/staff/commands/timesheets-tasks.js.map +7 -0
- package/dist/modules/staff/data/enrichers.js +426 -12
- package/dist/modules/staff/data/enrichers.js.map +2 -2
- package/dist/modules/staff/data/entities.js +552 -3
- package/dist/modules/staff/data/entities.js.map +2 -2
- package/dist/modules/staff/data/extensions.js +41 -0
- package/dist/modules/staff/data/extensions.js.map +7 -0
- package/dist/modules/staff/data/validators.js +254 -9
- package/dist/modules/staff/data/validators.js.map +2 -2
- package/dist/modules/staff/di.js +42 -1
- package/dist/modules/staff/di.js.map +2 -2
- package/dist/modules/staff/events.js +84 -6
- package/dist/modules/staff/events.js.map +2 -2
- package/dist/modules/staff/events.payloads.js +158 -0
- package/dist/modules/staff/events.payloads.js.map +7 -0
- package/dist/modules/staff/extension-points.js +261 -0
- package/dist/modules/staff/extension-points.js.map +7 -0
- package/dist/modules/staff/frontend/[orgSlug]/portal/time-reports/[id]/page.js +138 -0
- package/dist/modules/staff/frontend/[orgSlug]/portal/time-reports/[id]/page.js.map +7 -0
- package/dist/modules/staff/frontend/[orgSlug]/portal/time-reports/[id]/page.meta.js +12 -0
- package/dist/modules/staff/frontend/[orgSlug]/portal/time-reports/[id]/page.meta.js.map +7 -0
- package/dist/modules/staff/frontend/[orgSlug]/portal/time-reports/page.js +133 -0
- package/dist/modules/staff/frontend/[orgSlug]/portal/time-reports/page.js.map +7 -0
- package/dist/modules/staff/frontend/[orgSlug]/portal/time-reports/page.meta.js +19 -0
- package/dist/modules/staff/frontend/[orgSlug]/portal/time-reports/page.meta.js.map +7 -0
- package/dist/modules/staff/lib/crud.js +11 -1
- package/dist/modules/staff/lib/crud.js.map +2 -2
- package/dist/modules/staff/lib/time-tracking/access.js +92 -0
- package/dist/modules/staff/lib/time-tracking/access.js.map +7 -0
- package/dist/modules/staff/lib/time-tracking/billability.js +39 -0
- package/dist/modules/staff/lib/time-tracking/billability.js.map +7 -0
- package/dist/modules/staff/lib/time-tracking/capacity.js +68 -0
- package/dist/modules/staff/lib/time-tracking/capacity.js.map +7 -0
- package/dist/modules/staff/lib/time-tracking/componentContracts.js +15 -0
- package/dist/modules/staff/lib/time-tracking/componentContracts.js.map +7 -0
- package/dist/modules/staff/lib/time-tracking/cost.js +82 -0
- package/dist/modules/staff/lib/time-tracking/cost.js.map +7 -0
- package/dist/modules/staff/lib/time-tracking/duration.js +55 -0
- package/dist/modules/staff/lib/time-tracking/duration.js.map +7 -0
- package/dist/modules/staff/lib/time-tracking/featureAccess.js +41 -0
- package/dist/modules/staff/lib/time-tracking/featureAccess.js.map +7 -0
- package/dist/modules/staff/lib/time-tracking/interval.js +72 -0
- package/dist/modules/staff/lib/time-tracking/interval.js.map +7 -0
- package/dist/modules/staff/lib/time-tracking/migrateProjectCodes.js +88 -0
- package/dist/modules/staff/lib/time-tracking/migrateProjectCodes.js.map +7 -0
- package/dist/modules/staff/lib/time-tracking/moneyVisibility.js +10 -0
- package/dist/modules/staff/lib/time-tracking/moneyVisibility.js.map +7 -0
- package/dist/modules/staff/lib/time-tracking/overlap.js +87 -0
- package/dist/modules/staff/lib/time-tracking/overlap.js.map +7 -0
- package/dist/modules/staff/lib/time-tracking/portalRecipients.js +27 -0
- package/dist/modules/staff/lib/time-tracking/portalRecipients.js.map +7 -0
- package/dist/modules/staff/lib/time-tracking/portalReports.js +16 -0
- package/dist/modules/staff/lib/time-tracking/portalReports.js.map +7 -0
- package/dist/modules/staff/lib/time-tracking/projectCode.js +135 -0
- package/dist/modules/staff/lib/time-tracking/projectCode.js.map +7 -0
- package/dist/modules/staff/lib/time-tracking/reapplyRounding.js +187 -0
- package/dist/modules/staff/lib/time-tracking/reapplyRounding.js.map +7 -0
- package/dist/modules/staff/lib/time-tracking/recalculationRunner.js +80 -0
- package/dist/modules/staff/lib/time-tracking/recalculationRunner.js.map +7 -0
- package/dist/modules/staff/lib/time-tracking/recalculations.js +56 -0
- package/dist/modules/staff/lib/time-tracking/recalculations.js.map +7 -0
- package/dist/modules/staff/lib/time-tracking/registries/invoke.js +63 -0
- package/dist/modules/staff/lib/time-tracking/registries/invoke.js.map +7 -0
- package/dist/modules/staff/lib/time-tracking/registries/registry.js +62 -0
- package/dist/modules/staff/lib/time-tracking/registries/registry.js.map +7 -0
- package/dist/modules/staff/lib/time-tracking/registries/scope.js +21 -0
- package/dist/modules/staff/lib/time-tracking/registries/scope.js.map +7 -0
- package/dist/modules/staff/lib/time-tracking/rollup.js +34 -0
- package/dist/modules/staff/lib/time-tracking/rollup.js.map +7 -0
- package/dist/modules/staff/lib/time-tracking/rounding.js +66 -0
- package/dist/modules/staff/lib/time-tracking/rounding.js.map +7 -0
- package/dist/modules/staff/lib/time-tracking/roundingImpact.js +39 -0
- package/dist/modules/staff/lib/time-tracking/roundingImpact.js.map +7 -0
- package/dist/modules/staff/lib/time-tracking/settingKeys.js +214 -0
- package/dist/modules/staff/lib/time-tracking/settingKeys.js.map +7 -0
- package/dist/modules/staff/lib/time-tracking/settings.js +87 -0
- package/dist/modules/staff/lib/time-tracking/settings.js.map +7 -0
- package/dist/modules/staff/lib/time-tracking/sqlInClause.js +9 -0
- package/dist/modules/staff/lib/time-tracking/sqlInClause.js.map +7 -0
- package/dist/modules/staff/lib/time-tracking/timeEntrySources.js +48 -0
- package/dist/modules/staff/lib/time-tracking/timeEntrySources.js.map +7 -0
- package/dist/modules/staff/lib/time-tracking-ui/BoardFilterChips.js +283 -0
- package/dist/modules/staff/lib/time-tracking-ui/BoardFilterChips.js.map +7 -0
- package/dist/modules/staff/lib/time-tracking-ui/CustomerPicker.js +324 -0
- package/dist/modules/staff/lib/time-tracking-ui/CustomerPicker.js.map +7 -0
- package/dist/modules/staff/lib/time-tracking-ui/DurationInput.js +121 -0
- package/dist/modules/staff/lib/time-tracking-ui/DurationInput.js.map +7 -0
- package/dist/modules/staff/lib/time-tracking-ui/EntryDetailsFields.js +188 -0
- package/dist/modules/staff/lib/time-tracking-ui/EntryDetailsFields.js.map +7 -0
- package/dist/modules/staff/lib/time-tracking-ui/EntryFilterBar.js +89 -0
- package/dist/modules/staff/lib/time-tracking-ui/EntryFilterBar.js.map +7 -0
- package/dist/modules/staff/lib/time-tracking-ui/KanbanBoard.js +855 -0
- package/dist/modules/staff/lib/time-tracking-ui/KanbanBoard.js.map +7 -0
- package/dist/modules/staff/lib/time-tracking-ui/KanbanCard.js +360 -0
- package/dist/modules/staff/lib/time-tracking-ui/KanbanCard.js.map +7 -0
- package/dist/modules/staff/lib/time-tracking-ui/KanbanColumn.js +259 -0
- package/dist/modules/staff/lib/time-tracking-ui/KanbanColumn.js.map +7 -0
- package/dist/modules/staff/lib/time-tracking-ui/NewTaskDialog.js +238 -0
- package/dist/modules/staff/lib/time-tracking-ui/NewTaskDialog.js.map +7 -0
- package/dist/modules/staff/lib/time-tracking-ui/NoProjectAccess.js +130 -0
- package/dist/modules/staff/lib/time-tracking-ui/NoProjectAccess.js.map +7 -0
- package/dist/modules/staff/lib/time-tracking-ui/PeriodSelector.js +98 -0
- package/dist/modules/staff/lib/time-tracking-ui/PeriodSelector.js.map +7 -0
- package/dist/modules/staff/lib/time-tracking-ui/PhasePlaceholder.js +27 -0
- package/dist/modules/staff/lib/time-tracking-ui/PhasePlaceholder.js.map +7 -0
- package/dist/modules/staff/lib/time-tracking-ui/ProjectCodeField.js +166 -0
- package/dist/modules/staff/lib/time-tracking-ui/ProjectCodeField.js.map +7 -0
- package/dist/modules/staff/lib/time-tracking-ui/ProjectCurrencyField.js +295 -0
- package/dist/modules/staff/lib/time-tracking-ui/ProjectCurrencyField.js.map +7 -0
- package/dist/modules/staff/lib/time-tracking-ui/ProjectFormSections.js +212 -0
- package/dist/modules/staff/lib/time-tracking-ui/ProjectFormSections.js.map +7 -0
- package/dist/modules/staff/lib/time-tracking-ui/ProjectTeamDrawer.js +729 -0
- package/dist/modules/staff/lib/time-tracking-ui/ProjectTeamDrawer.js.map +7 -0
- package/dist/modules/staff/lib/time-tracking-ui/ReportSheet.js +217 -0
- package/dist/modules/staff/lib/time-tracking-ui/ReportSheet.js.map +7 -0
- package/dist/modules/staff/lib/time-tracking-ui/TagPicker.js +158 -0
- package/dist/modules/staff/lib/time-tracking-ui/TagPicker.js.map +7 -0
- package/dist/modules/staff/lib/time-tracking-ui/TaskBoardScreen.js +224 -0
- package/dist/modules/staff/lib/time-tracking-ui/TaskBoardScreen.js.map +7 -0
- package/dist/modules/staff/lib/time-tracking-ui/TaskCommentThread.js +93 -0
- package/dist/modules/staff/lib/time-tracking-ui/TaskCommentThread.js.map +7 -0
- package/dist/modules/staff/lib/time-tracking-ui/TaskDrawer.js +1196 -0
- package/dist/modules/staff/lib/time-tracking-ui/TaskDrawer.js.map +7 -0
- package/dist/modules/staff/lib/time-tracking-ui/TaskListView.js +176 -0
- package/dist/modules/staff/lib/time-tracking-ui/TaskListView.js.map +7 -0
- package/dist/modules/staff/lib/time-tracking-ui/TaskPicker.js +307 -0
- package/dist/modules/staff/lib/time-tracking-ui/TaskPicker.js.map +7 -0
- package/dist/modules/staff/lib/time-tracking-ui/TaskQuickLog.js +284 -0
- package/dist/modules/staff/lib/time-tracking-ui/TaskQuickLog.js.map +7 -0
- package/dist/modules/staff/lib/time-tracking-ui/TimeEntriesSummaryFooter.js +73 -0
- package/dist/modules/staff/lib/time-tracking-ui/TimeEntriesSummaryFooter.js.map +7 -0
- package/dist/modules/staff/lib/time-tracking-ui/TimeEntryDialog.js +1499 -0
- package/dist/modules/staff/lib/time-tracking-ui/TimeEntryDialog.js.map +7 -0
- package/dist/modules/staff/lib/time-tracking-ui/TimeEntryDurationCell.js +95 -0
- package/dist/modules/staff/lib/time-tracking-ui/TimeEntryDurationCell.js.map +7 -0
- package/dist/modules/staff/lib/time-tracking-ui/TimesheetCalendar.js +188 -0
- package/dist/modules/staff/lib/time-tracking-ui/TimesheetCalendar.js.map +7 -0
- package/dist/modules/staff/lib/time-tracking-ui/TimesheetPeriodFooter.js +61 -0
- package/dist/modules/staff/lib/time-tracking-ui/TimesheetPeriodFooter.js.map +7 -0
- package/dist/modules/staff/lib/time-tracking-ui/TimesheetViewSwitch.js +45 -0
- package/dist/modules/staff/lib/time-tracking-ui/TimesheetViewSwitch.js.map +7 -0
- package/dist/modules/staff/lib/time-tracking-ui/boardDirectory.js +176 -0
- package/dist/modules/staff/lib/time-tracking-ui/boardDirectory.js.map +7 -0
- package/dist/modules/staff/lib/time-tracking-ui/boardFilters.js +82 -0
- package/dist/modules/staff/lib/time-tracking-ui/boardFilters.js.map +7 -0
- package/dist/modules/staff/lib/time-tracking-ui/boardSummary.js +5 -0
- package/dist/modules/staff/lib/time-tracking-ui/boardSummary.js.map +7 -0
- package/dist/modules/staff/lib/time-tracking-ui/kanbanBoardData.js +152 -0
- package/dist/modules/staff/lib/time-tracking-ui/kanbanBoardData.js.map +7 -0
- package/dist/modules/staff/lib/time-tracking-ui/projectTeamAssignment.js +92 -0
- package/dist/modules/staff/lib/time-tracking-ui/projectTeamAssignment.js.map +7 -0
- package/dist/modules/staff/lib/time-tracking-ui/taskDrawerData.js +111 -0
- package/dist/modules/staff/lib/time-tracking-ui/taskDrawerData.js.map +7 -0
- package/dist/modules/staff/lib/time-tracking-ui/timeEntryDialogState.js +243 -0
- package/dist/modules/staff/lib/time-tracking-ui/timeEntryDialogState.js.map +7 -0
- package/dist/modules/staff/lib/time-tracking-ui/timeEntryListData.js +151 -0
- package/dist/modules/staff/lib/time-tracking-ui/timeEntryListData.js.map +7 -0
- package/dist/modules/staff/lib/time-tracking-ui/timeTrackingSettingsForm.js +105 -0
- package/dist/modules/staff/lib/time-tracking-ui/timeTrackingSettingsForm.js.map +7 -0
- package/dist/modules/staff/lib/time-tracking-ui/timesheetData.js +132 -0
- package/dist/modules/staff/lib/time-tracking-ui/timesheetData.js.map +7 -0
- package/dist/modules/staff/lib/time-tracking-ui/timesheetPeriod.js +205 -0
- package/dist/modules/staff/lib/time-tracking-ui/timesheetPeriod.js.map +7 -0
- package/dist/modules/staff/lib/time-tracking-ui/timesheetTargets.js +53 -0
- package/dist/modules/staff/lib/time-tracking-ui/timesheetTargets.js.map +7 -0
- package/dist/modules/staff/lib/time-tracking-ui/useBoardFilters.js +77 -0
- package/dist/modules/staff/lib/time-tracking-ui/useBoardFilters.js.map +7 -0
- package/dist/modules/staff/lib/time-tracking-ui/useTimesheetPreferences.js +151 -0
- package/dist/modules/staff/lib/time-tracking-ui/useTimesheetPreferences.js.map +7 -0
- package/dist/modules/staff/lib/timeTrackingSeeds.js +809 -0
- package/dist/modules/staff/lib/timeTrackingSeeds.js.map +7 -0
- package/dist/modules/staff/lib/timesheets/timeEntryCacheInvalidation.js +2 -3
- package/dist/modules/staff/lib/timesheets/timeEntryCacheInvalidation.js.map +2 -2
- package/dist/modules/staff/lib/timesheets/timeEntryDecoration.js +152 -0
- package/dist/modules/staff/lib/timesheets/timeEntryDecoration.js.map +7 -0
- package/dist/modules/staff/lib/timesheets-projects/budgetBurn.js +36 -0
- package/dist/modules/staff/lib/timesheets-projects/budgetBurn.js.map +7 -0
- package/dist/modules/staff/lib/timesheets-projects/budgetThreshold.js +66 -0
- package/dist/modules/staff/lib/timesheets-projects/budgetThreshold.js.map +7 -0
- package/dist/modules/staff/lib/timesheets-projects/budgetThresholdState.js +78 -0
- package/dist/modules/staff/lib/timesheets-projects/budgetThresholdState.js.map +7 -0
- package/dist/modules/staff/lib/timesheets-projects/computeProjectFinancials.js +81 -0
- package/dist/modules/staff/lib/timesheets-projects/computeProjectFinancials.js.map +7 -0
- package/dist/modules/staff/lib/timesheets-projects/reportSelection.js +44 -0
- package/dist/modules/staff/lib/timesheets-projects/reportSelection.js.map +7 -0
- package/dist/modules/staff/lib/timesheets-projects-ui/AssignMembersDialog.js +169 -0
- package/dist/modules/staff/lib/timesheets-projects-ui/AssignMembersDialog.js.map +7 -0
- package/dist/modules/staff/lib/timesheets-projects-ui/ProjectBudgetCell.js +22 -0
- package/dist/modules/staff/lib/timesheets-projects-ui/ProjectBudgetCell.js.map +7 -0
- package/dist/modules/staff/lib/timesheets-projects-ui/ProjectCard.js +51 -1
- package/dist/modules/staff/lib/timesheets-projects-ui/ProjectCard.js.map +2 -2
- package/dist/modules/staff/lib/timesheets-projects-ui/ProjectsBulkActionsBar.js +70 -0
- package/dist/modules/staff/lib/timesheets-projects-ui/ProjectsBulkActionsBar.js.map +7 -0
- package/dist/modules/staff/lib/timesheets-reports/buildReportSheet.js +63 -0
- package/dist/modules/staff/lib/timesheets-reports/buildReportSheet.js.map +7 -0
- package/dist/modules/staff/lib/timesheets-reports/loadReportData.js +170 -0
- package/dist/modules/staff/lib/timesheets-reports/loadReportData.js.map +7 -0
- package/dist/modules/staff/lib/timesheets-reports/pdf.js +205 -0
- package/dist/modules/staff/lib/timesheets-reports/pdf.js.map +7 -0
- package/dist/modules/staff/lib/timesheets-reports/reportApprovalPolicies.js +68 -0
- package/dist/modules/staff/lib/timesheets-reports/reportApprovalPolicies.js.map +7 -0
- package/dist/modules/staff/lib/timesheets-reports/reportConfigData.js +135 -0
- package/dist/modules/staff/lib/timesheets-reports/reportConfigData.js.map +7 -0
- package/dist/modules/staff/lib/timesheets-reports/reportConfigState.js +48 -0
- package/dist/modules/staff/lib/timesheets-reports/reportConfigState.js.map +7 -0
- package/dist/modules/staff/lib/timesheets-reports/reportExport.js +262 -0
- package/dist/modules/staff/lib/timesheets-reports/reportExport.js.map +7 -0
- package/dist/modules/staff/lib/timesheets-reports/reportExportFormats.js +34 -0
- package/dist/modules/staff/lib/timesheets-reports/reportExportFormats.js.map +7 -0
- package/dist/modules/staff/lib/timesheets-reports/reportGroupings.js +79 -0
- package/dist/modules/staff/lib/timesheets-reports/reportGroupings.js.map +7 -0
- package/dist/modules/staff/lib/timesheets-reports/reportLabels.js +11 -0
- package/dist/modules/staff/lib/timesheets-reports/reportLabels.js.map +7 -0
- package/dist/modules/staff/lib/timesheets-reports/reportReference.js +83 -0
- package/dist/modules/staff/lib/timesheets-reports/reportReference.js.map +7 -0
- package/dist/modules/staff/lib/timesheets-reports/reportRows.js +42 -0
- package/dist/modules/staff/lib/timesheets-reports/reportRows.js.map +7 -0
- package/dist/modules/staff/lib/timesheets-reports/reportSheetData.js +107 -0
- package/dist/modules/staff/lib/timesheets-reports/reportSheetData.js.map +7 -0
- package/dist/modules/staff/lib/timesheets-reports/reportTotals.js +289 -0
- package/dist/modules/staff/lib/timesheets-reports/reportTotals.js.map +7 -0
- package/dist/modules/staff/lib/timesheets-reports/xlsx.js +145 -0
- package/dist/modules/staff/lib/timesheets-reports/xlsx.js.map +7 -0
- package/dist/modules/staff/lib/timesheets-tasks/computeTaskRollups.js +116 -0
- package/dist/modules/staff/lib/timesheets-tasks/computeTaskRollups.js.map +7 -0
- package/dist/modules/staff/lib/timesheets-tasks/defaultStatusTemplate.js +50 -0
- package/dist/modules/staff/lib/timesheets-tasks/defaultStatusTemplate.js.map +7 -0
- package/dist/modules/staff/lib/timesheets-tasks/seedProjectStatuses.js +27 -0
- package/dist/modules/staff/lib/timesheets-tasks/seedProjectStatuses.js.map +7 -0
- package/dist/modules/staff/lib/timesheets-tasks/statusPositions.js +65 -0
- package/dist/modules/staff/lib/timesheets-tasks/statusPositions.js.map +7 -0
- package/dist/modules/staff/lib/timesheets-tasks/statusSlug.js +31 -0
- package/dist/modules/staff/lib/timesheets-tasks/statusSlug.js.map +7 -0
- package/dist/modules/staff/lib/timesheets-tasks/taskHierarchy.js +31 -0
- package/dist/modules/staff/lib/timesheets-tasks/taskHierarchy.js.map +7 -0
- package/dist/modules/staff/lib/timesheets-tasks/taskHoursTotals.js +17 -0
- package/dist/modules/staff/lib/timesheets-tasks/taskHoursTotals.js.map +7 -0
- package/dist/modules/staff/lib/timesheets-tasks/taskReference.js +51 -0
- package/dist/modules/staff/lib/timesheets-tasks/taskReference.js.map +7 -0
- package/dist/modules/staff/lib/timesheets-ui/CreateProjectDialog.js +11 -4
- package/dist/modules/staff/lib/timesheets-ui/CreateProjectDialog.js.map +2 -2
- package/dist/modules/staff/lib/timesheets-ui/ListView.js +369 -111
- package/dist/modules/staff/lib/timesheets-ui/ListView.js.map +2 -2
- package/dist/modules/staff/lib/timesheets-ui/TimerBar.js +47 -2
- package/dist/modules/staff/lib/timesheets-ui/TimerBar.js.map +2 -2
- package/dist/modules/staff/migrations/Migration20260813073131_staff.js +79 -0
- package/dist/modules/staff/migrations/Migration20260813073131_staff.js.map +7 -0
- package/dist/modules/staff/migrations/Migration20260824143357_staff.js +15 -0
- package/dist/modules/staff/migrations/Migration20260824143357_staff.js.map +7 -0
- package/dist/modules/staff/notifications.client.js +16 -0
- package/dist/modules/staff/notifications.client.js.map +7 -0
- package/dist/modules/staff/notifications.handlers.js +80 -0
- package/dist/modules/staff/notifications.handlers.js.map +7 -0
- package/dist/modules/staff/notifications.js +168 -0
- package/dist/modules/staff/notifications.js.map +2 -2
- package/dist/modules/staff/search.js +159 -1
- package/dist/modules/staff/search.js.map +2 -2
- package/dist/modules/staff/setup.js +20 -1
- package/dist/modules/staff/setup.js.map +2 -2
- package/dist/modules/staff/subscribers/time-project-access-requested-notification.js +68 -0
- package/dist/modules/staff/subscribers/time-project-access-requested-notification.js.map +7 -0
- package/dist/modules/staff/subscribers/time-project-budget-threshold-notification.js +149 -0
- package/dist/modules/staff/subscribers/time-project-budget-threshold-notification.js.map +7 -0
- package/dist/modules/staff/subscribers/time-report-approved-notification.js +78 -0
- package/dist/modules/staff/subscribers/time-report-approved-notification.js.map +7 -0
- package/dist/modules/staff/subscribers/time-report-portal-broadcast.js +78 -0
- package/dist/modules/staff/subscribers/time-report-portal-broadcast.js.map +7 -0
- package/dist/modules/staff/translations.js +4 -1
- package/dist/modules/staff/translations.js.map +2 -2
- package/dist/modules/staff/widgets/components.js +7 -0
- package/dist/modules/staff/widgets/components.js.map +7 -0
- package/dist/modules/staff/widgets/injection/timer-sidebar-indicator/widget.js +5 -4
- package/dist/modules/staff/widgets/injection/timer-sidebar-indicator/widget.js.map +2 -2
- package/dist/modules/staff/widgets/notifications/TimeProjectAccessRequestedRenderer.js +135 -0
- package/dist/modules/staff/widgets/notifications/TimeProjectAccessRequestedRenderer.js.map +7 -0
- package/dist/modules/staff/widgets/notifications/index.js +5 -0
- package/dist/modules/staff/widgets/notifications/index.js.map +7 -0
- package/dist/modules/staff/workers/timesheets-reapply-rounding.js +43 -0
- package/dist/modules/staff/workers/timesheets-reapply-rounding.js.map +7 -0
- package/generated/entities/staff_time_entry/index.ts +7 -0
- package/generated/entities/staff_time_entry_tag/index.ts +6 -0
- package/generated/entities/staff_time_project/index.ts +8 -0
- package/generated/entities/staff_time_report/index.ts +27 -0
- package/generated/entities/staff_time_report_entry/index.ts +12 -0
- package/generated/entities/staff_time_report_event/index.ts +9 -0
- package/generated/entities/staff_time_report_project/index.ts +6 -0
- package/generated/entities/staff_time_tag/index.ts +9 -0
- package/generated/entities/staff_time_task/index.ts +17 -0
- package/generated/entities/staff_time_task_comment/index.ts +9 -0
- package/generated/entities/staff_time_task_status/index.ts +13 -0
- package/generated/entities/staff_time_task_tag/index.ts +6 -0
- package/generated/entities.ids.generated.ts +11 -1
- package/generated/entity-fields-registry.ts +149 -0
- package/package.json +7 -7
- package/src/helpers/integration/timesheetFixtures.ts +31 -1
- package/src/modules/auth/README.md +1 -1
- package/src/modules/auth/cli.ts +35 -1
- package/src/modules/auth/i18n/de.json +7 -0
- package/src/modules/auth/i18n/en.json +7 -0
- package/src/modules/auth/i18n/es.json +7 -0
- package/src/modules/auth/i18n/ko.json +7 -0
- package/src/modules/auth/i18n/pl.json +7 -0
- package/src/modules/auth/lib/backendChrome.tsx +1 -0
- package/src/modules/customer_accounts/lib/customerRoleAcls.ts +79 -0
- package/src/modules/customer_accounts/setup.ts +1 -45
- package/src/modules/data_sync/AGENTS.md +34 -0
- package/src/modules/data_sync/api/options.ts +2 -0
- package/src/modules/data_sync/backend/data-sync/page.tsx +82 -33
- package/src/modules/data_sync/i18n/de.json +1 -0
- package/src/modules/data_sync/i18n/en.json +1 -0
- package/src/modules/data_sync/i18n/es.json +1 -0
- package/src/modules/data_sync/i18n/ko.json +1 -0
- package/src/modules/data_sync/i18n/pl.json +1 -0
- package/src/modules/data_sync/lib/adapter.ts +45 -0
- package/src/modules/data_sync/lib/start-controls.ts +89 -0
- package/src/modules/staff/AGENTS.md +769 -1
- package/src/modules/staff/acl.ts +9 -0
- package/src/modules/staff/ai-agents.ts +189 -0
- package/src/modules/staff/ai-tools/time-tracking-pack.ts +494 -0
- package/src/modules/staff/ai-tools/types.ts +82 -0
- package/src/modules/staff/ai-tools.ts +13 -0
- package/src/modules/staff/analytics.ts +113 -0
- package/src/modules/staff/api/guards.ts +85 -3
- package/src/modules/staff/api/leave-requests/accept/route.ts +0 -2
- package/src/modules/staff/api/leave-requests/reject/route.ts +0 -2
- package/src/modules/staff/api/portal/time-reports/[id]/route.ts +182 -0
- package/src/modules/staff/api/portal/time-reports/route.ts +270 -0
- package/src/modules/staff/api/team-members/self/route.ts +0 -2
- package/src/modules/staff/api/team-members/tags/assign/route.ts +0 -2
- package/src/modules/staff/api/team-members/tags/unassign/route.ts +0 -2
- package/src/modules/staff/api/timesheets/_shared/withTimesheetInterceptors.ts +292 -0
- package/src/modules/staff/api/timesheets/access-requests/route.ts +299 -0
- package/src/modules/staff/api/timesheets/my-projects/[projectId]/route.ts +15 -7
- package/src/modules/staff/api/timesheets/my-projects/route.ts +14 -1
- package/src/modules/staff/api/timesheets/my-work/myWorkAggregate.ts +90 -0
- package/src/modules/staff/api/timesheets/my-work/route.ts +475 -0
- package/src/modules/staff/api/timesheets/projects/kpis/route.ts +15 -2
- package/src/modules/staff/api/timesheets/reports/[id]/close/route.ts +203 -0
- package/src/modules/staff/api/timesheets/reports/[id]/export/route.ts +315 -0
- package/src/modules/staff/api/timesheets/reports/[id]/sheet/route.ts +220 -0
- package/src/modules/staff/api/timesheets/reports/[id]/unlock/route.ts +208 -0
- package/src/modules/staff/api/timesheets/reports/preview/route.ts +449 -0
- package/src/modules/staff/api/timesheets/reports/route.ts +386 -0
- package/src/modules/staff/api/timesheets/reports/shared.ts +121 -0
- package/src/modules/staff/api/timesheets/settings/reapply-rounding/route.ts +205 -0
- package/src/modules/staff/api/timesheets/settings/rounding-impact/route.ts +226 -0
- package/src/modules/staff/api/timesheets/settings/route.ts +242 -0
- package/src/modules/staff/api/timesheets/tags/access.ts +134 -0
- package/src/modules/staff/api/timesheets/tags/entry-assignments/route.ts +290 -0
- package/src/modules/staff/api/timesheets/tags/route.ts +177 -0
- package/src/modules/staff/api/timesheets/tags/task-assignments/route.ts +294 -0
- package/src/modules/staff/api/timesheets/task-statuses/route.ts +232 -0
- package/src/modules/staff/api/timesheets/tasks/[id]/comments/route.ts +532 -0
- package/src/modules/staff/api/timesheets/tasks/[id]/status/route.ts +271 -0
- package/src/modules/staff/api/timesheets/tasks/route.ts +443 -0
- package/src/modules/staff/api/timesheets/time-entries/[id]/duplicate/route.ts +306 -0
- package/src/modules/staff/api/timesheets/time-entries/[id]/segments/[segmentId]/route.ts +32 -10
- package/src/modules/staff/api/timesheets/time-entries/[id]/segments/route.ts +32 -17
- package/src/modules/staff/api/timesheets/time-entries/[id]/timer-start/route.ts +27 -6
- package/src/modules/staff/api/timesheets/time-entries/[id]/timer-stop/route.ts +36 -6
- package/src/modules/staff/api/timesheets/time-entries/bulk/route.ts +331 -34
- package/src/modules/staff/api/timesheets/time-entries/copy-day/route.ts +533 -0
- package/src/modules/staff/api/timesheets/time-entries/overlaps/route.ts +457 -0
- package/src/modules/staff/api/timesheets/time-entries/route.ts +378 -24
- package/src/modules/staff/api/timesheets/time-entries/start-timer/route.ts +31 -9
- package/src/modules/staff/api/timesheets/time-projects/[id]/change-currency/route.ts +246 -0
- package/src/modules/staff/api/timesheets/time-projects/[id]/employees/route.ts +62 -2
- package/src/modules/staff/api/timesheets/time-projects/route.ts +397 -22
- package/src/modules/staff/backend/staff/time-tracking/board/page.meta.ts +14 -0
- package/src/modules/staff/backend/staff/time-tracking/board/page.tsx +151 -0
- package/src/modules/staff/backend/staff/time-tracking/entries/page.meta.ts +14 -0
- package/src/modules/staff/backend/staff/time-tracking/entries/page.tsx +1229 -0
- package/src/modules/staff/backend/staff/time-tracking/page.meta.ts +11 -0
- package/src/modules/staff/backend/staff/time-tracking/page.tsx +823 -0
- package/src/modules/staff/backend/staff/time-tracking/projects/[id]/board/page.meta.ts +12 -0
- package/src/modules/staff/backend/staff/time-tracking/projects/[id]/board/page.tsx +81 -0
- package/src/modules/staff/backend/staff/time-tracking/projects/[id]/edit/page.meta.ts +12 -0
- package/src/modules/staff/backend/staff/time-tracking/projects/[id]/edit/page.tsx +275 -0
- package/src/modules/staff/backend/staff/time-tracking/projects/[id]/page.meta.ts +12 -0
- package/src/modules/staff/backend/staff/time-tracking/projects/[id]/page.tsx +1420 -0
- package/src/modules/staff/backend/staff/time-tracking/projects/create/page.meta.ts +12 -0
- package/src/modules/staff/backend/staff/time-tracking/projects/create/page.tsx +109 -0
- package/src/modules/staff/backend/staff/time-tracking/projects/page.meta.ts +15 -0
- package/src/modules/staff/backend/staff/time-tracking/projects/page.tsx +1254 -0
- package/src/modules/staff/backend/staff/time-tracking/projects/projectFormConfig.ts +466 -0
- package/src/modules/staff/backend/staff/time-tracking/reports/[id]/page.meta.ts +12 -0
- package/src/modules/staff/backend/staff/time-tracking/reports/[id]/page.tsx +632 -0
- package/src/modules/staff/backend/staff/time-tracking/reports/create/page.meta.ts +12 -0
- package/src/modules/staff/backend/staff/time-tracking/reports/create/page.tsx +867 -0
- package/src/modules/staff/backend/staff/time-tracking/reports/page.meta.ts +14 -0
- package/src/modules/staff/backend/staff/time-tracking/reports/page.tsx +246 -0
- package/src/modules/staff/backend/staff/time-tracking/settings/page.meta.ts +14 -0
- package/src/modules/staff/backend/staff/time-tracking/settings/page.tsx +701 -0
- package/src/modules/staff/backend/staff/time-tracking/timesheet/GridView.tsx +953 -0
- package/src/modules/staff/backend/staff/time-tracking/timesheet/page.meta.ts +14 -0
- package/src/modules/staff/backend/staff/time-tracking/timesheet/page.tsx +800 -0
- package/src/modules/staff/backend/staff/timesheets/page.meta.ts +6 -6
- package/src/modules/staff/backend/staff/timesheets/page.tsx +12 -1010
- package/src/modules/staff/backend/staff/timesheets/projects/[id]/edit/page.meta.ts +0 -6
- package/src/modules/staff/backend/staff/timesheets/projects/[id]/edit/page.tsx +4 -158
- package/src/modules/staff/backend/staff/timesheets/projects/[id]/page.meta.ts +0 -6
- package/src/modules/staff/backend/staff/timesheets/projects/[id]/page.tsx +4 -609
- package/src/modules/staff/backend/staff/timesheets/projects/create/page.meta.ts +0 -6
- package/src/modules/staff/backend/staff/timesheets/projects/create/page.tsx +3 -89
- package/src/modules/staff/backend/staff/timesheets/projects/page.meta.ts +2 -19
- package/src/modules/staff/backend/staff/timesheets/projects/page.tsx +3 -778
- package/src/modules/staff/ce.ts +63 -0
- package/src/modules/staff/cli.ts +207 -1
- package/src/modules/staff/commands/index.ts +5 -0
- package/src/modules/staff/commands/timesheets-entries.ts +1006 -28
- package/src/modules/staff/commands/timesheets-projects.ts +593 -7
- package/src/modules/staff/commands/timesheets-reports.ts +1329 -0
- package/src/modules/staff/commands/timesheets-tags.ts +1315 -0
- package/src/modules/staff/commands/timesheets-task-comments.ts +583 -0
- package/src/modules/staff/commands/timesheets-task-statuses.ts +889 -0
- package/src/modules/staff/commands/timesheets-tasks.ts +1121 -0
- package/src/modules/staff/data/enrichers.ts +675 -10
- package/src/modules/staff/data/entities.ts +494 -2
- package/src/modules/staff/data/extensions.ts +68 -0
- package/src/modules/staff/data/validators.ts +348 -3
- package/src/modules/staff/di.ts +96 -0
- package/src/modules/staff/events.payloads.ts +268 -0
- package/src/modules/staff/events.ts +87 -5
- package/src/modules/staff/extension-points.ts +308 -0
- package/src/modules/staff/frontend/[orgSlug]/portal/time-reports/[id]/page.meta.ts +10 -0
- package/src/modules/staff/frontend/[orgSlug]/portal/time-reports/[id]/page.tsx +225 -0
- package/src/modules/staff/frontend/[orgSlug]/portal/time-reports/page.meta.ts +17 -0
- package/src/modules/staff/frontend/[orgSlug]/portal/time-reports/page.tsx +182 -0
- package/src/modules/staff/i18n/de.json +899 -0
- package/src/modules/staff/i18n/en.json +899 -0
- package/src/modules/staff/i18n/es.json +899 -0
- package/src/modules/staff/i18n/ko.json +899 -0
- package/src/modules/staff/i18n/pl.json +899 -0
- package/src/modules/staff/lib/crud.ts +14 -3
- package/src/modules/staff/lib/time-tracking/access.ts +155 -0
- package/src/modules/staff/lib/time-tracking/billability.ts +68 -0
- package/src/modules/staff/lib/time-tracking/capacity.ts +124 -0
- package/src/modules/staff/lib/time-tracking/componentContracts.ts +26 -0
- package/src/modules/staff/lib/time-tracking/cost.ts +144 -0
- package/src/modules/staff/lib/time-tracking/duration.ts +68 -0
- package/src/modules/staff/lib/time-tracking/featureAccess.ts +115 -0
- package/src/modules/staff/lib/time-tracking/interval.ts +90 -0
- package/src/modules/staff/lib/time-tracking/migrateProjectCodes.ts +161 -0
- package/src/modules/staff/lib/time-tracking/moneyVisibility.ts +37 -0
- package/src/modules/staff/lib/time-tracking/overlap.ts +159 -0
- package/src/modules/staff/lib/time-tracking/portalRecipients.ts +76 -0
- package/src/modules/staff/lib/time-tracking/portalReports.ts +31 -0
- package/src/modules/staff/lib/time-tracking/projectCode.ts +221 -0
- package/src/modules/staff/lib/time-tracking/reapplyRounding.ts +313 -0
- package/src/modules/staff/lib/time-tracking/recalculationRunner.ts +118 -0
- package/src/modules/staff/lib/time-tracking/recalculations.ts +135 -0
- package/src/modules/staff/lib/time-tracking/registries/invoke.ts +122 -0
- package/src/modules/staff/lib/time-tracking/registries/registry.ts +124 -0
- package/src/modules/staff/lib/time-tracking/registries/scope.ts +56 -0
- package/src/modules/staff/lib/time-tracking/rollup.ts +59 -0
- package/src/modules/staff/lib/time-tracking/rounding.ts +126 -0
- package/src/modules/staff/lib/time-tracking/roundingImpact.ts +75 -0
- package/src/modules/staff/lib/time-tracking/settingKeys.ts +274 -0
- package/src/modules/staff/lib/time-tracking/settings.ts +168 -0
- package/src/modules/staff/lib/time-tracking/sqlInClause.ts +22 -0
- package/src/modules/staff/lib/time-tracking/timeEntrySources.ts +85 -0
- package/src/modules/staff/lib/time-tracking-ui/BoardFilterChips.tsx +360 -0
- package/src/modules/staff/lib/time-tracking-ui/CustomerPicker.tsx +427 -0
- package/src/modules/staff/lib/time-tracking-ui/DurationInput.tsx +192 -0
- package/src/modules/staff/lib/time-tracking-ui/EntryDetailsFields.tsx +224 -0
- package/src/modules/staff/lib/time-tracking-ui/EntryFilterBar.tsx +144 -0
- package/src/modules/staff/lib/time-tracking-ui/KanbanBoard.tsx +1065 -0
- package/src/modules/staff/lib/time-tracking-ui/KanbanCard.tsx +435 -0
- package/src/modules/staff/lib/time-tracking-ui/KanbanColumn.tsx +316 -0
- package/src/modules/staff/lib/time-tracking-ui/NewTaskDialog.tsx +291 -0
- package/src/modules/staff/lib/time-tracking-ui/NoProjectAccess.tsx +162 -0
- package/src/modules/staff/lib/time-tracking-ui/PeriodSelector.tsx +149 -0
- package/src/modules/staff/lib/time-tracking-ui/PhasePlaceholder.tsx +31 -0
- package/src/modules/staff/lib/time-tracking-ui/ProjectCodeField.tsx +230 -0
- package/src/modules/staff/lib/time-tracking-ui/ProjectCurrencyField.tsx +432 -0
- package/src/modules/staff/lib/time-tracking-ui/ProjectFormSections.tsx +323 -0
- package/src/modules/staff/lib/time-tracking-ui/ProjectTeamDrawer.tsx +930 -0
- package/src/modules/staff/lib/time-tracking-ui/ReportSheet.tsx +357 -0
- package/src/modules/staff/lib/time-tracking-ui/TagPicker.tsx +195 -0
- package/src/modules/staff/lib/time-tracking-ui/TaskBoardScreen.tsx +243 -0
- package/src/modules/staff/lib/time-tracking-ui/TaskCommentThread.tsx +137 -0
- package/src/modules/staff/lib/time-tracking-ui/TaskDrawer.tsx +1405 -0
- package/src/modules/staff/lib/time-tracking-ui/TaskListView.tsx +260 -0
- package/src/modules/staff/lib/time-tracking-ui/TaskPicker.tsx +435 -0
- package/src/modules/staff/lib/time-tracking-ui/TaskQuickLog.tsx +296 -0
- package/src/modules/staff/lib/time-tracking-ui/TimeEntriesSummaryFooter.tsx +97 -0
- package/src/modules/staff/lib/time-tracking-ui/TimeEntryDialog.tsx +1929 -0
- package/src/modules/staff/lib/time-tracking-ui/TimeEntryDurationCell.tsx +126 -0
- package/src/modules/staff/lib/time-tracking-ui/TimesheetCalendar.tsx +265 -0
- package/src/modules/staff/lib/time-tracking-ui/TimesheetPeriodFooter.tsx +78 -0
- package/src/modules/staff/lib/time-tracking-ui/TimesheetViewSwitch.tsx +70 -0
- package/src/modules/staff/lib/time-tracking-ui/boardDirectory.ts +231 -0
- package/src/modules/staff/lib/time-tracking-ui/boardFilters.ts +128 -0
- package/src/modules/staff/lib/time-tracking-ui/boardSummary.ts +20 -0
- package/src/modules/staff/lib/time-tracking-ui/kanbanBoardData.ts +228 -0
- package/src/modules/staff/lib/time-tracking-ui/projectTeamAssignment.ts +143 -0
- package/src/modules/staff/lib/time-tracking-ui/taskDrawerData.ts +194 -0
- package/src/modules/staff/lib/time-tracking-ui/timeEntryDialogState.ts +400 -0
- package/src/modules/staff/lib/time-tracking-ui/timeEntryListData.ts +271 -0
- package/src/modules/staff/lib/time-tracking-ui/timeTrackingSettingsForm.ts +168 -0
- package/src/modules/staff/lib/time-tracking-ui/timesheetData.ts +225 -0
- package/src/modules/staff/lib/time-tracking-ui/timesheetPeriod.ts +278 -0
- package/src/modules/staff/lib/time-tracking-ui/timesheetTargets.ts +93 -0
- package/src/modules/staff/lib/time-tracking-ui/useBoardFilters.ts +107 -0
- package/src/modules/staff/lib/time-tracking-ui/useTimesheetPreferences.ts +245 -0
- package/src/modules/staff/lib/timeTrackingSeeds.ts +1037 -0
- package/src/modules/staff/lib/timesheets/timeEntryCacheInvalidation.ts +11 -10
- package/src/modules/staff/lib/timesheets/timeEntryDecoration.ts +256 -0
- package/src/modules/staff/lib/timesheets-projects/budgetBurn.ts +60 -0
- package/src/modules/staff/lib/timesheets-projects/budgetThreshold.ts +135 -0
- package/src/modules/staff/lib/timesheets-projects/budgetThresholdState.ts +137 -0
- package/src/modules/staff/lib/timesheets-projects/computeProjectFinancials.ts +142 -0
- package/src/modules/staff/lib/timesheets-projects/reportSelection.ts +82 -0
- package/src/modules/staff/lib/timesheets-projects-ui/AssignMembersDialog.tsx +237 -0
- package/src/modules/staff/lib/timesheets-projects-ui/ProjectBudgetCell.tsx +33 -0
- package/src/modules/staff/lib/timesheets-projects-ui/ProjectCard.tsx +56 -1
- package/src/modules/staff/lib/timesheets-projects-ui/ProjectsBulkActionsBar.tsx +90 -0
- package/src/modules/staff/lib/timesheets-reports/buildReportSheet.ts +125 -0
- package/src/modules/staff/lib/timesheets-reports/loadReportData.ts +251 -0
- package/src/modules/staff/lib/timesheets-reports/pdf.ts +263 -0
- package/src/modules/staff/lib/timesheets-reports/reportApprovalPolicies.ts +137 -0
- package/src/modules/staff/lib/timesheets-reports/reportConfigData.ts +247 -0
- package/src/modules/staff/lib/timesheets-reports/reportConfigState.ts +89 -0
- package/src/modules/staff/lib/timesheets-reports/reportExport.ts +373 -0
- package/src/modules/staff/lib/timesheets-reports/reportExportFormats.ts +71 -0
- package/src/modules/staff/lib/timesheets-reports/reportGroupings.ts +153 -0
- package/src/modules/staff/lib/timesheets-reports/reportLabels.ts +23 -0
- package/src/modules/staff/lib/timesheets-reports/reportReference.ts +146 -0
- package/src/modules/staff/lib/timesheets-reports/reportRows.ts +89 -0
- package/src/modules/staff/lib/timesheets-reports/reportSheetData.ts +196 -0
- package/src/modules/staff/lib/timesheets-reports/reportTotals.ts +544 -0
- package/src/modules/staff/lib/timesheets-reports/xlsx.ts +207 -0
- package/src/modules/staff/lib/timesheets-tasks/computeTaskRollups.ts +238 -0
- package/src/modules/staff/lib/timesheets-tasks/defaultStatusTemplate.ts +90 -0
- package/src/modules/staff/lib/timesheets-tasks/seedProjectStatuses.ts +43 -0
- package/src/modules/staff/lib/timesheets-tasks/statusPositions.ts +132 -0
- package/src/modules/staff/lib/timesheets-tasks/statusSlug.ts +43 -0
- package/src/modules/staff/lib/timesheets-tasks/taskHierarchy.ts +99 -0
- package/src/modules/staff/lib/timesheets-tasks/taskHoursTotals.ts +42 -0
- package/src/modules/staff/lib/timesheets-tasks/taskReference.ts +108 -0
- package/src/modules/staff/lib/timesheets-ui/CreateProjectDialog.tsx +18 -4
- package/src/modules/staff/lib/timesheets-ui/ListView.tsx +504 -149
- package/src/modules/staff/lib/timesheets-ui/TimerBar.tsx +50 -2
- package/src/modules/staff/migrations/.snapshot-open-mercato.json +3244 -228
- package/src/modules/staff/migrations/Migration20260813073131_staff.ts +94 -0
- package/src/modules/staff/migrations/Migration20260824143357_staff.ts +17 -0
- package/src/modules/staff/notifications.client.ts +16 -0
- package/src/modules/staff/notifications.handlers.ts +88 -0
- package/src/modules/staff/notifications.ts +163 -0
- package/src/modules/staff/search.ts +191 -1
- package/src/modules/staff/setup.ts +22 -0
- package/src/modules/staff/subscribers/time-project-access-requested-notification.ts +95 -0
- package/src/modules/staff/subscribers/time-project-budget-threshold-notification.ts +226 -0
- package/src/modules/staff/subscribers/time-report-approved-notification.ts +116 -0
- package/src/modules/staff/subscribers/time-report-portal-broadcast.ts +120 -0
- package/src/modules/staff/translations.ts +17 -0
- package/src/modules/staff/widgets/components.ts +34 -0
- package/src/modules/staff/widgets/injection/timer-sidebar-indicator/widget.tsx +6 -5
- package/src/modules/staff/widgets/notifications/TimeProjectAccessRequestedRenderer.tsx +138 -0
- package/src/modules/staff/widgets/notifications/index.ts +1 -0
- package/src/modules/staff/workers/timesheets-reapply-rounding.ts +59 -0
- package/dist/modules/staff/backend/staff/timesheets/projects/projectFormConfig.js +0 -123
- package/dist/modules/staff/backend/staff/timesheets/projects/projectFormConfig.js.map +0 -7
- package/src/modules/staff/backend/staff/timesheets/projects/projectFormConfig.ts +0 -138
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../../src/modules/staff/lib/time-tracking-ui/KanbanBoard.tsx"],
|
|
4
|
+
"sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { useRouter, useSearchParams } from 'next/navigation'\nimport { useQueries, useQuery, useQueryClient } from '@tanstack/react-query'\nimport {\n DndContext,\n DragOverlay,\n MeasuringStrategy,\n PointerSensor,\n pointerWithin,\n useSensor,\n useSensors,\n type Announcements,\n type CollisionDetection,\n type DragEndEvent,\n type DragStartEvent,\n type ScreenReaderInstructions,\n type UniqueIdentifier,\n} from '@dnd-kit/core'\nimport { Plus, RotateCcw } from 'lucide-react'\nimport { Alert, AlertDescription } from '@open-mercato/ui/primitives/alert'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { EmptyState } from '@open-mercato/ui/primitives/empty-state'\nimport { Input } from '@open-mercato/ui/primitives/input'\nimport { ErrorMessage, LoadingMessage } from '@open-mercato/ui/backend/detail'\nimport { apiCall, apiCallOrThrow, withScopedApiRequestHeaders } from '@open-mercato/ui/backend/utils/apiCall'\nimport { buildOptimisticLockHeader } from '@open-mercato/ui/backend/utils/optimisticLock'\nimport { surfaceRecordConflict } from '@open-mercato/ui/backend/conflicts'\nimport { useBackendChrome } from '@open-mercato/ui/backend/BackendChromeProvider'\nimport { useGuardedMutation } from '@open-mercato/ui/backend/injection/useGuardedMutation'\nimport { useAppEvent } from '@open-mercato/ui/backend/injection/useAppEvent'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { hasFeature } from '@open-mercato/shared/security/features'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { useOrganizationScopeVersion } from '@open-mercato/shared/lib/frontend/useOrganizationScope'\nimport { createLogger } from '@open-mercato/shared/lib/logger'\nimport { sumTaskLoggedMinutes } from '../timesheets-tasks/taskHoursTotals'\nimport { KanbanColumn, KANBAN_COLUMN_DROPPABLE_PREFIX } from './KanbanColumn'\nimport { InjectionSpot } from '@open-mercato/ui/backend/injection/InjectionSpot'\nimport { extensionPoints } from '@open-mercato/core/modules/staff/extension-points'\nimport { TaskDrawer } from './TaskDrawer'\nimport type { KanbanMoveTarget, KanbanTagOption } from './KanbanCard'\nimport {\n BOARD_DIRECTORY_PAGE_SIZE,\n BOARD_PAGE_SIZE,\n BOARD_QUERY_ROOT,\n boardColumnQueryKey,\n fetchTaskPages,\n useAssigneeNames,\n useBoardSelf,\n useBoardStatuses,\n useTagLabels,\n} from './boardDirectory'\nimport {\n EMPTY_BOARD_FILTERS,\n boardServerFilterKey,\n boardServerFilterParams,\n visibleBoardStatusIds,\n type BoardFilters,\n} from './boardFilters'\nimport type { BoardSummary } from './boardSummary'\nimport {\n computeSubtaskProgress,\n formatBoardMinutes,\n nextPositionAtColumnTop,\n readItems,\n readString,\n sortByPosition,\n toBoardTask,\n type BoardApiRow,\n type BoardTask,\n} from './kanbanBoardData'\n\nconst logger = createLogger('staff').child({ component: 'KanbanBoard' })\n\nexport { BOARD_PAGE_SIZE, BOARD_DIRECTORY_PAGE_SIZE }\nexport const BOARD_MAX_CHILD_PAGES = 5\nexport const MOVE_MUTATION_CONTEXT_ID = 'staff.time_tracking.board.move'\nexport const CREATE_MUTATION_CONTEXT_ID = 'staff.time_tracking.board.create'\nexport const MANAGE_COLUMNS_FEATURE = 'staff.timesheets.projects.manage'\nexport const MANAGE_TASKS_FEATURE = 'staff.timesheets.tasks.manage'\nexport const TASK_STATUS_CHANGED_EVENT = 'staff.timesheets.time_task.status_changed'\n\n/** Window a locally-originated move stays \"mine\" for, so a lost SSE cannot wedge the filter. */\nconst OWN_MOVE_ECHO_TTL_MS = 15_000\n\ntype ColumnCache = { items: BoardApiRow[]; total: number }\n\ntype PendingMove = {\n taskId: string\n targetStatusId: string\n}\n\nexport type KanbanBoardProps = {\n timeProjectId: string\n /** Used by the drawer's header; the page owns the breadcrumb and the rest of the chrome. */\n projectName?: string | null\n /** Board filters (T3.8). Assignee narrows the request, status picks columns, tag filters rows. */\n filters?: BoardFilters\n /** Reports what is on screen so the page head can describe it without a second fetch. */\n onSummaryChange?: (summary: BoardSummary) => void\n}\n\nfunction statusIdFromColumnKey(key: readonly unknown[]): string | null {\n const part = key.find((entry) => typeof entry === 'string' && entry.startsWith('status:'))\n return typeof part === 'string' ? part.slice('status:'.length) : null\n}\n\n/**\n * `true` when `candidate` names a strictly earlier version than `reference`.\n * Unparseable input answers `false`, so an unexpected format leaves whatever the\n * list handed us in charge rather than pinning the board to a remembered token.\n */\nfunction isOlderVersion(candidate: string, reference: string): boolean {\n const candidateAt = Date.parse(candidate)\n const referenceAt = Date.parse(reference)\n if (!Number.isFinite(candidateAt) || !Number.isFinite(referenceAt)) return false\n return candidateAt < referenceAt\n}\n\n/**\n * The Kanban board of screen 6 (T3.6, US-C1/US-C2).\n *\n * Four things carry the design intent and are worth reading before changing anything:\n *\n * 1. **The move is optimistic and the rollback is exact.** Before the PATCH the board\n * snapshots every column cache; the card is moved between them immediately. On any\n * failure the whole snapshot is written back, which returns the card to the column\n * it came from even when the drag crossed columns whose pages had shifted.\n * 2. **A 409 is not a retryable failure.** The PATCH carries the card's `updatedAt` in\n * the optimistic-lock header, so a 409 means somebody else moved this card while the\n * drag was in flight. `surfaceRecordConflict` raises the shared conflict bar, the\n * board refetches, and no Retry is offered \u2014 retrying would overwrite the other\n * move. Every other failure gets the retry affordance of note 2.\n * 3. **Echoes of your own move are ignored.** `status_changed` is broadcast to every\n * connected board, including the one that caused it. Each locally-issued move\n * registers a `taskId|statusId` key that the event handler consumes instead of\n * refetching, so a colleague's drag moves the card here and yours does not fight the\n * optimistic update that already landed.\n * 4. **The next move's version comes out of the last move's response.** A move bumps\n * the row's `updated_at`, so the version the board is holding for that card is spent\n * the moment the PATCH commits \u2014 and the optimistic write of note 1 carries the\n * pre-move version forward until a refetch replaces it. Reading the version back off\n * the response (as `TaskDrawer` already does) is what lets the same card be moved\n * twice in a row; waiting for the refetch made every second move answer 409 \"changed\n * by someone else\" with nobody else editing.\n */\nexport function KanbanBoard({\n timeProjectId,\n projectName,\n filters = EMPTY_BOARD_FILTERS,\n onSummaryChange,\n}: KanbanBoardProps): React.ReactElement {\n const t = useT()\n const router = useRouter()\n const searchParams = useSearchParams()\n const queryClient = useQueryClient()\n const scopeVersion = useOrganizationScopeVersion()\n const { payload } = useBackendChrome()\n const canManageColumns = hasFeature(payload?.grantedFeatures, MANAGE_COLUMNS_FEATURE)\n const canManageTasks = hasFeature(payload?.grantedFeatures, MANAGE_TASKS_FEATURE)\n const serverFilterKey = boardServerFilterKey(filters)\n const serverFilterParams = boardServerFilterParams(filters)\n\n const [pagesByStatus, setPagesByStatus] = React.useState<Record<string, number>>({})\n const [activeDragTaskId, setActiveDragTaskId] = React.useState<string | null>(null)\n const [pendingTaskIds, setPendingTaskIds] = React.useState<ReadonlySet<string>>(new Set())\n const [failedMove, setFailedMove] = React.useState<PendingMove | null>(null)\n const [quickAddPendingStatusId, setQuickAddPendingStatusId] = React.useState<string | null>(null)\n const [composingStatus, setComposingStatus] = React.useState(false)\n const [statusDraft, setStatusDraft] = React.useState('')\n\n const ownMoveKeysRef = React.useRef(new Map<string, number>())\n\n // The version the server confirmed for a card in its own move response, kept until\n // a fetched row catches up with it (note 4). \"Newest wins\" never suppresses a real\n // conflict: somebody else's move produces a version NEWER than the one confirmed\n // here, and the row that carries it takes over \u2014 this only stops the board from\n // replaying a version its own last move already spent.\n const confirmedVersionsRef = React.useRef(new Map<string, string>())\n\n const resolveTaskVersion = React.useCallback(\n (taskId: string, rowVersion: string | null): string | null => {\n const confirmed = confirmedVersionsRef.current.get(taskId)\n if (!confirmed) return rowVersion\n if (rowVersion && !isOlderVersion(rowVersion, confirmed)) {\n confirmedVersionsRef.current.delete(taskId)\n return rowVersion\n }\n return confirmed\n },\n [],\n )\n\n const { runMutation: runMoveMutation, retryLastMutation: retryMoveMutation } = useGuardedMutation<{\n formId: string\n resourceKind: string\n resourceId: string\n retryLastMutation: () => Promise<boolean>\n }>({\n contextId: MOVE_MUTATION_CONTEXT_ID,\n blockedMessage: t('staff.time_tracking.board.move.error', 'Could not move the task.'),\n })\n\n const { runMutation: runCreateMutation, retryLastMutation: retryCreateMutation } = useGuardedMutation<{\n formId: string\n resourceKind: string\n resourceId: string\n retryLastMutation: () => Promise<boolean>\n }>({\n contextId: CREATE_MUTATION_CONTEXT_ID,\n blockedMessage: t('staff.time_tracking.board.quickAdd.error', 'Could not create the task.'),\n })\n\n const statusesQuery = useBoardStatuses(timeProjectId)\n\n const statuses = React.useMemo(() => statusesQuery.data ?? [], [statusesQuery.data])\n\n // A status filter is not a request parameter here \u2014 it selects which columns exist.\n const visibleStatuses = React.useMemo(\n () => visibleBoardStatusIds(statuses, filters),\n [filters, statuses],\n )\n\n const columnQueries = useQueries({\n queries: visibleStatuses.map((status) => {\n const pages = pagesByStatus[status.id] ?? 1\n return {\n queryKey: boardColumnQueryKey(scopeVersion, timeProjectId, status.id, pages, serverFilterKey),\n staleTime: 15_000,\n queryFn: async (): Promise<ColumnCache> =>\n fetchTaskPages(\n (page) =>\n `timeProjectId=${encodeURIComponent(timeProjectId)}&taskStatusId=${encodeURIComponent(status.id)}&topLevelOnly=true&page=${page}&pageSize=${BOARD_PAGE_SIZE}&sortField=position&sortDir=asc${serverFilterParams}`,\n pages,\n ),\n }\n }),\n })\n\n const tasksByStatusId = React.useMemo(() => {\n const map = new Map<string, { tasks: BoardTask[]; loaded: number; total: number }>()\n visibleStatuses.forEach((status, index) => {\n const data = columnQueries[index]?.data\n const loaded = (data?.items ?? [])\n .map(toBoardTask)\n .filter((task): task is BoardTask => task !== null)\n map.set(status.id, {\n tasks: sortByPosition(loaded),\n loaded: loaded.length,\n total: data?.total ?? loaded.length,\n })\n })\n return map\n }, [columnQueries, visibleStatuses])\n\n const allTasks = React.useMemo(() => {\n const rows: BoardTask[] = []\n for (const entry of tasksByStatusId.values()) rows.push(...entry.tasks)\n return rows\n }, [tasksByStatusId])\n\n const hasChildren = React.useMemo(() => allTasks.some((task) => task.childCount > 0), [allTasks])\n\n const childrenQuery = useQuery<BoardTask[]>({\n queryKey: [...BOARD_QUERY_ROOT, 'children', `scope:${scopeVersion}`, `project:${timeProjectId}`],\n enabled: hasChildren,\n staleTime: 30_000,\n queryFn: async () => {\n // The list route filters children only by a single `parentTaskId`, so a board-wide\n // sweep is the one request that answers \"how many of each card's subtasks are done\"\n // without one call per card. Bounded, because the count is decoration, not data.\n const { items } = await fetchTaskPages(\n (page) =>\n `timeProjectId=${encodeURIComponent(timeProjectId)}&page=${page}&pageSize=${BOARD_PAGE_SIZE}&sortField=position&sortDir=asc`,\n BOARD_MAX_CHILD_PAGES,\n )\n return items\n .map(toBoardTask)\n .filter((task): task is BoardTask => task !== null && !!task.parentTaskId)\n },\n })\n\n const doneStatusIds = React.useMemo(\n () => new Set(statuses.filter((status) => status.isDone).map((status) => status.id)),\n [statuses],\n )\n\n const subtasksByTaskId = React.useMemo(\n () => computeSubtaskProgress(childrenQuery.data ?? [], doneStatusIds),\n [childrenQuery.data, doneStatusIds],\n )\n\n const assigneeIds = React.useMemo(() => {\n const ids = new Set<string>()\n for (const task of allTasks) {\n if (task.assigneeStaffMemberId) ids.add(task.assigneeStaffMemberId)\n }\n return Array.from(ids).sort((a, b) => (a < b ? -1 : a > b ? 1 : 0))\n }, [allTasks])\n\n const assigneeQuery = useAssigneeNames(assigneeIds)\n\n const tagIds = React.useMemo(() => {\n const ids = new Set<string>()\n for (const task of allTasks) {\n for (const id of task.tagIds) ids.add(id)\n }\n return Array.from(ids).sort((a, b) => (a < b ? -1 : a > b ? 1 : 0))\n }, [allTasks])\n\n const tagQuery = useTagLabels(tagIds)\n\n // A chip carries a tag's name or it is not drawn at all. The label lookup is a\n // separate request from the card's own row, so falling back to the id painted a\n // raw uuid on the card for as long as that request was in flight.\n const tagsByTaskId = React.useMemo(() => {\n const labels = tagQuery.data ?? new Map<string, string>()\n const map = new Map<string, KanbanTagOption[]>()\n for (const task of allTasks) {\n if (task.tagIds.length === 0) continue\n const named: KanbanTagOption[] = []\n for (const id of task.tagIds) {\n const label = labels.get(id)\n if (label) named.push({ id, label })\n }\n if (named.length === 0) continue\n map.set(task.id, named)\n }\n return map\n }, [allTasks, tagQuery.data])\n\n const selfQuery = useBoardSelf()\n\n const selfStaffMemberId = selfQuery.data?.id ?? null\n\n const runningTimerQuery = useQuery<{ entryId: string | null; taskId: string | null }>({\n queryKey: [...BOARD_QUERY_ROOT, 'running-timer', `scope:${scopeVersion}`, selfStaffMemberId ?? 'none'],\n enabled: !!selfStaffMemberId,\n staleTime: 15_000,\n refetchInterval: 30_000,\n queryFn: async () => {\n if (!selfStaffMemberId) return { entryId: null, taskId: null }\n const call = await apiCall<Record<string, unknown>>(\n `/api/staff/timesheets/time-entries?staffMemberId=${encodeURIComponent(selfStaffMemberId)}&running=true&pageSize=${BOARD_PAGE_SIZE}`,\n )\n if (!call.ok) return { entryId: null, taskId: null }\n for (const row of readItems(call.result)) {\n const endedAt = readString(row, 'ended_at', 'endedAt')\n const startedAt = readString(row, 'started_at', 'startedAt')\n if (!startedAt || endedAt) continue\n return { entryId: readString(row, 'id'), taskId: readString(row, 'task_id', 'taskId') }\n }\n return { entryId: null, taskId: null }\n },\n })\n\n const runningTimerTaskId = runningTimerQuery.data?.taskId ?? null\n const runningTimerEntryId = runningTimerQuery.data?.entryId ?? null\n\n const invalidateBoard = React.useCallback(() => {\n queryClient.invalidateQueries({ queryKey: [...BOARD_QUERY_ROOT, 'column'] }).catch(() => {})\n queryClient.invalidateQueries({ queryKey: [...BOARD_QUERY_ROOT, 'children'] }).catch(() => {})\n }, [queryClient])\n\n const invalidateStatuses = React.useCallback(() => {\n queryClient.invalidateQueries({ queryKey: [...BOARD_QUERY_ROOT, 'statuses'] }).catch(() => {})\n }, [queryClient])\n\n const markOwnMove = React.useCallback((taskId: string, statusId: string) => {\n ownMoveKeysRef.current.set(`${taskId}|${statusId}`, Date.now())\n }, [])\n\n const consumeOwnMove = React.useCallback((taskId: string, statusId: string): boolean => {\n const keys = ownMoveKeysRef.current\n const key = `${taskId}|${statusId}`\n const stamped = keys.get(key)\n // Drop stale entries so a broadcast that never arrived cannot suppress a later,\n // genuinely remote move of the same card into the same column.\n for (const [entry, at] of keys) {\n if (Date.now() - at > OWN_MOVE_ECHO_TTL_MS) keys.delete(entry)\n }\n if (stamped === undefined) return false\n keys.delete(key)\n return true\n }, [])\n\n useAppEvent(\n TASK_STATUS_CHANGED_EVENT,\n (event) => {\n const eventPayload = event.payload as Record<string, unknown> | null | undefined\n if (!eventPayload) return\n const projectId = typeof eventPayload.timeProjectId === 'string' ? eventPayload.timeProjectId : null\n if (projectId && projectId !== timeProjectId) return\n const taskId =\n typeof eventPayload.taskId === 'string'\n ? eventPayload.taskId\n : typeof eventPayload.id === 'string'\n ? eventPayload.id\n : null\n const statusId = typeof eventPayload.taskStatusId === 'string' ? eventPayload.taskStatusId : null\n if (taskId && statusId && consumeOwnMove(taskId, statusId)) return\n invalidateBoard()\n },\n [consumeOwnMove, invalidateBoard, timeProjectId],\n )\n\n const setTaskPending = React.useCallback((taskId: string, pending: boolean) => {\n setPendingTaskIds((previous) => {\n const next = new Set(previous)\n if (pending) next.add(taskId)\n else next.delete(taskId)\n return next\n })\n }, [])\n\n const moveTask = React.useCallback(\n (taskId: string, targetStatusId: string) => {\n const columnCaches = queryClient.getQueriesData<ColumnCache>({\n queryKey: [...BOARD_QUERY_ROOT, 'column'],\n })\n // The full pre-move picture. Restoring it wholesale is what puts the card back in\n // its origin column on failure, regardless of how many columns the drag touched.\n const snapshot = columnCaches.map(([key, data]) => [key, data] as const)\n\n let sourceStatusId: string | null = null\n let movingRow: BoardApiRow | null = null\n for (const [key, data] of columnCaches) {\n if (!data) continue\n const statusId = statusIdFromColumnKey(key as readonly unknown[])\n if (!statusId) continue\n const index = data.items.findIndex((item) => readString(item, 'id') === taskId)\n if (index < 0) continue\n sourceStatusId = statusId\n movingRow = { ...data.items[index], task_status_id: targetStatusId, taskStatusId: targetStatusId }\n queryClient.setQueryData(key, {\n items: data.items.filter((item) => readString(item, 'id') !== taskId),\n total: Math.max(0, data.total - 1),\n })\n break\n }\n\n if (!movingRow || !sourceStatusId || sourceStatusId === targetStatusId) {\n for (const [key, data] of snapshot) queryClient.setQueryData(key, data)\n return\n }\n\n const targetTasks = tasksByStatusId.get(targetStatusId)?.tasks ?? []\n const position = nextPositionAtColumnTop(targetTasks)\n const landed: BoardApiRow = { ...movingRow, position }\n\n for (const [key, data] of columnCaches) {\n if (!data) continue\n if (statusIdFromColumnKey(key as readonly unknown[]) !== targetStatusId) continue\n queryClient.setQueryData(key, {\n items: [landed, ...data.items],\n total: data.total + 1,\n })\n }\n\n const taskVersion = resolveTaskVersion(taskId, readString(movingRow, 'updated_at', 'updatedAt'))\n setTaskPending(taskId, true)\n setFailedMove(null)\n markOwnMove(taskId, targetStatusId)\n\n runMoveMutation({\n operation: async () => {\n const call = await withScopedApiRequestHeaders(buildOptimisticLockHeader(taskVersion), () =>\n apiCallOrThrow<Record<string, unknown>>(\n `/api/staff/timesheets/tasks/${encodeURIComponent(taskId)}/status`,\n {\n method: 'PATCH',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ taskStatusId: targetStatusId, position }),\n },\n { errorMessage: t('staff.time_tracking.board.move.error', 'Could not move the task.') },\n ),\n )\n return readString(call.result ?? {}, 'updatedAt', 'updated_at')\n },\n context: {\n formId: MOVE_MUTATION_CONTEXT_ID,\n resourceKind: 'staff.timesheets.task',\n resourceId: taskId,\n retryLastMutation: retryMoveMutation,\n },\n })\n .then((confirmedVersion) => {\n // Note 4: the card the optimistic write left in the target column still\n // carries the version this move just spent, so the response's version has\n // to take over until a fetched row carries a newer one.\n if (confirmedVersion) confirmedVersionsRef.current.set(taskId, confirmedVersion)\n invalidateBoard()\n })\n .catch((error: unknown) => {\n // Card first: it goes back where it came from before anything else is decided.\n for (const [key, data] of snapshot) queryClient.setQueryData(key, data)\n consumeOwnMove(taskId, targetStatusId)\n if (surfaceRecordConflict(error, t)) {\n // Somebody else moved this card. Refetch and let the conflict bar speak \u2014\n // retrying here would silently overwrite their move. The version this board\n // remembered is behind the server's, so the refetched row takes over.\n confirmedVersionsRef.current.delete(taskId)\n invalidateBoard()\n return\n }\n setFailedMove({ taskId, targetStatusId })\n const message =\n error instanceof Error && error.message\n ? error.message\n : t('staff.time_tracking.board.move.error', 'Could not move the task.')\n flash(message, 'error')\n })\n .finally(() => {\n setTaskPending(taskId, false)\n })\n },\n [\n consumeOwnMove,\n invalidateBoard,\n markOwnMove,\n queryClient,\n resolveTaskVersion,\n retryMoveMutation,\n runMoveMutation,\n setTaskPending,\n t,\n tasksByStatusId,\n ],\n )\n\n // Pointer only. dnd-kit's keyboard sensor would have to own Enter/Space on the card \u2014\n // the key that opens the drawer \u2014 and it has no sortable context to traverse anyway;\n // keyboard moves go through the card's explicit \"Move\" menu, which calls `moveTask`\n // directly (U3).\n const sensors = useSensors(useSensor(PointerSensor, { activationConstraint: { distance: 4 } }))\n\n const collisionDetection = React.useCallback<CollisionDetection>((args) => pointerWithin(args), [])\n\n const measuringConfig = React.useMemo(\n () => ({ droppable: { strategy: MeasuringStrategy.BeforeDragging } }),\n [],\n )\n\n const statusIdByTaskId = React.useMemo(() => {\n const map = new Map<string, string>()\n for (const [statusId, entry] of tasksByStatusId) {\n for (const task of entry.tasks) map.set(task.id, statusId)\n }\n return map\n }, [tasksByStatusId])\n\n const activeDragTask = React.useMemo(\n () => (activeDragTaskId ? allTasks.find((task) => task.id === activeDragTaskId) ?? null : null),\n [activeDragTaskId, allTasks],\n )\n\n const handleDragStart = React.useCallback((event: DragStartEvent) => {\n setActiveDragTaskId(typeof event.active.id === 'string' ? event.active.id : null)\n }, [])\n\n const handleDragCancel = React.useCallback(() => setActiveDragTaskId(null), [])\n\n const targetStatusIdFor = React.useCallback(\n (overId: UniqueIdentifier | null | undefined): string | null => {\n if (typeof overId !== 'string') return null\n return overId.startsWith(KANBAN_COLUMN_DROPPABLE_PREFIX)\n ? overId.slice(KANBAN_COLUMN_DROPPABLE_PREFIX.length)\n : statusIdByTaskId.get(overId) ?? null\n },\n [statusIdByTaskId],\n )\n\n const handleDragEnd = React.useCallback(\n (event: DragEndEvent) => {\n setActiveDragTaskId(null)\n const taskId = typeof event.active.id === 'string' ? event.active.id : null\n if (!taskId) return\n const targetStatusId = targetStatusIdFor(event.over?.id)\n if (!targetStatusId) return\n if (statusIdByTaskId.get(taskId) === targetStatusId) return\n moveTask(taskId, targetStatusId)\n },\n [moveTask, statusIdByTaskId, targetStatusIdFor],\n )\n\n const moveTargets = React.useMemo<KanbanMoveTarget[]>(\n () => visibleStatuses.map((status) => ({ id: status.id, name: status.name })),\n [visibleStatuses],\n )\n\n const describeTask = React.useCallback(\n (taskId: UniqueIdentifier | null | undefined): string => {\n if (typeof taskId !== 'string') return ''\n return allTasks.find((task) => task.id === taskId)?.title ?? taskId\n },\n [allTasks],\n )\n\n const describeColumn = React.useCallback(\n (overId: UniqueIdentifier | null | undefined): string | null => {\n const statusId = targetStatusIdFor(overId)\n if (!statusId) return null\n return statuses.find((status) => status.id === statusId)?.name ?? statusId\n },\n [statuses, targetStatusIdFor],\n )\n\n // dnd-kit narrates every drag through a live region. Left unset it narrates in English\n // regardless of locale (U9), so the board owns the strings.\n const announcements = React.useMemo<Announcements>(\n () => ({\n onDragStart: ({ active }) =>\n t('staff.time_tracking.board.dnd.dragStart', 'Picked up the task {task}.', {\n task: describeTask(active.id),\n }),\n onDragOver: ({ active, over }) => {\n const column = describeColumn(over?.id)\n return column\n ? t('staff.time_tracking.board.dnd.dragOver', 'The task {task} is over the column {column}.', {\n task: describeTask(active.id),\n column,\n })\n : t('staff.time_tracking.board.dnd.dragOverNothing', 'The task {task} is not over a column.', {\n task: describeTask(active.id),\n })\n },\n onDragEnd: ({ active, over }) => {\n const column = describeColumn(over?.id)\n return column\n ? t('staff.time_tracking.board.dnd.dragEnd', 'The task {task} was dropped into the column {column}.', {\n task: describeTask(active.id),\n column,\n })\n : t('staff.time_tracking.board.dnd.dragEndOutside', 'The task {task} was dropped outside the columns.', {\n task: describeTask(active.id),\n })\n },\n onDragCancel: ({ active }) =>\n t('staff.time_tracking.board.dnd.dragCancel', 'Moving the task {task} was cancelled.', {\n task: describeTask(active.id),\n }),\n }),\n [describeColumn, describeTask, t],\n )\n\n const screenReaderInstructions = React.useMemo<ScreenReaderInstructions>(\n () => ({\n draggable: t(\n 'staff.time_tracking.board.dnd.instructions',\n 'Drag a card with the pointer to move it between columns. With the keyboard, press Enter on a card to open it, or use the Move button in the card actions to choose a target column.',\n ),\n }),\n [t],\n )\n\n const accessibility = React.useMemo(\n () => ({ announcements, screenReaderInstructions }),\n [announcements, screenReaderInstructions],\n )\n\n const handleQuickAdd = React.useCallback(\n async (statusId: string, title: string) => {\n setQuickAddPendingStatusId(statusId)\n try {\n await runCreateMutation({\n operation: () =>\n apiCallOrThrow(\n '/api/staff/timesheets/tasks',\n {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({\n timeProjectId,\n taskStatusId: statusId,\n title,\n // US-C1: the creator owns what they just typed until somebody reassigns it.\n assigneeStaffMemberId: selfStaffMemberId,\n }),\n },\n { errorMessage: t('staff.time_tracking.board.quickAdd.error', 'Could not create the task.') },\n ),\n context: {\n formId: CREATE_MUTATION_CONTEXT_ID,\n resourceKind: 'staff.timesheets.task',\n resourceId: statusId,\n retryLastMutation: retryCreateMutation,\n },\n })\n invalidateBoard()\n } catch (error) {\n if (surfaceRecordConflict(error, t)) return\n logger.error('staff.time_tracking board quick add failed', { err: error })\n flash(\n error instanceof Error && error.message\n ? error.message\n : t('staff.time_tracking.board.quickAdd.error', 'Could not create the task.'),\n 'error',\n )\n } finally {\n setQuickAddPendingStatusId(null)\n }\n },\n [invalidateBoard, retryCreateMutation, runCreateMutation, selfStaffMemberId, t, timeProjectId],\n )\n\n const handleCreateStatus = React.useCallback(async () => {\n const name = statusDraft.trim()\n if (!name) {\n setComposingStatus(false)\n setStatusDraft('')\n return\n }\n try {\n await runCreateMutation({\n operation: () =>\n apiCallOrThrow(\n '/api/staff/timesheets/task-statuses',\n {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ timeProjectId, name }),\n },\n { errorMessage: t('staff.time_tracking.board.addStatus.error', 'Could not add the column.') },\n ),\n context: {\n formId: CREATE_MUTATION_CONTEXT_ID,\n resourceKind: 'staff.timesheets.task_status',\n resourceId: timeProjectId,\n retryLastMutation: retryCreateMutation,\n },\n })\n setStatusDraft('')\n setComposingStatus(false)\n invalidateStatuses()\n } catch (error) {\n if (surfaceRecordConflict(error, t)) return\n flash(\n error instanceof Error && error.message\n ? error.message\n : t('staff.time_tracking.board.addStatus.error', 'Could not add the column.'),\n 'error',\n )\n }\n }, [invalidateStatuses, retryCreateMutation, runCreateMutation, statusDraft, t, timeProjectId])\n\n const handleLoadMore = React.useCallback((statusId: string) => {\n setPagesByStatus((previous) => ({ ...previous, [statusId]: (previous[statusId] ?? 1) + 1 }))\n }, [])\n\n const openTask = React.useCallback(\n (taskId: string) => {\n // Seam for the task drawer (T3.7): the drawer reads `?task=` and the board keeps\n // rendering underneath it.\n const params = new URLSearchParams(searchParams?.toString() ?? '')\n params.set('task', taskId)\n router.push(`?${params.toString()}`, { scroll: false })\n },\n [router, searchParams],\n )\n\n const handleAddTime = React.useCallback(\n (taskId: string) => {\n const params = new URLSearchParams(searchParams?.toString() ?? '')\n params.set('task', taskId)\n params.set('panel', 'time')\n router.push(`?${params.toString()}`, { scroll: false })\n },\n [router, searchParams],\n )\n\n const drawerTaskId = searchParams?.get('task') ?? null\n const drawerPanel = searchParams?.get('panel') ?? null\n\n const closeTaskDrawer = React.useCallback(() => {\n const params = new URLSearchParams(searchParams?.toString() ?? '')\n params.delete('task')\n params.delete('panel')\n const query = params.toString()\n router.push(query.length > 0 ? `?${query}` : '?', { scroll: false })\n }, [router, searchParams])\n\n const handleStartTimer = React.useCallback(\n async (taskId: string) => {\n if (!selfStaffMemberId) return\n const task = allTasks.find((entry) => entry.id === taskId) ?? null\n try {\n const started = await runCreateMutation({\n operation: () =>\n apiCallOrThrow<Record<string, unknown>>(\n '/api/staff/timesheets/time-entries/start-timer',\n {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({\n staffMemberId: selfStaffMemberId,\n timeProjectId,\n date: new Date().toISOString().slice(0, 10),\n notes: task?.title ?? null,\n }),\n },\n { errorMessage: t('staff.time_tracking.board.timer.startError', 'Could not start the timer.') },\n ),\n context: {\n formId: CREATE_MUTATION_CONTEXT_ID,\n resourceKind: 'staff.timesheets.time_entry',\n resourceId: taskId,\n retryLastMutation: retryCreateMutation,\n },\n })\n const entryId = typeof started?.result?.id === 'string' ? started.result.id : null\n if (entryId) {\n // `start-timer` creates the entry atomically but takes no task, so the link is a\n // second write. A failure here leaves a running, project-level timer rather than\n // no timer at all \u2014 the lesser of the two wrong states.\n const linked = await apiCall(`/api/staff/timesheets/time-entries`, {\n method: 'PUT',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ id: entryId, taskId }),\n })\n if (!linked.ok) {\n flash(\n t(\n 'staff.time_tracking.board.timer.linkWarning',\n 'The timer is running but is not linked to this task yet.',\n ),\n 'warning',\n )\n }\n }\n await runningTimerQuery.refetch()\n } catch (error) {\n if (surfaceRecordConflict(error, t)) return\n flash(\n error instanceof Error && error.message\n ? error.message\n : t('staff.time_tracking.board.timer.startError', 'Could not start the timer.'),\n 'error',\n )\n }\n },\n [allTasks, retryCreateMutation, runCreateMutation, runningTimerQuery, selfStaffMemberId, t, timeProjectId],\n )\n\n const handleStopTimer = React.useCallback(async () => {\n if (!runningTimerEntryId) return\n try {\n await runCreateMutation({\n operation: () =>\n apiCallOrThrow(\n `/api/staff/timesheets/time-entries/${encodeURIComponent(runningTimerEntryId)}/timer-stop`,\n { method: 'POST' },\n { errorMessage: t('staff.time_tracking.board.timer.stopError', 'Could not stop the timer.') },\n ),\n context: {\n formId: CREATE_MUTATION_CONTEXT_ID,\n resourceKind: 'staff.timesheets.time_entry',\n resourceId: runningTimerEntryId,\n retryLastMutation: retryCreateMutation,\n },\n })\n await runningTimerQuery.refetch()\n invalidateBoard()\n } catch (error) {\n if (surfaceRecordConflict(error, t)) return\n flash(\n error instanceof Error && error.message\n ? error.message\n : t('staff.time_tracking.board.timer.stopError', 'Could not stop the timer.'),\n 'error',\n )\n }\n }, [invalidateBoard, retryCreateMutation, runCreateMutation, runningTimerEntryId, runningTimerQuery, t])\n\n // Never fold `loggedMinutes` inline: a parent's figure already contains its children's,\n // so the shared helper \u2014 which drops any row whose parent is in the same set \u2014 is the\n // only thing standing between this number and risk R10.\n const summary = React.useMemo<BoardSummary>(\n () => ({ taskCount: allTasks.length, loggedMinutes: sumTaskLoggedMinutes(allTasks) }),\n [allTasks],\n )\n\n React.useEffect(() => {\n onSummaryChange?.(summary)\n }, [onSummaryChange, summary])\n\n if (statusesQuery.isLoading) {\n return <LoadingMessage label={t('staff.time_tracking.board.loading', 'Loading the board\u2026')} />\n }\n\n if (statusesQuery.isError) {\n return (\n <ErrorMessage\n label={t('staff.time_tracking.board.loadError', 'Could not load the board.')}\n action={\n <Button type=\"button\" variant=\"outline\" size=\"sm\" onClick={() => void statusesQuery.refetch()}>\n {t('staff.time_tracking.board.reload', 'Try again')}\n </Button>\n }\n />\n )\n }\n\n if (statuses.length === 0) {\n return (\n <EmptyState\n title={t('staff.time_tracking.board.empty.title', 'This project has no columns yet')}\n description={t(\n 'staff.time_tracking.board.empty.description',\n 'A Team Leader configures the board columns for each project.',\n )}\n />\n )\n }\n\n return (\n <div className=\"flex flex-col gap-4\">\n <InjectionSpot\n spotId={extensionPoints.hosts.taskBoardToolbar.spotId}\n context={{ timeProjectId, projectName: projectName ?? null, statusIds: visibleStatuses.map((status) => status.id) }}\n data={summary}\n />\n\n {failedMove ? (\n <Alert status=\"error\" data-testid=\"kanban-move-retry\">\n <AlertDescription className=\"flex flex-wrap items-center gap-3\">\n <span>\n {t('staff.time_tracking.board.move.rolledBack', 'The task was moved back \u2014 the change was not saved.')}\n </span>\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n onClick={() => {\n const retry = failedMove\n setFailedMove(null)\n moveTask(retry.taskId, retry.targetStatusId)\n }}\n >\n <RotateCcw className=\"size-3.5\" aria-hidden=\"true\" />\n {t('staff.time_tracking.board.move.retry', 'Retry')}\n </Button>\n </AlertDescription>\n </Alert>\n ) : null}\n\n <DndContext\n sensors={sensors}\n accessibility={accessibility}\n collisionDetection={collisionDetection}\n measuring={measuringConfig}\n onDragStart={handleDragStart}\n onDragEnd={handleDragEnd}\n onDragCancel={handleDragCancel}\n >\n <div\n className={`flex min-w-0 gap-3.5 overflow-x-auto pb-6 ${\n activeDragTaskId ? 'cursor-grabbing select-none' : ''\n }`}\n >\n {visibleStatuses.map((status, index) => {\n const entry = tasksByStatusId.get(status.id)\n const serverTotal = entry?.total ?? 0\n const loaded = entry?.loaded ?? 0\n return (\n <KanbanColumn\n key={status.id}\n status={status}\n tasks={entry?.tasks ?? []}\n total={serverTotal}\n remaining={Math.max(0, serverTotal - loaded)}\n canQuickAdd={canManageTasks}\n loadingMore={columnQueries[index]?.isFetching ?? false}\n activeDragTaskId={activeDragTaskId}\n pendingTaskIds={pendingTaskIds}\n runningTimerTaskId={runningTimerTaskId}\n assigneeNames={assigneeQuery.data ?? new Map<string, string>()}\n tagsByTaskId={tagsByTaskId}\n subtasksByTaskId={subtasksByTaskId}\n quickAddPending={quickAddPendingStatusId === status.id}\n moveTargets={moveTargets}\n onQuickAdd={handleQuickAdd}\n onLoadMore={handleLoadMore}\n onOpenTask={openTask}\n onStartTimer={handleStartTimer}\n onStopTimer={handleStopTimer}\n onAddTime={handleAddTime}\n onMoveTask={moveTask}\n />\n )\n })}\n\n {canManageColumns ? (\n <div className=\"flex w-72 flex-none flex-col gap-3\">\n {composingStatus ? (\n <Input\n autoFocus\n value={statusDraft}\n onChange={(event) => setStatusDraft(event.target.value)}\n onKeyDown={(event) => {\n if (event.key === 'Enter') {\n event.preventDefault()\n void handleCreateStatus()\n }\n if (event.key === 'Escape') {\n event.preventDefault()\n setComposingStatus(false)\n setStatusDraft('')\n }\n }}\n placeholder={t('staff.time_tracking.board.addStatus.placeholder', 'Column name')}\n aria-label={t('staff.time_tracking.board.addStatus.cta', 'Add status')}\n data-testid=\"kanban-add-status-input\"\n />\n ) : (\n <Button\n type=\"button\"\n variant=\"ghost\"\n onClick={() => setComposingStatus(true)}\n data-testid=\"kanban-add-status\"\n className=\"flex h-24 flex-col items-center justify-center gap-2 rounded-lg border border-dashed border-muted-foreground/60 bg-muted/40 text-sm font-semibold leading-normal text-muted-foreground hover:text-foreground\"\n >\n <Plus className=\"size-5\" aria-hidden=\"true\" />\n {t('staff.time_tracking.board.addStatus.cta', 'Add status')}\n </Button>\n )}\n </div>\n ) : null}\n </div>\n\n <DragOverlay dropAnimation={null}>\n {activeDragTask ? (\n <div\n data-testid=\"kanban-drag-overlay\"\n className=\"pointer-events-none w-72 rotate-2 cursor-grabbing select-none rounded-lg border border-border bg-card px-4 py-3 opacity-80 shadow-xl\"\n >\n <div className=\"text-sm font-semibold leading-normal text-foreground\">\n {activeDragTask.title}\n </div>\n <div className=\"mt-2 text-xs font-semibold tabular-nums leading-normal text-muted-foreground\">\n {formatBoardMinutes(activeDragTask.loggedMinutes)}\n </div>\n </div>\n ) : null}\n </DragOverlay>\n </DndContext>\n\n {drawerTaskId ? (\n <TaskDrawer\n taskId={drawerTaskId}\n open\n onOpenChange={(next) => {\n if (!next) closeTaskDrawer()\n }}\n projectName={projectName ?? null}\n focusPanel={drawerPanel}\n onChanged={invalidateBoard}\n />\n ) : null}\n </div>\n )\n}\n\nexport default KanbanBoard\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,360 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import { z } from "zod";
|
|
5
|
+
import { useDraggable } from "@dnd-kit/core";
|
|
6
|
+
import { ArrowRightLeft, Check, Play, Plus, Square } from "lucide-react";
|
|
7
|
+
import { Avatar } from "@open-mercato/ui/primitives/avatar";
|
|
8
|
+
import { Badge } from "@open-mercato/ui/primitives/badge";
|
|
9
|
+
import { Button } from "@open-mercato/ui/primitives/button";
|
|
10
|
+
import { Progress } from "@open-mercato/ui/primitives/progress";
|
|
11
|
+
import { useT } from "@open-mercato/shared/lib/i18n/context";
|
|
12
|
+
import { InjectionSpot } from "@open-mercato/ui/backend/injection/InjectionSpot";
|
|
13
|
+
import { extensionPoints } from "@open-mercato/core/modules/staff/extension-points";
|
|
14
|
+
import { registerComponent } from "@open-mercato/shared/modules/widgets/component-registry";
|
|
15
|
+
import { useRegisteredComponent } from "@open-mercato/ui/backend/injection/useRegisteredComponent";
|
|
16
|
+
import { callbackProp, opaqueProp, optionalCallbackProp } from "../time-tracking/componentContracts.js";
|
|
17
|
+
import {
|
|
18
|
+
formatBoardMinutes,
|
|
19
|
+
initialsFromName
|
|
20
|
+
} from "./kanbanBoardData.js";
|
|
21
|
+
function useCoarsePointer() {
|
|
22
|
+
const [coarse, setCoarse] = React.useState(false);
|
|
23
|
+
React.useEffect(() => {
|
|
24
|
+
if (typeof window === "undefined" || typeof window.matchMedia !== "function") return;
|
|
25
|
+
const query = window.matchMedia("(hover: none)");
|
|
26
|
+
setCoarse(query.matches);
|
|
27
|
+
const listener = (event) => setCoarse(event.matches);
|
|
28
|
+
if (typeof query.addEventListener === "function") {
|
|
29
|
+
query.addEventListener("change", listener);
|
|
30
|
+
return () => query.removeEventListener("change", listener);
|
|
31
|
+
}
|
|
32
|
+
return void 0;
|
|
33
|
+
}, []);
|
|
34
|
+
return coarse;
|
|
35
|
+
}
|
|
36
|
+
const TASK_ENTITY_ID = "staff:staff_time_task";
|
|
37
|
+
const EMPTY_MOVE_TARGETS = [];
|
|
38
|
+
function KanbanCardImpl({
|
|
39
|
+
task,
|
|
40
|
+
assigneeName,
|
|
41
|
+
tags,
|
|
42
|
+
subtasks,
|
|
43
|
+
timerRunning,
|
|
44
|
+
pending,
|
|
45
|
+
isActiveDrag,
|
|
46
|
+
moveTargets = EMPTY_MOVE_TARGETS,
|
|
47
|
+
onOpen,
|
|
48
|
+
onStartTimer,
|
|
49
|
+
onStopTimer,
|
|
50
|
+
onAddTime,
|
|
51
|
+
onMoveToColumn
|
|
52
|
+
}) {
|
|
53
|
+
const t = useT();
|
|
54
|
+
const coarsePointer = useCoarsePointer();
|
|
55
|
+
const { attributes, listeners, setNodeRef, isDragging } = useDraggable({
|
|
56
|
+
id: task.id,
|
|
57
|
+
data: { type: "task", taskStatusId: task.taskStatusId }
|
|
58
|
+
});
|
|
59
|
+
const dimmed = isActiveDrag || isDragging;
|
|
60
|
+
const stopPointerDown = React.useCallback((event) => {
|
|
61
|
+
event.stopPropagation();
|
|
62
|
+
}, []);
|
|
63
|
+
const handleCardClick = React.useCallback(
|
|
64
|
+
(event) => {
|
|
65
|
+
const target = event.target;
|
|
66
|
+
if (target.closest('[data-card-action="true"]')) return;
|
|
67
|
+
onOpen(task.id);
|
|
68
|
+
},
|
|
69
|
+
[onOpen, task.id]
|
|
70
|
+
);
|
|
71
|
+
const handleKeyDown = React.useCallback(
|
|
72
|
+
(event) => {
|
|
73
|
+
if (event.key !== "Enter") return;
|
|
74
|
+
const target = event.target;
|
|
75
|
+
if (target.closest('[data-card-action="true"]')) return;
|
|
76
|
+
event.preventDefault();
|
|
77
|
+
onOpen(task.id);
|
|
78
|
+
},
|
|
79
|
+
[onOpen, task.id]
|
|
80
|
+
);
|
|
81
|
+
const [moveMenuOpen, setMoveMenuOpen] = React.useState(false);
|
|
82
|
+
const moveTriggerRef = React.useRef(null);
|
|
83
|
+
const moveMenuRef = React.useRef(null);
|
|
84
|
+
const moveItemRefs = React.useRef([]);
|
|
85
|
+
const showMoveMenu = moveTargets.length > 0 && typeof onMoveToColumn === "function";
|
|
86
|
+
React.useEffect(() => {
|
|
87
|
+
if (!moveMenuOpen) return;
|
|
88
|
+
moveItemRefs.current[0]?.focus();
|
|
89
|
+
}, [moveMenuOpen]);
|
|
90
|
+
React.useEffect(() => {
|
|
91
|
+
if (!moveMenuOpen) return;
|
|
92
|
+
const handleOutside = (event) => {
|
|
93
|
+
const target = event.target;
|
|
94
|
+
if (moveMenuRef.current?.contains(target)) return;
|
|
95
|
+
if (moveTriggerRef.current?.contains(target)) return;
|
|
96
|
+
setMoveMenuOpen(false);
|
|
97
|
+
};
|
|
98
|
+
document.addEventListener("mousedown", handleOutside);
|
|
99
|
+
return () => document.removeEventListener("mousedown", handleOutside);
|
|
100
|
+
}, [moveMenuOpen]);
|
|
101
|
+
const closeMoveMenu = React.useCallback(() => {
|
|
102
|
+
setMoveMenuOpen(false);
|
|
103
|
+
moveTriggerRef.current?.focus();
|
|
104
|
+
}, []);
|
|
105
|
+
const handleMoveMenuKeyDown = React.useCallback(
|
|
106
|
+
(event) => {
|
|
107
|
+
if (event.key === "Escape") {
|
|
108
|
+
event.preventDefault();
|
|
109
|
+
closeMoveMenu();
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
if (event.key !== "ArrowDown" && event.key !== "ArrowUp") return;
|
|
113
|
+
event.preventDefault();
|
|
114
|
+
const items = moveItemRefs.current.filter(
|
|
115
|
+
(item) => item !== null && item.isConnected
|
|
116
|
+
);
|
|
117
|
+
if (items.length === 0) return;
|
|
118
|
+
const current = items.indexOf(document.activeElement);
|
|
119
|
+
const step = event.key === "ArrowDown" ? 1 : -1;
|
|
120
|
+
const next = current < 0 ? 0 : (current + step + items.length) % items.length;
|
|
121
|
+
items[next]?.focus();
|
|
122
|
+
},
|
|
123
|
+
[closeMoveMenu]
|
|
124
|
+
);
|
|
125
|
+
const handleMoveSelect = React.useCallback(
|
|
126
|
+
(targetStatusId) => {
|
|
127
|
+
setMoveMenuOpen(false);
|
|
128
|
+
moveTriggerRef.current?.focus();
|
|
129
|
+
onMoveToColumn?.(task.id, targetStatusId);
|
|
130
|
+
},
|
|
131
|
+
[onMoveToColumn, task.id]
|
|
132
|
+
);
|
|
133
|
+
const quickActionsVisible = coarsePointer ? "opacity-100" : "opacity-0 transition-opacity group-hover:opacity-100 group-focus-within:opacity-100";
|
|
134
|
+
const cardInjectionContext = React.useMemo(
|
|
135
|
+
() => ({
|
|
136
|
+
entityId: TASK_ENTITY_ID,
|
|
137
|
+
recordId: task.id,
|
|
138
|
+
taskId: task.id,
|
|
139
|
+
timeProjectId: task.timeProjectId ?? null,
|
|
140
|
+
taskStatusId: task.taskStatusId ?? null,
|
|
141
|
+
timerRunning
|
|
142
|
+
}),
|
|
143
|
+
[task.id, task.taskStatusId, task.timeProjectId, timerRunning]
|
|
144
|
+
);
|
|
145
|
+
const subtaskPercent = subtasks && subtasks.total > 0 ? Math.round(subtasks.done / subtasks.total * 100) : 0;
|
|
146
|
+
return /* @__PURE__ */ jsxs(
|
|
147
|
+
"div",
|
|
148
|
+
{
|
|
149
|
+
ref: setNodeRef,
|
|
150
|
+
...attributes,
|
|
151
|
+
...listeners,
|
|
152
|
+
"data-task-card": task.id,
|
|
153
|
+
"aria-label": t("staff.time_tracking.board.card.aria", "Task: {title}", { title: task.title }),
|
|
154
|
+
onClick: handleCardClick,
|
|
155
|
+
onKeyDown: handleKeyDown,
|
|
156
|
+
className: `group relative flex w-full flex-col gap-2 rounded-lg border border-border bg-card px-4 py-3 shadow-xs transition-shadow ${dimmed ? "cursor-grabbing opacity-30" : "cursor-grab hover:shadow-sm active:cursor-grabbing"} ${pending ? "opacity-70" : ""}`,
|
|
157
|
+
children: [
|
|
158
|
+
/* @__PURE__ */ jsx("div", { className: "text-sm font-semibold leading-normal text-foreground", children: task.title }),
|
|
159
|
+
tags.length > 0 ? /* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-1", children: tags.map((tag) => /* @__PURE__ */ jsx(Badge, { variant: "info", size: "sm", children: tag.label }, tag.id)) }) : null,
|
|
160
|
+
/* @__PURE__ */ jsx(
|
|
161
|
+
InjectionSpot,
|
|
162
|
+
{
|
|
163
|
+
spotId: extensionPoints.hosts.taskBoardCardBadges.spotId,
|
|
164
|
+
context: cardInjectionContext,
|
|
165
|
+
data: task
|
|
166
|
+
}
|
|
167
|
+
),
|
|
168
|
+
subtasks && subtasks.total > 0 ? /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
169
|
+
/* @__PURE__ */ jsxs("span", { className: "flex items-center gap-1 text-xs font-medium leading-normal text-muted-foreground", children: [
|
|
170
|
+
/* @__PURE__ */ jsx(Check, { className: "size-3", "aria-hidden": "true" }),
|
|
171
|
+
t("staff.time_tracking.board.card.subtasks", "{done}/{total} subtasks", {
|
|
172
|
+
done: subtasks.done,
|
|
173
|
+
total: subtasks.total
|
|
174
|
+
})
|
|
175
|
+
] }),
|
|
176
|
+
/* @__PURE__ */ jsx(Progress, { value: subtaskPercent, size: "sm", tone: "success" })
|
|
177
|
+
] }) : null,
|
|
178
|
+
/* @__PURE__ */ jsx("div", { className: "h-px w-full bg-border", "aria-hidden": "true" }),
|
|
179
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
180
|
+
/* @__PURE__ */ jsx(
|
|
181
|
+
Avatar,
|
|
182
|
+
{
|
|
183
|
+
size: "xs",
|
|
184
|
+
label: initialsFromName(assigneeName),
|
|
185
|
+
ariaLabel: assigneeName ? t("staff.time_tracking.board.card.assignee", "Assigned to {name}", { name: assigneeName }) : t("staff.time_tracking.board.card.unassigned", "Unassigned")
|
|
186
|
+
}
|
|
187
|
+
),
|
|
188
|
+
timerRunning ? /* @__PURE__ */ jsx(Badge, { variant: "success", size: "sm", dot: true, children: t("staff.time_tracking.board.card.timerRunning", "timer") }) : null,
|
|
189
|
+
/* @__PURE__ */ jsx("span", { className: "grow" }),
|
|
190
|
+
/* @__PURE__ */ jsx("span", { className: "text-xs font-semibold tabular-nums leading-normal text-foreground", children: formatBoardMinutes(task.loggedMinutes) })
|
|
191
|
+
] }),
|
|
192
|
+
/* @__PURE__ */ jsxs(
|
|
193
|
+
"div",
|
|
194
|
+
{
|
|
195
|
+
"data-card-action": "true",
|
|
196
|
+
"data-testid": `kanban-card-actions-${task.id}`,
|
|
197
|
+
onPointerDown: stopPointerDown,
|
|
198
|
+
className: `flex flex-wrap items-center gap-1.5 ${moveMenuOpen ? "opacity-100" : quickActionsVisible}`,
|
|
199
|
+
children: [
|
|
200
|
+
timerRunning ? /* @__PURE__ */ jsxs(
|
|
201
|
+
Button,
|
|
202
|
+
{
|
|
203
|
+
type: "button",
|
|
204
|
+
variant: "outline",
|
|
205
|
+
size: "2xs",
|
|
206
|
+
"aria-label": t("staff.time_tracking.board.card.stopTimerAria", "Stop the timer for {title}", {
|
|
207
|
+
title: task.title
|
|
208
|
+
}),
|
|
209
|
+
onClick: () => onStopTimer(task.id),
|
|
210
|
+
children: [
|
|
211
|
+
/* @__PURE__ */ jsx(Square, { className: "size-3", "aria-hidden": "true" }),
|
|
212
|
+
t("staff.time_tracking.board.card.stopTimer", "Stop")
|
|
213
|
+
]
|
|
214
|
+
}
|
|
215
|
+
) : /* @__PURE__ */ jsxs(
|
|
216
|
+
Button,
|
|
217
|
+
{
|
|
218
|
+
type: "button",
|
|
219
|
+
variant: "outline",
|
|
220
|
+
size: "2xs",
|
|
221
|
+
"aria-label": t("staff.time_tracking.board.card.startTimerAria", "Start a timer for {title}", {
|
|
222
|
+
title: task.title
|
|
223
|
+
}),
|
|
224
|
+
onClick: () => onStartTimer(task.id),
|
|
225
|
+
children: [
|
|
226
|
+
/* @__PURE__ */ jsx(Play, { className: "size-3", "aria-hidden": "true" }),
|
|
227
|
+
t("staff.time_tracking.board.card.startTimer", "Start")
|
|
228
|
+
]
|
|
229
|
+
}
|
|
230
|
+
),
|
|
231
|
+
/* @__PURE__ */ jsxs(
|
|
232
|
+
Button,
|
|
233
|
+
{
|
|
234
|
+
type: "button",
|
|
235
|
+
variant: "outline",
|
|
236
|
+
size: "2xs",
|
|
237
|
+
"aria-label": t("staff.time_tracking.board.card.addTimeAria", "Add time to {title}", {
|
|
238
|
+
title: task.title
|
|
239
|
+
}),
|
|
240
|
+
onClick: () => onAddTime(task.id),
|
|
241
|
+
children: [
|
|
242
|
+
/* @__PURE__ */ jsx(Plus, { className: "size-3", "aria-hidden": "true" }),
|
|
243
|
+
t("staff.time_tracking.board.card.addTime", "Add time")
|
|
244
|
+
]
|
|
245
|
+
}
|
|
246
|
+
),
|
|
247
|
+
showMoveMenu ? /* @__PURE__ */ jsxs("div", { className: "relative", children: [
|
|
248
|
+
/* @__PURE__ */ jsxs(
|
|
249
|
+
Button,
|
|
250
|
+
{
|
|
251
|
+
ref: moveTriggerRef,
|
|
252
|
+
type: "button",
|
|
253
|
+
variant: "outline",
|
|
254
|
+
size: "2xs",
|
|
255
|
+
"aria-haspopup": "menu",
|
|
256
|
+
"aria-expanded": moveMenuOpen,
|
|
257
|
+
"aria-label": t("staff.time_tracking.board.card.moveTo.aria", "Move {title} to another column", {
|
|
258
|
+
title: task.title
|
|
259
|
+
}),
|
|
260
|
+
"data-testid": `kanban-card-move-${task.id}`,
|
|
261
|
+
onClick: () => setMoveMenuOpen((open) => !open),
|
|
262
|
+
onKeyDown: (event) => {
|
|
263
|
+
if (event.key !== "ArrowDown") return;
|
|
264
|
+
event.preventDefault();
|
|
265
|
+
setMoveMenuOpen(true);
|
|
266
|
+
},
|
|
267
|
+
children: [
|
|
268
|
+
/* @__PURE__ */ jsx(ArrowRightLeft, { className: "size-3", "aria-hidden": "true" }),
|
|
269
|
+
t("staff.time_tracking.board.card.moveTo.cta", "Move")
|
|
270
|
+
]
|
|
271
|
+
}
|
|
272
|
+
),
|
|
273
|
+
moveMenuOpen ? /* @__PURE__ */ jsx(
|
|
274
|
+
"div",
|
|
275
|
+
{
|
|
276
|
+
ref: moveMenuRef,
|
|
277
|
+
role: "menu",
|
|
278
|
+
"aria-label": t("staff.time_tracking.board.card.moveTo.menu", "Move {title} to", {
|
|
279
|
+
title: task.title
|
|
280
|
+
}),
|
|
281
|
+
"data-testid": `kanban-card-move-menu-${task.id}`,
|
|
282
|
+
onKeyDown: handleMoveMenuKeyDown,
|
|
283
|
+
className: "absolute bottom-full left-0 z-dropdown mb-1 flex min-w-40 flex-col gap-0.5 rounded-md border border-border bg-popover p-1 text-popover-foreground shadow-md",
|
|
284
|
+
children: moveTargets.map((target, index) => /* @__PURE__ */ jsx(
|
|
285
|
+
Button,
|
|
286
|
+
{
|
|
287
|
+
ref: (node) => {
|
|
288
|
+
moveItemRefs.current[index] = node;
|
|
289
|
+
},
|
|
290
|
+
type: "button",
|
|
291
|
+
variant: "ghost",
|
|
292
|
+
size: "2xs",
|
|
293
|
+
role: "menuitem",
|
|
294
|
+
className: "justify-start",
|
|
295
|
+
"data-testid": `kanban-card-move-option-${task.id}-${target.id}`,
|
|
296
|
+
onClick: () => handleMoveSelect(target.id),
|
|
297
|
+
children: target.name
|
|
298
|
+
},
|
|
299
|
+
target.id
|
|
300
|
+
))
|
|
301
|
+
}
|
|
302
|
+
) : null
|
|
303
|
+
] }) : null
|
|
304
|
+
]
|
|
305
|
+
}
|
|
306
|
+
),
|
|
307
|
+
/* @__PURE__ */ jsx(
|
|
308
|
+
InjectionSpot,
|
|
309
|
+
{
|
|
310
|
+
spotId: extensionPoints.hosts.taskBoardCardFooter.spotId,
|
|
311
|
+
context: cardInjectionContext,
|
|
312
|
+
data: task
|
|
313
|
+
}
|
|
314
|
+
)
|
|
315
|
+
]
|
|
316
|
+
}
|
|
317
|
+
);
|
|
318
|
+
}
|
|
319
|
+
const DefaultKanbanCard = React.memo(KanbanCardImpl);
|
|
320
|
+
const kanbanTagOptionSchema = z.object({ id: z.string(), label: z.string() });
|
|
321
|
+
const kanbanMoveTargetSchema = z.object({ id: z.string(), name: z.string() });
|
|
322
|
+
const kanbanCardPropsSchema = z.object({
|
|
323
|
+
task: opaqueProp(),
|
|
324
|
+
assigneeName: z.string().nullable(),
|
|
325
|
+
tags: z.array(kanbanTagOptionSchema),
|
|
326
|
+
subtasks: opaqueProp().nullable(),
|
|
327
|
+
timerRunning: z.boolean(),
|
|
328
|
+
pending: z.boolean(),
|
|
329
|
+
isActiveDrag: z.boolean(),
|
|
330
|
+
moveTargets: z.array(kanbanMoveTargetSchema).optional(),
|
|
331
|
+
onOpen: callbackProp(),
|
|
332
|
+
onStartTimer: callbackProp(),
|
|
333
|
+
onStopTimer: callbackProp(),
|
|
334
|
+
onAddTime: callbackProp(),
|
|
335
|
+
onMoveToColumn: optionalCallbackProp()
|
|
336
|
+
});
|
|
337
|
+
registerComponent({
|
|
338
|
+
id: extensionPoints.hosts.kanbanCardComponent.componentId,
|
|
339
|
+
component: DefaultKanbanCard,
|
|
340
|
+
metadata: {
|
|
341
|
+
module: "staff",
|
|
342
|
+
description: "One task card on the time-tracking Kanban board.",
|
|
343
|
+
propsSchema: kanbanCardPropsSchema
|
|
344
|
+
}
|
|
345
|
+
});
|
|
346
|
+
function KanbanCardHost(props) {
|
|
347
|
+
const Resolved = useRegisteredComponent(
|
|
348
|
+
extensionPoints.hosts.kanbanCardComponent.componentId,
|
|
349
|
+
DefaultKanbanCard
|
|
350
|
+
);
|
|
351
|
+
return /* @__PURE__ */ jsx(Resolved, { ...props });
|
|
352
|
+
}
|
|
353
|
+
const KanbanCard = React.memo(KanbanCardHost);
|
|
354
|
+
var KanbanCard_default = KanbanCard;
|
|
355
|
+
export {
|
|
356
|
+
KanbanCard,
|
|
357
|
+
KanbanCard_default as default,
|
|
358
|
+
useCoarsePointer
|
|
359
|
+
};
|
|
360
|
+
//# sourceMappingURL=KanbanCard.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../../src/modules/staff/lib/time-tracking-ui/KanbanCard.tsx"],
|
|
4
|
+
"sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { z } from 'zod'\nimport { useDraggable } from '@dnd-kit/core'\nimport { ArrowRightLeft, Check, Play, Plus, Square } from 'lucide-react'\nimport { Avatar } from '@open-mercato/ui/primitives/avatar'\nimport { Badge } from '@open-mercato/ui/primitives/badge'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { Progress } from '@open-mercato/ui/primitives/progress'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { InjectionSpot } from '@open-mercato/ui/backend/injection/InjectionSpot'\nimport { extensionPoints } from '@open-mercato/core/modules/staff/extension-points'\nimport { registerComponent } from '@open-mercato/shared/modules/widgets/component-registry'\nimport { useRegisteredComponent } from '@open-mercato/ui/backend/injection/useRegisteredComponent'\nimport { callbackProp, opaqueProp, optionalCallbackProp } from '../time-tracking/componentContracts'\nimport {\n formatBoardMinutes,\n initialsFromName,\n type BoardTask,\n type SubtaskProgress,\n} from './kanbanBoardData'\n\n/**\n * Quick actions are hover- and focus-revealed on a pointer device (mockup note 3),\n * which leaves them unreachable on a touch screen where neither state exists. The\n * media query is read at runtime rather than expressed as a Tailwind variant so the\n * card can hand the same `visible` decision to both the class list and the tests.\n */\nexport function useCoarsePointer(): boolean {\n const [coarse, setCoarse] = React.useState(false)\n React.useEffect(() => {\n if (typeof window === 'undefined' || typeof window.matchMedia !== 'function') return\n const query = window.matchMedia('(hover: none)')\n setCoarse(query.matches)\n const listener = (event: MediaQueryListEvent) => setCoarse(event.matches)\n if (typeof query.addEventListener === 'function') {\n query.addEventListener('change', listener)\n return () => query.removeEventListener('change', listener)\n }\n return undefined\n }, [])\n return coarse\n}\n\nconst TASK_ENTITY_ID = 'staff:staff_time_task'\n\nexport type KanbanTagOption = {\n id: string\n label: string\n}\n\n/** A column this card can be moved into \u2014 every board column except its own. */\nexport type KanbanMoveTarget = {\n id: string\n name: string\n}\n\nexport type KanbanCardProps = {\n task: BoardTask\n assigneeName: string | null\n tags: KanbanTagOption[]\n subtasks: SubtaskProgress | null\n /** A running timer marks the card permanently \u2014 never hover-dependent (note 3). */\n timerRunning: boolean\n pending: boolean\n isActiveDrag: boolean\n /**\n * Columns offered by the keyboard move menu. Empty (the default) hides the\n * control, which is what a single-column board should do.\n */\n moveTargets?: readonly KanbanMoveTarget[]\n onOpen: (taskId: string) => void\n onStartTimer: (taskId: string) => void\n onStopTimer: (taskId: string) => void\n onAddTime: (taskId: string) => void\n /** Same move the drag performs \u2014 optimistic update, lock header, rollback and all. */\n onMoveToColumn?: (taskId: string, targetStatusId: string) => void\n}\n\nconst EMPTY_MOVE_TARGETS: readonly KanbanMoveTarget[] = []\n\nfunction KanbanCardImpl({\n task,\n assigneeName,\n tags,\n subtasks,\n timerRunning,\n pending,\n isActiveDrag,\n moveTargets = EMPTY_MOVE_TARGETS,\n onOpen,\n onStartTimer,\n onStopTimer,\n onAddTime,\n onMoveToColumn,\n}: KanbanCardProps): React.ReactElement {\n const t = useT()\n const coarsePointer = useCoarsePointer()\n const { attributes, listeners, setNodeRef, isDragging } = useDraggable({\n id: task.id,\n data: { type: 'task', taskStatusId: task.taskStatusId },\n })\n const dimmed = isActiveDrag || isDragging\n\n // dnd-kit's draggable listeners take pointer capture on the card, which rewrites the\n // subsequent click's target to the card itself and swallows the inner buttons. Cutting\n // the pointerdown at the action row keeps Start / Stop / Add time clickable.\n const stopPointerDown = React.useCallback((event: React.PointerEvent) => {\n event.stopPropagation()\n }, [])\n\n const handleCardClick = React.useCallback(\n (event: React.MouseEvent<HTMLDivElement>) => {\n const target = event.target as HTMLElement\n if (target.closest('[data-card-action=\"true\"]')) return\n onOpen(task.id)\n },\n [onOpen, task.id],\n )\n\n const handleKeyDown = React.useCallback(\n (event: React.KeyboardEvent<HTMLDivElement>) => {\n if (event.key !== 'Enter') return\n const target = event.target as HTMLElement\n if (target.closest('[data-card-action=\"true\"]')) return\n event.preventDefault()\n onOpen(task.id)\n },\n [onOpen, task.id],\n )\n\n // Keyboard operability of the board does NOT go through dnd-kit: its keyboard sensor\n // would have to own Enter/Space on the card, and Enter is what opens the drawer. The\n // move is an explicit menu instead \u2014 same `onMoveToColumn` the drop calls, so a keyboard\n // move is the identical optimistic, version-locked request a drag issues.\n const [moveMenuOpen, setMoveMenuOpen] = React.useState(false)\n const moveTriggerRef = React.useRef<HTMLButtonElement | null>(null)\n const moveMenuRef = React.useRef<HTMLDivElement | null>(null)\n const moveItemRefs = React.useRef<(HTMLButtonElement | null)[]>([])\n const showMoveMenu = moveTargets.length > 0 && typeof onMoveToColumn === 'function'\n\n React.useEffect(() => {\n if (!moveMenuOpen) return\n moveItemRefs.current[0]?.focus()\n }, [moveMenuOpen])\n\n React.useEffect(() => {\n if (!moveMenuOpen) return\n const handleOutside = (event: MouseEvent) => {\n const target = event.target as Node\n if (moveMenuRef.current?.contains(target)) return\n if (moveTriggerRef.current?.contains(target)) return\n setMoveMenuOpen(false)\n }\n document.addEventListener('mousedown', handleOutside)\n return () => document.removeEventListener('mousedown', handleOutside)\n }, [moveMenuOpen])\n\n const closeMoveMenu = React.useCallback(() => {\n setMoveMenuOpen(false)\n moveTriggerRef.current?.focus()\n }, [])\n\n const handleMoveMenuKeyDown = React.useCallback(\n (event: React.KeyboardEvent<HTMLDivElement>) => {\n if (event.key === 'Escape') {\n event.preventDefault()\n closeMoveMenu()\n return\n }\n if (event.key !== 'ArrowDown' && event.key !== 'ArrowUp') return\n event.preventDefault()\n const items = moveItemRefs.current.filter(\n (item): item is HTMLButtonElement => item !== null && item.isConnected,\n )\n if (items.length === 0) return\n const current = items.indexOf(document.activeElement as HTMLButtonElement)\n const step = event.key === 'ArrowDown' ? 1 : -1\n const next = current < 0 ? 0 : (current + step + items.length) % items.length\n items[next]?.focus()\n },\n [closeMoveMenu],\n )\n\n const handleMoveSelect = React.useCallback(\n (targetStatusId: string) => {\n setMoveMenuOpen(false)\n moveTriggerRef.current?.focus()\n onMoveToColumn?.(task.id, targetStatusId)\n },\n [onMoveToColumn, task.id],\n )\n\n const quickActionsVisible = coarsePointer\n ? 'opacity-100'\n : 'opacity-0 transition-opacity group-hover:opacity-100 group-focus-within:opacity-100'\n\n const cardInjectionContext = React.useMemo(\n () => ({\n entityId: TASK_ENTITY_ID,\n recordId: task.id,\n taskId: task.id,\n timeProjectId: task.timeProjectId ?? null,\n taskStatusId: task.taskStatusId ?? null,\n timerRunning,\n }),\n [task.id, task.taskStatusId, task.timeProjectId, timerRunning],\n )\n\n const subtaskPercent = subtasks && subtasks.total > 0\n ? Math.round((subtasks.done / subtasks.total) * 100)\n : 0\n\n return (\n <div\n ref={setNodeRef}\n {...attributes}\n {...listeners}\n data-task-card={task.id}\n aria-label={t('staff.time_tracking.board.card.aria', 'Task: {title}', { title: task.title })}\n onClick={handleCardClick}\n onKeyDown={handleKeyDown}\n className={`group relative flex w-full flex-col gap-2 rounded-lg border border-border bg-card px-4 py-3 shadow-xs transition-shadow ${\n dimmed ? 'cursor-grabbing opacity-30' : 'cursor-grab hover:shadow-sm active:cursor-grabbing'\n } ${pending ? 'opacity-70' : ''}`}\n >\n <div className=\"text-sm font-semibold leading-normal text-foreground\">{task.title}</div>\n\n {tags.length > 0 ? (\n <div className=\"flex flex-wrap gap-1\">\n {tags.map((tag) => (\n <Badge key={tag.id} variant=\"info\" size=\"sm\">\n {tag.label}\n </Badge>\n ))}\n </div>\n ) : null}\n\n <InjectionSpot\n spotId={extensionPoints.hosts.taskBoardCardBadges.spotId}\n context={cardInjectionContext}\n data={task}\n />\n\n {subtasks && subtasks.total > 0 ? (\n <div className=\"flex flex-col gap-1\">\n <span className=\"flex items-center gap-1 text-xs font-medium leading-normal text-muted-foreground\">\n <Check className=\"size-3\" aria-hidden=\"true\" />\n {t('staff.time_tracking.board.card.subtasks', '{done}/{total} subtasks', {\n done: subtasks.done,\n total: subtasks.total,\n })}\n </span>\n <Progress value={subtaskPercent} size=\"sm\" tone=\"success\" />\n </div>\n ) : null}\n\n <div className=\"h-px w-full bg-border\" aria-hidden=\"true\" />\n\n <div className=\"flex items-center gap-2\">\n <Avatar\n size=\"xs\"\n label={initialsFromName(assigneeName)}\n ariaLabel={\n assigneeName\n ? t('staff.time_tracking.board.card.assignee', 'Assigned to {name}', { name: assigneeName })\n : t('staff.time_tracking.board.card.unassigned', 'Unassigned')\n }\n />\n {timerRunning ? (\n <Badge variant=\"success\" size=\"sm\" dot>\n {t('staff.time_tracking.board.card.timerRunning', 'timer')}\n </Badge>\n ) : null}\n <span className=\"grow\" />\n <span className=\"text-xs font-semibold tabular-nums leading-normal text-foreground\">\n {formatBoardMinutes(task.loggedMinutes)}\n </span>\n </div>\n\n <div\n data-card-action=\"true\"\n data-testid={`kanban-card-actions-${task.id}`}\n onPointerDown={stopPointerDown}\n className={`flex flex-wrap items-center gap-1.5 ${moveMenuOpen ? 'opacity-100' : quickActionsVisible}`}\n >\n {timerRunning ? (\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"2xs\"\n aria-label={t('staff.time_tracking.board.card.stopTimerAria', 'Stop the timer for {title}', {\n title: task.title,\n })}\n onClick={() => onStopTimer(task.id)}\n >\n <Square className=\"size-3\" aria-hidden=\"true\" />\n {t('staff.time_tracking.board.card.stopTimer', 'Stop')}\n </Button>\n ) : (\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"2xs\"\n aria-label={t('staff.time_tracking.board.card.startTimerAria', 'Start a timer for {title}', {\n title: task.title,\n })}\n onClick={() => onStartTimer(task.id)}\n >\n <Play className=\"size-3\" aria-hidden=\"true\" />\n {t('staff.time_tracking.board.card.startTimer', 'Start')}\n </Button>\n )}\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"2xs\"\n aria-label={t('staff.time_tracking.board.card.addTimeAria', 'Add time to {title}', {\n title: task.title,\n })}\n onClick={() => onAddTime(task.id)}\n >\n <Plus className=\"size-3\" aria-hidden=\"true\" />\n {t('staff.time_tracking.board.card.addTime', 'Add time')}\n </Button>\n {showMoveMenu ? (\n <div className=\"relative\">\n <Button\n ref={moveTriggerRef}\n type=\"button\"\n variant=\"outline\"\n size=\"2xs\"\n aria-haspopup=\"menu\"\n aria-expanded={moveMenuOpen}\n aria-label={t('staff.time_tracking.board.card.moveTo.aria', 'Move {title} to another column', {\n title: task.title,\n })}\n data-testid={`kanban-card-move-${task.id}`}\n onClick={() => setMoveMenuOpen((open) => !open)}\n onKeyDown={(event) => {\n if (event.key !== 'ArrowDown') return\n event.preventDefault()\n setMoveMenuOpen(true)\n }}\n >\n <ArrowRightLeft className=\"size-3\" aria-hidden=\"true\" />\n {t('staff.time_tracking.board.card.moveTo.cta', 'Move')}\n </Button>\n {moveMenuOpen ? (\n <div\n ref={moveMenuRef}\n role=\"menu\"\n aria-label={t('staff.time_tracking.board.card.moveTo.menu', 'Move {title} to', {\n title: task.title,\n })}\n data-testid={`kanban-card-move-menu-${task.id}`}\n onKeyDown={handleMoveMenuKeyDown}\n className=\"absolute bottom-full left-0 z-dropdown mb-1 flex min-w-40 flex-col gap-0.5 rounded-md border border-border bg-popover p-1 text-popover-foreground shadow-md\"\n >\n {moveTargets.map((target, index) => (\n <Button\n key={target.id}\n ref={(node: HTMLButtonElement | null) => {\n moveItemRefs.current[index] = node\n }}\n type=\"button\"\n variant=\"ghost\"\n size=\"2xs\"\n role=\"menuitem\"\n className=\"justify-start\"\n data-testid={`kanban-card-move-option-${task.id}-${target.id}`}\n onClick={() => handleMoveSelect(target.id)}\n >\n {target.name}\n </Button>\n ))}\n </div>\n ) : null}\n </div>\n ) : null}\n </div>\n\n <InjectionSpot\n spotId={extensionPoints.hosts.taskBoardCardFooter.spotId}\n context={cardInjectionContext}\n data={task}\n />\n </div>\n )\n}\n\nconst DefaultKanbanCard = React.memo(KanbanCardImpl)\n\nconst kanbanTagOptionSchema = z.object({ id: z.string(), label: z.string() })\n\nconst kanbanMoveTargetSchema = z.object({ id: z.string(), name: z.string() })\n\nconst kanbanCardPropsSchema: z.ZodType<KanbanCardProps> = z.object({\n task: opaqueProp<BoardTask>(),\n assigneeName: z.string().nullable(),\n tags: z.array(kanbanTagOptionSchema),\n subtasks: opaqueProp<SubtaskProgress>().nullable(),\n timerRunning: z.boolean(),\n pending: z.boolean(),\n isActiveDrag: z.boolean(),\n moveTargets: z.array(kanbanMoveTargetSchema).optional(),\n onOpen: callbackProp<(taskId: string) => void>(),\n onStartTimer: callbackProp<(taskId: string) => void>(),\n onStopTimer: callbackProp<(taskId: string) => void>(),\n onAddTime: callbackProp<(taskId: string) => void>(),\n onMoveToColumn: optionalCallbackProp<(taskId: string, targetStatusId: string) => void>(),\n})\n\nregisterComponent<KanbanCardProps>({\n id: extensionPoints.hosts.kanbanCardComponent.componentId,\n component: DefaultKanbanCard,\n metadata: {\n module: 'staff',\n description: 'One task card on the time-tracking Kanban board.',\n propsSchema: kanbanCardPropsSchema,\n },\n})\n\nfunction KanbanCardHost(props: KanbanCardProps): React.ReactElement {\n const Resolved = useRegisteredComponent<KanbanCardProps>(\n extensionPoints.hosts.kanbanCardComponent.componentId,\n DefaultKanbanCard,\n )\n return <Resolved {...props} />\n}\n\nexport const KanbanCard = React.memo(KanbanCardHost)\n\nexport default KanbanCard\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|