@open-mercato/core 0.10.1-develop.7717.1.2befe9c634 → 0.10.1-develop.7721.1.b5c4a00a68
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_support_routing_rule/index.js +21 -0
- package/dist/generated/entities/staff_support_routing_rule/index.js.map +7 -0
- package/dist/generated/entities/staff_support_ticket/index.js +37 -0
- package/dist/generated/entities/staff_support_ticket/index.js.map +7 -0
- package/dist/generated/entities/staff_time_project/index.js +2 -0
- package/dist/generated/entities/staff_time_project/index.js.map +2 -2
- package/dist/generated/entities/staff_time_project_member/index.js +2 -0
- package/dist/generated/entities/staff_time_project_member/index.js.map +2 -2
- package/dist/generated/entities/staff_time_task/index.js +4 -0
- package/dist/generated/entities/staff_time_task/index.js.map +2 -2
- package/dist/generated/entities/staff_time_task_comment/index.js +9 -1
- package/dist/generated/entities/staff_time_task_comment/index.js.map +2 -2
- package/dist/generated/entities.ids.generated.js +2 -0
- package/dist/generated/entities.ids.generated.js.map +2 -2
- package/dist/generated/entity-fields-registry.js +38 -0
- package/dist/generated/entity-fields-registry.js.map +2 -2
- package/dist/helpers/integration/auth.js +1 -0
- package/dist/helpers/integration/auth.js.map +2 -2
- package/dist/helpers/integration/communicationChannelsFixtures.js +20 -0
- package/dist/helpers/integration/communicationChannelsFixtures.js.map +2 -2
- package/dist/modules/catalog/api/bulk-delete/route.js +12 -2
- package/dist/modules/catalog/api/bulk-delete/route.js.map +2 -2
- package/dist/modules/communication_channels/api/post/test-seed/route.js +17 -3
- package/dist/modules/communication_channels/api/post/test-seed/route.js.map +2 -2
- package/dist/modules/communication_channels/lib/test-seed.js +38 -5
- package/dist/modules/communication_channels/lib/test-seed.js.map +2 -2
- package/dist/modules/messages/commands/messages.js +2 -3
- package/dist/modules/messages/commands/messages.js.map +2 -2
- package/dist/modules/portal/frontend/[orgSlug]/portal/dashboard/page.js +2 -2
- package/dist/modules/portal/frontend/[orgSlug]/portal/dashboard/page.js.map +2 -2
- package/dist/modules/staff/api/portal/support-tickets/[id]/attachments/route.js +299 -0
- package/dist/modules/staff/api/portal/support-tickets/[id]/attachments/route.js.map +7 -0
- package/dist/modules/staff/api/portal/support-tickets/[id]/messages/route.js +91 -0
- package/dist/modules/staff/api/portal/support-tickets/[id]/messages/route.js.map +7 -0
- package/dist/modules/staff/api/portal/support-tickets/[id]/route.js +146 -0
- package/dist/modules/staff/api/portal/support-tickets/[id]/route.js.map +7 -0
- package/dist/modules/staff/api/portal/support-tickets/options/route.js +60 -0
- package/dist/modules/staff/api/portal/support-tickets/options/route.js.map +7 -0
- package/dist/modules/staff/api/portal/support-tickets/route.js +220 -0
- package/dist/modules/staff/api/portal/support-tickets/route.js.map +7 -0
- package/dist/modules/staff/api/timesheets/settings/route.js +7 -1
- package/dist/modules/staff/api/timesheets/settings/route.js.map +2 -2
- package/dist/modules/staff/api/timesheets/support-routing-rules/fallback-project/route.js +122 -0
- package/dist/modules/staff/api/timesheets/support-routing-rules/fallback-project/route.js.map +7 -0
- package/dist/modules/staff/api/timesheets/support-routing-rules/preview/route.js +180 -0
- package/dist/modules/staff/api/timesheets/support-routing-rules/preview/route.js.map +7 -0
- package/dist/modules/staff/api/timesheets/support-routing-rules/route.js +147 -0
- package/dist/modules/staff/api/timesheets/support-routing-rules/route.js.map +7 -0
- package/dist/modules/staff/api/timesheets/support-tickets/options/route.js +133 -0
- package/dist/modules/staff/api/timesheets/support-tickets/options/route.js.map +7 -0
- package/dist/modules/staff/api/timesheets/tasks/[id]/claim/route.js +33 -0
- package/dist/modules/staff/api/timesheets/tasks/[id]/claim/route.js.map +7 -0
- package/dist/modules/staff/api/timesheets/tasks/[id]/comments/route.js +25 -7
- package/dist/modules/staff/api/timesheets/tasks/[id]/comments/route.js.map +2 -2
- package/dist/modules/staff/api/timesheets/tasks/[id]/release/route.js +32 -0
- package/dist/modules/staff/api/timesheets/tasks/[id]/release/route.js.map +7 -0
- package/dist/modules/staff/api/timesheets/tasks/route.js +94 -47
- package/dist/modules/staff/api/timesheets/tasks/route.js.map +2 -2
- package/dist/modules/staff/api/timesheets/time-projects/[id]/employees/route.js +3 -0
- 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 +3 -0
- package/dist/modules/staff/api/timesheets/time-projects/route.js.map +2 -2
- package/dist/modules/staff/backend/staff/time-tracking/projects/[id]/edit/page.js +1 -0
- package/dist/modules/staff/backend/staff/time-tracking/projects/[id]/edit/page.js.map +2 -2
- package/dist/modules/staff/backend/staff/time-tracking/projects/[id]/page.js +54 -4
- package/dist/modules/staff/backend/staff/time-tracking/projects/[id]/page.js.map +2 -2
- package/dist/modules/staff/backend/staff/time-tracking/projects/projectFormConfig.js +21 -5
- package/dist/modules/staff/backend/staff/time-tracking/projects/projectFormConfig.js.map +2 -2
- package/dist/modules/staff/backend/staff/time-tracking/settings/page.js +319 -254
- package/dist/modules/staff/backend/staff/time-tracking/settings/page.js.map +2 -2
- package/dist/modules/staff/backend/staff/time-tracking/support/page.js +363 -0
- package/dist/modules/staff/backend/staff/time-tracking/support/page.js.map +7 -0
- package/dist/modules/staff/backend/staff/time-tracking/support/page.meta.js +18 -0
- package/dist/modules/staff/backend/staff/time-tracking/support/page.meta.js.map +7 -0
- package/dist/modules/staff/cli.js +27 -0
- package/dist/modules/staff/cli.js.map +2 -2
- package/dist/modules/staff/commands/index.js +3 -0
- package/dist/modules/staff/commands/index.js.map +2 -2
- package/dist/modules/staff/commands/shared.js +10 -1
- package/dist/modules/staff/commands/shared.js.map +2 -2
- package/dist/modules/staff/commands/support-routing-rules.js +505 -0
- package/dist/modules/staff/commands/support-routing-rules.js.map +7 -0
- package/dist/modules/staff/commands/support-tickets.js +513 -0
- package/dist/modules/staff/commands/support-tickets.js.map +7 -0
- package/dist/modules/staff/commands/timesheets-projects.js +72 -14
- package/dist/modules/staff/commands/timesheets-projects.js.map +2 -2
- package/dist/modules/staff/commands/timesheets-task-assignment.js +270 -0
- package/dist/modules/staff/commands/timesheets-task-assignment.js.map +7 -0
- package/dist/modules/staff/commands/timesheets-task-comments.js +58 -12
- package/dist/modules/staff/commands/timesheets-task-comments.js.map +2 -2
- package/dist/modules/staff/commands/timesheets-tasks.js +91 -9
- package/dist/modules/staff/commands/timesheets-tasks.js.map +3 -3
- package/dist/modules/staff/data/enrichers.js +141 -0
- package/dist/modules/staff/data/enrichers.js.map +2 -2
- package/dist/modules/staff/data/entities.js +143 -2
- package/dist/modules/staff/data/entities.js.map +2 -2
- package/dist/modules/staff/data/extensions.js +8 -0
- package/dist/modules/staff/data/extensions.js.map +2 -2
- package/dist/modules/staff/data/validators.js +34 -5
- package/dist/modules/staff/data/validators.js.map +2 -2
- package/dist/modules/staff/encryption.js +6 -0
- package/dist/modules/staff/encryption.js.map +2 -2
- package/dist/modules/staff/events.js +25 -0
- package/dist/modules/staff/events.js.map +2 -2
- package/dist/modules/staff/events.payloads.js +54 -0
- package/dist/modules/staff/events.payloads.js.map +2 -2
- package/dist/modules/staff/extension-points.js +1 -0
- package/dist/modules/staff/extension-points.js.map +2 -2
- package/dist/modules/staff/frontend/[orgSlug]/portal/support/[id]/page.js +468 -0
- package/dist/modules/staff/frontend/[orgSlug]/portal/support/[id]/page.js.map +7 -0
- package/dist/modules/staff/frontend/[orgSlug]/portal/support/[id]/page.meta.js +12 -0
- package/dist/modules/staff/frontend/[orgSlug]/portal/support/[id]/page.meta.js.map +7 -0
- package/dist/modules/staff/frontend/[orgSlug]/portal/support/new/page.js +316 -0
- package/dist/modules/staff/frontend/[orgSlug]/portal/support/new/page.js.map +7 -0
- package/dist/modules/staff/frontend/[orgSlug]/portal/support/new/page.meta.js +12 -0
- package/dist/modules/staff/frontend/[orgSlug]/portal/support/new/page.meta.js.map +7 -0
- package/dist/modules/staff/frontend/[orgSlug]/portal/support/page.js +190 -0
- package/dist/modules/staff/frontend/[orgSlug]/portal/support/page.js.map +7 -0
- package/dist/modules/staff/frontend/[orgSlug]/portal/support/page.meta.js +19 -0
- package/dist/modules/staff/frontend/[orgSlug]/portal/support/page.meta.js.map +7 -0
- package/dist/modules/staff/index.js +1 -1
- package/dist/modules/staff/index.js.map +2 -2
- package/dist/modules/staff/lib/crud.js +2 -0
- package/dist/modules/staff/lib/crud.js.map +2 -2
- package/dist/modules/staff/lib/support/attachments.js +36 -0
- package/dist/modules/staff/lib/support/attachments.js.map +7 -0
- package/dist/modules/staff/lib/support/dictionaries.js +87 -0
- package/dist/modules/staff/lib/support/dictionaries.js.map +7 -0
- package/dist/modules/staff/lib/support/notifications.js +111 -0
- package/dist/modules/staff/lib/support/notifications.js.map +7 -0
- package/dist/modules/staff/lib/support/portalAttachments.js +100 -0
- package/dist/modules/staff/lib/support/portalAttachments.js.map +7 -0
- package/dist/modules/staff/lib/support/portalBroadcast.js +117 -0
- package/dist/modules/staff/lib/support/portalBroadcast.js.map +7 -0
- package/dist/modules/staff/lib/support/portalRoute.js +99 -0
- package/dist/modules/staff/lib/support/portalRoute.js.map +7 -0
- package/dist/modules/staff/lib/support/portalStatus.js +12 -0
- package/dist/modules/staff/lib/support/portalStatus.js.map +7 -0
- package/dist/modules/staff/lib/support/portalTickets.js +148 -0
- package/dist/modules/staff/lib/support/portalTickets.js.map +7 -0
- package/dist/modules/staff/lib/support/routing.js +81 -0
- package/dist/modules/staff/lib/support/routing.js.map +7 -0
- package/dist/modules/staff/lib/support/routingRuleDraft.js +25 -0
- package/dist/modules/staff/lib/support/routingRuleDraft.js.map +7 -0
- package/dist/modules/staff/lib/support/seedDefaults.js +114 -0
- package/dist/modules/staff/lib/support/seedDefaults.js.map +7 -0
- package/dist/modules/staff/lib/support/supportActivity.js +26 -0
- package/dist/modules/staff/lib/support/supportActivity.js.map +7 -0
- package/dist/modules/staff/lib/support-ui/PortalSupportNotLinked.js +23 -0
- package/dist/modules/staff/lib/support-ui/PortalSupportNotLinked.js.map +7 -0
- package/dist/modules/staff/lib/support-ui/portalAttachmentValidation.js +112 -0
- package/dist/modules/staff/lib/support-ui/portalAttachmentValidation.js.map +7 -0
- package/dist/modules/staff/lib/support-ui/portalPendingUploads.js +45 -0
- package/dist/modules/staff/lib/support-ui/portalPendingUploads.js.map +7 -0
- package/dist/modules/staff/lib/support-ui/portalSupport.js +51 -0
- package/dist/modules/staff/lib/support-ui/portalSupport.js.map +7 -0
- package/dist/modules/staff/lib/time-tracking/access.js +3 -39
- package/dist/modules/staff/lib/time-tracking/access.js.map +2 -2
- package/dist/modules/staff/lib/time-tracking/listProjectAccess.js +54 -0
- package/dist/modules/staff/lib/time-tracking/listProjectAccess.js.map +7 -0
- package/dist/modules/staff/lib/time-tracking/portalRecipients.js +92 -2
- package/dist/modules/staff/lib/time-tracking/portalRecipients.js.map +2 -2
- package/dist/modules/staff/lib/time-tracking/projectAssignment.js +112 -0
- package/dist/modules/staff/lib/time-tracking/projectAssignment.js.map +7 -0
- package/dist/modules/staff/lib/time-tracking/settingKeys.js +14 -0
- package/dist/modules/staff/lib/time-tracking/settingKeys.js.map +2 -2
- package/dist/modules/staff/lib/time-tracking/settings.js +28 -1
- package/dist/modules/staff/lib/time-tracking/settings.js.map +2 -2
- package/dist/modules/staff/lib/time-tracking/taskAssignmentRoute.js +143 -0
- package/dist/modules/staff/lib/time-tracking/taskAssignmentRoute.js.map +7 -0
- package/dist/modules/staff/lib/time-tracking/workRecipients.js +92 -0
- package/dist/modules/staff/lib/time-tracking/workRecipients.js.map +7 -0
- package/dist/modules/staff/lib/time-tracking-ui/BoardFilterChips.js +32 -3
- package/dist/modules/staff/lib/time-tracking-ui/BoardFilterChips.js.map +2 -2
- package/dist/modules/staff/lib/time-tracking-ui/KanbanBoard.js +29 -0
- package/dist/modules/staff/lib/time-tracking-ui/KanbanBoard.js.map +2 -2
- package/dist/modules/staff/lib/time-tracking-ui/KanbanCard.js +4 -0
- package/dist/modules/staff/lib/time-tracking-ui/KanbanCard.js.map +2 -2
- package/dist/modules/staff/lib/time-tracking-ui/ProjectFormSections.js +141 -1
- package/dist/modules/staff/lib/time-tracking-ui/ProjectFormSections.js.map +2 -2
- package/dist/modules/staff/lib/time-tracking-ui/SupportAttachmentsSection.js +153 -0
- package/dist/modules/staff/lib/time-tracking-ui/SupportAttachmentsSection.js.map +7 -0
- package/dist/modules/staff/lib/time-tracking-ui/SupportRequestPanel.js +67 -0
- package/dist/modules/staff/lib/time-tracking-ui/SupportRequestPanel.js.map +7 -0
- package/dist/modules/staff/lib/time-tracking-ui/TaskBoardScreen.js +3 -1
- package/dist/modules/staff/lib/time-tracking-ui/TaskBoardScreen.js.map +2 -2
- package/dist/modules/staff/lib/time-tracking-ui/TaskCommentThread.js +80 -17
- package/dist/modules/staff/lib/time-tracking-ui/TaskCommentThread.js.map +2 -2
- package/dist/modules/staff/lib/time-tracking-ui/TaskDrawer.js +230 -41
- package/dist/modules/staff/lib/time-tracking-ui/TaskDrawer.js.map +2 -2
- package/dist/modules/staff/lib/time-tracking-ui/boardDirectory.js +21 -1
- package/dist/modules/staff/lib/time-tracking-ui/boardDirectory.js.map +2 -2
- package/dist/modules/staff/lib/time-tracking-ui/boardFilters.js +16 -4
- package/dist/modules/staff/lib/time-tracking-ui/boardFilters.js.map +2 -2
- package/dist/modules/staff/lib/time-tracking-ui/kanbanBoardData.js +3 -1
- package/dist/modules/staff/lib/time-tracking-ui/kanbanBoardData.js.map +2 -2
- package/dist/modules/staff/lib/time-tracking-ui/projectDefaultAssignee.js +68 -0
- package/dist/modules/staff/lib/time-tracking-ui/projectDefaultAssignee.js.map +7 -0
- package/dist/modules/staff/lib/time-tracking-ui/settingsTabs.js +7 -0
- package/dist/modules/staff/lib/time-tracking-ui/settingsTabs.js.map +7 -0
- package/dist/modules/staff/lib/time-tracking-ui/supportTicketData.js +50 -0
- package/dist/modules/staff/lib/time-tracking-ui/supportTicketData.js.map +7 -0
- package/dist/modules/staff/lib/time-tracking-ui/taskDrawerData.js +13 -1
- package/dist/modules/staff/lib/time-tracking-ui/taskDrawerData.js.map +2 -2
- package/dist/modules/staff/lib/time-tracking-ui/timeTrackingSettingsForm.js +36 -2
- package/dist/modules/staff/lib/time-tracking-ui/timeTrackingSettingsForm.js.map +2 -2
- package/dist/modules/staff/migrations/Migration20261009180543_staff.js +42 -0
- package/dist/modules/staff/migrations/Migration20261009180543_staff.js.map +7 -0
- package/dist/modules/staff/notifications.js +92 -0
- package/dist/modules/staff/notifications.js.map +2 -2
- package/dist/modules/staff/setup.js +6 -2
- package/dist/modules/staff/setup.js.map +2 -2
- package/dist/modules/staff/subscribers/support-portal-comment-created.js +26 -0
- package/dist/modules/staff/subscribers/support-portal-comment-created.js.map +7 -0
- package/dist/modules/staff/subscribers/support-portal-comment-deleted.js +26 -0
- package/dist/modules/staff/subscribers/support-portal-comment-deleted.js.map +7 -0
- package/dist/modules/staff/subscribers/support-portal-comment-updated.js +26 -0
- package/dist/modules/staff/subscribers/support-portal-comment-updated.js.map +7 -0
- package/dist/modules/staff/subscribers/support-portal-status-column-updated.js +24 -0
- package/dist/modules/staff/subscribers/support-portal-status-column-updated.js.map +7 -0
- package/dist/modules/staff/subscribers/support-portal-task-status-changed.js +25 -0
- package/dist/modules/staff/subscribers/support-portal-task-status-changed.js.map +7 -0
- package/dist/modules/staff/subscribers/support-portal-task-updated.js +25 -0
- package/dist/modules/staff/subscribers/support-portal-task-updated.js.map +7 -0
- package/dist/modules/staff/subscribers/support-ticket-created-notification.js +25 -0
- package/dist/modules/staff/subscribers/support-ticket-created-notification.js.map +7 -0
- package/dist/modules/staff/subscribers/support-ticket-customer-replied-notification.js +25 -0
- package/dist/modules/staff/subscribers/support-ticket-customer-replied-notification.js.map +7 -0
- package/dist/modules/staff/subscribers/support-ticket-unnotified-clear.js +26 -0
- package/dist/modules/staff/subscribers/support-ticket-unnotified-clear.js.map +7 -0
- package/dist/modules/staff/subscribers/time-task-assignee-notification.js +83 -0
- package/dist/modules/staff/subscribers/time-task-assignee-notification.js.map +7 -0
- package/dist/modules/staff/widgets/injection/portal-support-tickets/widget.client.js +112 -0
- package/dist/modules/staff/widgets/injection/portal-support-tickets/widget.client.js.map +7 -0
- package/dist/modules/staff/widgets/injection/portal-support-tickets/widget.js +17 -0
- package/dist/modules/staff/widgets/injection/portal-support-tickets/widget.js.map +7 -0
- package/dist/modules/staff/widgets/injection/time-tracking-settings-support/widget.client.js +870 -0
- package/dist/modules/staff/widgets/injection/time-tracking-settings-support/widget.client.js.map +7 -0
- package/dist/modules/staff/widgets/injection/time-tracking-settings-support/widget.js +17 -0
- package/dist/modules/staff/widgets/injection/time-tracking-settings-support/widget.js.map +7 -0
- package/dist/modules/staff/widgets/injection-table.js +16 -1
- package/dist/modules/staff/widgets/injection-table.js.map +2 -2
- package/dist/modules/wms/components/backend/WmsLocationDetailPage.js +4 -18
- package/dist/modules/wms/components/backend/WmsLocationDetailPage.js.map +2 -2
- package/dist/modules/wms/components/backend/WmsLotDetailPage.js +4 -18
- package/dist/modules/wms/components/backend/WmsLotDetailPage.js.map +2 -2
- package/dist/modules/wms/components/backend/WmsSkuDetailPage.js +4 -18
- package/dist/modules/wms/components/backend/WmsSkuDetailPage.js.map +2 -2
- package/dist/modules/wms/lib/inventoryCsvExport.js +19 -0
- package/dist/modules/wms/lib/inventoryCsvExport.js.map +7 -0
- package/generated/entities/staff_support_routing_rule/index.ts +9 -0
- package/generated/entities/staff_support_ticket/index.ts +17 -0
- package/generated/entities/staff_time_project/index.ts +1 -0
- package/generated/entities/staff_time_project_member/index.ts +1 -0
- package/generated/entities/staff_time_task/index.ts +2 -0
- package/generated/entities/staff_time_task_comment/index.ts +4 -0
- package/generated/entities.ids.generated.ts +2 -0
- package/generated/entity-fields-registry.ts +38 -0
- package/package.json +8 -8
- package/src/helpers/integration/auth.ts +1 -1
- package/src/helpers/integration/communicationChannelsFixtures.ts +60 -2
- package/src/modules/catalog/api/bulk-delete/route.ts +12 -2
- package/src/modules/communication_channels/api/post/test-seed/route.ts +29 -12
- package/src/modules/communication_channels/lib/test-seed.ts +49 -10
- package/src/modules/messages/commands/messages.ts +8 -10
- package/src/modules/portal/frontend/[orgSlug]/portal/dashboard/page.tsx +2 -2
- package/src/modules/staff/AGENTS.md +22 -6
- package/src/modules/staff/api/portal/support-tickets/[id]/attachments/route.ts +327 -0
- package/src/modules/staff/api/portal/support-tickets/[id]/messages/route.ts +94 -0
- package/src/modules/staff/api/portal/support-tickets/[id]/route.ts +160 -0
- package/src/modules/staff/api/portal/support-tickets/options/route.ts +60 -0
- package/src/modules/staff/api/portal/support-tickets/route.ts +253 -0
- package/src/modules/staff/api/timesheets/settings/route.ts +7 -1
- package/src/modules/staff/api/timesheets/support-routing-rules/fallback-project/route.ts +131 -0
- package/src/modules/staff/api/timesheets/support-routing-rules/preview/route.ts +248 -0
- package/src/modules/staff/api/timesheets/support-routing-rules/route.ts +150 -0
- package/src/modules/staff/api/timesheets/support-tickets/options/route.ts +181 -0
- package/src/modules/staff/api/timesheets/tasks/[id]/claim/route.ts +31 -0
- package/src/modules/staff/api/timesheets/tasks/[id]/comments/route.ts +25 -7
- package/src/modules/staff/api/timesheets/tasks/[id]/release/route.ts +30 -0
- package/src/modules/staff/api/timesheets/tasks/route.ts +119 -67
- package/src/modules/staff/api/timesheets/time-projects/[id]/employees/route.ts +3 -0
- package/src/modules/staff/api/timesheets/time-projects/route.ts +3 -0
- package/src/modules/staff/backend/staff/time-tracking/projects/[id]/edit/page.tsx +1 -0
- package/src/modules/staff/backend/staff/time-tracking/projects/[id]/page.tsx +67 -2
- package/src/modules/staff/backend/staff/time-tracking/projects/projectFormConfig.ts +22 -3
- package/src/modules/staff/backend/staff/time-tracking/settings/page.tsx +405 -308
- package/src/modules/staff/backend/staff/time-tracking/support/page.meta.ts +14 -0
- package/src/modules/staff/backend/staff/time-tracking/support/page.tsx +428 -0
- package/src/modules/staff/cli.ts +28 -0
- package/src/modules/staff/commands/index.ts +3 -0
- package/src/modules/staff/commands/shared.ts +22 -1
- package/src/modules/staff/commands/support-routing-rules.ts +595 -0
- package/src/modules/staff/commands/support-tickets.ts +580 -0
- package/src/modules/staff/commands/timesheets-projects.ts +84 -13
- package/src/modules/staff/commands/timesheets-task-assignment.ts +319 -0
- package/src/modules/staff/commands/timesheets-task-comments.ts +70 -15
- package/src/modules/staff/commands/timesheets-tasks.ts +106 -15
- package/src/modules/staff/data/enrichers.ts +203 -0
- package/src/modules/staff/data/entities.ts +133 -2
- package/src/modules/staff/data/extensions.ts +9 -1
- package/src/modules/staff/data/validators.ts +36 -0
- package/src/modules/staff/encryption.ts +6 -0
- package/src/modules/staff/events.payloads.ts +87 -1
- package/src/modules/staff/events.ts +26 -0
- package/src/modules/staff/extension-points.ts +1 -0
- package/src/modules/staff/frontend/[orgSlug]/portal/support/[id]/page.meta.ts +10 -0
- package/src/modules/staff/frontend/[orgSlug]/portal/support/[id]/page.tsx +553 -0
- package/src/modules/staff/frontend/[orgSlug]/portal/support/new/page.meta.ts +10 -0
- package/src/modules/staff/frontend/[orgSlug]/portal/support/new/page.tsx +346 -0
- package/src/modules/staff/frontend/[orgSlug]/portal/support/page.meta.ts +17 -0
- package/src/modules/staff/frontend/[orgSlug]/portal/support/page.tsx +253 -0
- package/src/modules/staff/i18n/de.json +291 -0
- package/src/modules/staff/i18n/en.json +291 -0
- package/src/modules/staff/i18n/es.json +291 -0
- package/src/modules/staff/i18n/ko.json +291 -0
- package/src/modules/staff/i18n/pl.json +291 -0
- package/src/modules/staff/index.ts +1 -1
- package/src/modules/staff/lib/crud.ts +2 -1
- package/src/modules/staff/lib/support/attachments.ts +43 -0
- package/src/modules/staff/lib/support/dictionaries.ts +120 -0
- package/src/modules/staff/lib/support/notifications.ts +138 -0
- package/src/modules/staff/lib/support/portalAttachments.ts +140 -0
- package/src/modules/staff/lib/support/portalBroadcast.ts +161 -0
- package/src/modules/staff/lib/support/portalRoute.ts +108 -0
- package/src/modules/staff/lib/support/portalStatus.ts +15 -0
- package/src/modules/staff/lib/support/portalTickets.ts +233 -0
- package/src/modules/staff/lib/support/routing.ts +117 -0
- package/src/modules/staff/lib/support/routingRuleDraft.ts +45 -0
- package/src/modules/staff/lib/support/seedDefaults.ts +151 -0
- package/src/modules/staff/lib/support/supportActivity.ts +39 -0
- package/src/modules/staff/lib/support-ui/PortalSupportNotLinked.tsx +20 -0
- package/src/modules/staff/lib/support-ui/portalAttachmentValidation.ts +125 -0
- package/src/modules/staff/lib/support-ui/portalPendingUploads.ts +49 -0
- package/src/modules/staff/lib/support-ui/portalSupport.ts +116 -0
- package/src/modules/staff/lib/time-tracking/access.ts +2 -62
- package/src/modules/staff/lib/time-tracking/listProjectAccess.ts +78 -0
- package/src/modules/staff/lib/time-tracking/portalRecipients.ts +173 -5
- package/src/modules/staff/lib/time-tracking/projectAssignment.ts +172 -0
- package/src/modules/staff/lib/time-tracking/settingKeys.ts +11 -0
- package/src/modules/staff/lib/time-tracking/settings.ts +46 -1
- package/src/modules/staff/lib/time-tracking/taskAssignmentRoute.ts +165 -0
- package/src/modules/staff/lib/time-tracking/workRecipients.ts +183 -0
- package/src/modules/staff/lib/time-tracking-ui/BoardFilterChips.tsx +36 -1
- package/src/modules/staff/lib/time-tracking-ui/KanbanBoard.tsx +30 -0
- package/src/modules/staff/lib/time-tracking-ui/KanbanCard.tsx +9 -0
- package/src/modules/staff/lib/time-tracking-ui/ProjectFormSections.tsx +185 -6
- package/src/modules/staff/lib/time-tracking-ui/SupportAttachmentsSection.tsx +188 -0
- package/src/modules/staff/lib/time-tracking-ui/SupportRequestPanel.tsx +102 -0
- package/src/modules/staff/lib/time-tracking-ui/TaskBoardScreen.tsx +2 -0
- package/src/modules/staff/lib/time-tracking-ui/TaskCommentThread.tsx +105 -22
- package/src/modules/staff/lib/time-tracking-ui/TaskDrawer.tsx +278 -43
- package/src/modules/staff/lib/time-tracking-ui/boardDirectory.ts +21 -0
- package/src/modules/staff/lib/time-tracking-ui/boardFilters.ts +16 -2
- package/src/modules/staff/lib/time-tracking-ui/kanbanBoardData.ts +4 -0
- package/src/modules/staff/lib/time-tracking-ui/projectDefaultAssignee.ts +117 -0
- package/src/modules/staff/lib/time-tracking-ui/settingsTabs.ts +17 -0
- package/src/modules/staff/lib/time-tracking-ui/supportTicketData.ts +71 -0
- package/src/modules/staff/lib/time-tracking-ui/taskDrawerData.ts +15 -0
- package/src/modules/staff/lib/time-tracking-ui/timeTrackingSettingsForm.ts +48 -1
- package/src/modules/staff/migrations/.snapshot-open-mercato.json +714 -0
- package/src/modules/staff/migrations/Migration20261009180543_staff.ts +50 -0
- package/src/modules/staff/notifications.ts +92 -0
- package/src/modules/staff/setup.ts +6 -2
- package/src/modules/staff/subscribers/support-portal-comment-created.ts +35 -0
- package/src/modules/staff/subscribers/support-portal-comment-deleted.ts +35 -0
- package/src/modules/staff/subscribers/support-portal-comment-updated.ts +35 -0
- package/src/modules/staff/subscribers/support-portal-status-column-updated.ts +36 -0
- package/src/modules/staff/subscribers/support-portal-task-status-changed.ts +34 -0
- package/src/modules/staff/subscribers/support-portal-task-updated.ts +34 -0
- package/src/modules/staff/subscribers/support-ticket-created-notification.ts +27 -0
- package/src/modules/staff/subscribers/support-ticket-customer-replied-notification.ts +27 -0
- package/src/modules/staff/subscribers/support-ticket-unnotified-clear.ts +29 -0
- package/src/modules/staff/subscribers/time-task-assignee-notification.ts +102 -0
- package/src/modules/staff/widgets/injection/portal-support-tickets/widget.client.tsx +151 -0
- package/src/modules/staff/widgets/injection/portal-support-tickets/widget.ts +16 -0
- package/src/modules/staff/widgets/injection/time-tracking-settings-support/widget.client.tsx +1058 -0
- package/src/modules/staff/widgets/injection/time-tracking-settings-support/widget.ts +17 -0
- package/src/modules/staff/widgets/injection-table.ts +15 -0
- package/src/modules/wms/components/backend/WmsLocationDetailPage.tsx +4 -20
- package/src/modules/wms/components/backend/WmsLotDetailPage.tsx +4 -20
- package/src/modules/wms/components/backend/WmsSkuDetailPage.tsx +4 -19
- package/src/modules/wms/lib/inventoryCsvExport.ts +18 -0
|
@@ -12,7 +12,8 @@ import {
|
|
|
12
12
|
DEFAULT_BUDGET_WARN_AT_PERCENT,
|
|
13
13
|
ProjectBudgetSection,
|
|
14
14
|
ProjectRoundingNotice,
|
|
15
|
-
ProjectTeamSection
|
|
15
|
+
ProjectTeamSection,
|
|
16
|
+
ProjectDefaultAssigneeField
|
|
16
17
|
} from "../../../../lib/time-tracking-ui/ProjectFormSections.js";
|
|
17
18
|
const CUSTOM_FIELD_KEY_PATTERN = /^cf[_:]/;
|
|
18
19
|
function pickCustomFieldValues(values) {
|
|
@@ -52,7 +53,8 @@ function createProjectFormSchema() {
|
|
|
52
53
|
).optional().nullable(),
|
|
53
54
|
startDate: z.string().optional().nullable(),
|
|
54
55
|
costCenter: z.string().max(100).optional().nullable(),
|
|
55
|
-
status: z.enum(["active", "on_hold", "completed"]).optional()
|
|
56
|
+
status: z.enum(["active", "on_hold", "completed"]).optional(),
|
|
57
|
+
defaultAssigneeStaffMemberId: z.string().optional().nullable()
|
|
56
58
|
});
|
|
57
59
|
}
|
|
58
60
|
function readText(values, key) {
|
|
@@ -274,9 +276,20 @@ function createProjectFormGroups(t, options = {}) {
|
|
|
274
276
|
id: "team",
|
|
275
277
|
column: 2,
|
|
276
278
|
title: t("staff.time_tracking.projects.form.groupTeam", "Team"),
|
|
277
|
-
component: (ctx) =>
|
|
278
|
-
projectId
|
|
279
|
-
|
|
279
|
+
component: (ctx) => {
|
|
280
|
+
const projectId = typeof ctx.values.id === "string" ? ctx.values.id : null;
|
|
281
|
+
const defaultAssignee = ctx.values.defaultAssigneeStaffMemberId;
|
|
282
|
+
return React.createElement(
|
|
283
|
+
React.Fragment,
|
|
284
|
+
null,
|
|
285
|
+
React.createElement(ProjectTeamSection, { projectId }),
|
|
286
|
+
projectId ? React.createElement(ProjectDefaultAssigneeField, {
|
|
287
|
+
projectId,
|
|
288
|
+
value: typeof defaultAssignee === "string" && defaultAssignee.length > 0 ? defaultAssignee : null,
|
|
289
|
+
onChange: (next) => ctx.setValue("defaultAssigneeStaffMemberId", next)
|
|
290
|
+
}) : null
|
|
291
|
+
);
|
|
292
|
+
}
|
|
280
293
|
},
|
|
281
294
|
{
|
|
282
295
|
id: "rounding",
|
|
@@ -336,6 +349,9 @@ function buildProjectPayload(values) {
|
|
|
336
349
|
payload.currencyCode = trimmedOrNull(values.currencyCode);
|
|
337
350
|
} else {
|
|
338
351
|
payload.id = values.id;
|
|
352
|
+
if (values.defaultAssigneeStaffMemberId !== void 0) {
|
|
353
|
+
payload.defaultAssigneeStaffMemberId = values.defaultAssigneeStaffMemberId || null;
|
|
354
|
+
}
|
|
339
355
|
}
|
|
340
356
|
if (values.status) payload.status = values.status;
|
|
341
357
|
Object.assign(payload, pickCustomFieldValues(values));
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../../../src/modules/staff/backend/staff/time-tracking/projects/projectFormConfig.ts"],
|
|
4
|
-
"sourcesContent": ["import * as React from 'react'\nimport { z } from 'zod'\nimport type { CrudField, CrudFormGroup } from '@open-mercato/ui/backend/CrudForm'\nimport type { TranslateFn } from '@open-mercato/shared/lib/i18n/context'\nimport { Input } from '@open-mercato/ui/primitives/input'\nimport { SwitchField } from '@open-mercato/ui/primitives/switch-field'\nimport { ColorPicker } from '../../../../lib/timesheets-ui/ColorPicker'\nimport { PROJECT_COLOR_KEYS } from '../../../../lib/timesheets-ui/colors'\nimport { PROJECT_CODE_MAX_LENGTH } from '../../../../lib/time-tracking/projectCode'\nimport { CustomerPickerBinding } from '../../../../lib/time-tracking-ui/CustomerPicker'\nimport { ProjectCodeFieldBinding } from '../../../../lib/time-tracking-ui/ProjectCodeField'\nimport { ProjectCurrencyFieldBinding } from '../../../../lib/time-tracking-ui/ProjectCurrencyField'\nimport {\n DEFAULT_BUDGET_WARN_AT_PERCENT,\n ProjectBudgetSection,\n ProjectRoundingNotice,\n ProjectTeamSection,\n type ProjectBudgetKind,\n} from '../../../../lib/time-tracking-ui/ProjectFormSections'\n\nexport type ProjectFormValues = {\n id?: string\n updatedAt?: string | null\n name: string\n code: string\n codeManual?: boolean\n customerId?: string | null\n customerName?: string | null\n customerKind?: string | null\n customerTaxId?: string | null\n description?: string | null\n hourlyRate?: string | null\n currencyCode?: string | null\n currencyLocked?: boolean\n entryCount?: number\n billableByDefault?: boolean\n budgetEnabled?: boolean\n budgetKind?: ProjectBudgetKind\n budgetValue?: string | null\n budgetWarnAtPercent?: string | null\n projectType?: string | null\n color?: string | null\n startDate?: string | null\n costCenter?: string | null\n status?: string\n /**\n * Custom-field values rendered by `CrudForm` from `entityIds`. They are keyed\n * `cf_<key>` / `cf:<key>` and are opaque here: this form neither declares nor\n * validates them, it only has to stop dropping them on the way to the command.\n */\n [customFieldKey: `cf_${string}`]: unknown\n [prefixedCustomFieldKey: `cf:${string}`]: unknown\n}\n\nconst CUSTOM_FIELD_KEY_PATTERN = /^cf[_:]/\n\nexport function pickCustomFieldValues(values: Record<string, unknown>): Record<string, unknown> {\n const picked: Record<string, unknown> = {}\n for (const [key, value] of Object.entries(values)) {\n if (CUSTOM_FIELD_KEY_PATTERN.test(key)) picked[key] = value\n }\n return picked\n}\n\nconst decimalPattern = /^\\d+([.,]\\d{1,4})?$/\n\nexport function createProjectFormSchema() {\n return z.object({\n id: z.string().optional(),\n updatedAt: z.string().optional().nullable(),\n name: z.string().min(1, 'staff.time_tracking.projects.validation.nameRequired'),\n code: z\n .string()\n .min(1, 'staff.time_tracking.projects.validation.codeRequired')\n .max(PROJECT_CODE_MAX_LENGTH)\n .regex(/^[A-Za-z0-9-]+$/, 'staff.time_tracking.projects.validation.codeFormat'),\n codeManual: z.boolean().optional(),\n // D-9 / US-B1: time is organised per customer, so a project cannot be saved without one.\n customerId: z.string().uuid('staff.time_tracking.projects.validation.customerRequired'),\n customerName: z.string().optional().nullable(),\n customerKind: z.string().optional().nullable(),\n customerTaxId: z.string().optional().nullable(),\n description: z.string().max(2000).optional().nullable(),\n hourlyRate: z\n .string()\n .regex(decimalPattern, 'staff.time_tracking.projects.validation.rateFormat')\n .optional()\n .nullable()\n .or(z.literal('')),\n currencyCode: z.string().min(3).max(10).optional().nullable().or(z.literal('')),\n currencyLocked: z.boolean().optional(),\n entryCount: z.number().optional(),\n billableByDefault: z.boolean().optional(),\n budgetEnabled: z.boolean().optional(),\n budgetKind: z.enum(['none', 'hours', 'amount']).optional(),\n budgetValue: z\n .string()\n .regex(decimalPattern, 'staff.time_tracking.projects.validation.budgetFormat')\n .optional()\n .nullable()\n .or(z.literal('')),\n budgetWarnAtPercent: z.string().optional().nullable(),\n projectType: z.string().max(100).optional().nullable(),\n color: z\n .string()\n .refine(\n (value) => (PROJECT_COLOR_KEYS as readonly string[]).includes(value),\n { message: 'staff.time_tracking.projects.validation.color' },\n )\n .optional()\n .nullable(),\n startDate: z.string().optional().nullable(),\n costCenter: z.string().max(100).optional().nullable(),\n status: z.enum(['active', 'on_hold', 'completed']).optional(),\n })\n}\n\nfunction readText(values: Record<string, unknown> | undefined, key: string): string {\n const value = values?.[key]\n return typeof value === 'string' ? value : ''\n}\n\nexport type ProjectFormFieldOptions = {\n /**\n * Called after the change-currency action succeeded. Hosts editing a persisted\n * project use it to reload the record, so the form picks up the currency the\n * action wrote AND the `updatedAt` it bumped \u2014 otherwise the next save would\n * collide with a version the same user had just superseded.\n */\n onCurrencyChanged?: (currencyCode: string) => void\n}\n\nexport function createProjectFormFields(\n t: TranslateFn,\n options: ProjectFormFieldOptions = {},\n): CrudField[] {\n return [\n {\n id: 'name',\n type: 'text',\n label: t('staff.time_tracking.projects.form.name', 'Project name'),\n placeholder: t('staff.time_tracking.projects.form.namePlaceholder', 'e.g. Nordvik \u2014 service portal'),\n required: true,\n },\n {\n id: 'code',\n type: 'custom',\n label: t('staff.time_tracking.projects.form.code', 'Project code'),\n rendersOwnError: true,\n component: (props) => React.createElement(ProjectCodeFieldBinding, {\n value: props.value,\n values: props.values,\n error: props.error,\n disabled: props.disabled,\n setValue: props.setValue,\n setFormValue: props.setFormValue,\n }),\n },\n {\n id: 'customerId',\n type: 'custom',\n label: t('staff.time_tracking.projects.form.customer', 'Customer'),\n description: t(\n 'staff.time_tracking.projects.form.customerHint',\n 'Time is organised per customer \u2014 a project cannot be saved without one.',\n ),\n required: true,\n component: (props) => React.createElement(CustomerPickerBinding, {\n value: props.value,\n values: props.values,\n disabled: props.disabled,\n setValue: props.setValue,\n setFormValue: props.setFormValue,\n }),\n },\n {\n id: 'description',\n type: 'textarea',\n label: t('staff.time_tracking.projects.form.description', 'Description'),\n placeholder: t(\n 'staff.time_tracking.projects.form.descriptionPlaceholder',\n 'Scope of work, what was agreed with the customer\u2026',\n ),\n rows: 4,\n },\n {\n id: 'hourlyRate',\n type: 'custom',\n label: t('staff.time_tracking.projects.form.hourlyRate', 'Hourly rate'),\n layout: 'half',\n component: (props) => React.createElement(\n 'div',\n { className: 'flex items-center gap-2' },\n React.createElement(Input, {\n inputMode: 'decimal',\n value: typeof props.value === 'string' ? props.value : '',\n disabled: props.disabled,\n 'aria-invalid': Boolean(props.error),\n onChange: (event: React.ChangeEvent<HTMLInputElement>) => props.setValue(event.target.value),\n }),\n React.createElement(\n 'span',\n { className: 'shrink-0 text-sm text-muted-foreground' },\n t('staff.time_tracking.projects.form.perHour', '/ h'),\n ),\n ),\n },\n {\n id: 'currencyCode',\n type: 'custom',\n label: t('staff.time_tracking.projects.form.currency', 'Currency'),\n layout: 'half',\n component: (props) => React.createElement(ProjectCurrencyFieldBinding, {\n value: props.value,\n values: props.values,\n disabled: props.disabled,\n setValue: props.setValue,\n onCurrencyChanged: options.onCurrencyChanged,\n }),\n },\n {\n id: 'billableByDefault',\n type: 'custom',\n label: t('staff.time_tracking.projects.form.billableByDefault', 'Billable by default'),\n component: (props) => React.createElement(SwitchField, {\n checked: props.value !== false,\n disabled: props.disabled,\n onCheckedChange: (next: boolean) => props.setValue(next === true),\n label: t('staff.time_tracking.projects.form.billableByDefault', 'Billable by default'),\n description: t(\n 'staff.time_tracking.projects.form.billableByDefaultHint',\n 'New entries in this project start as billable.',\n ),\n }),\n },\n {\n id: 'status',\n type: 'select',\n label: t('staff.time_tracking.projects.form.status', 'Status'),\n options: [\n { value: 'active', label: t('staff.timesheets.projects.statuses.active', 'Active') },\n { value: 'on_hold', label: t('staff.timesheets.projects.statuses.onHold', 'On Hold') },\n { value: 'completed', label: t('staff.timesheets.projects.statuses.completed', 'Completed') },\n ],\n },\n {\n id: 'color',\n type: 'custom',\n label: t('staff.timesheets.projects.form.color', 'Project color'),\n component: (props) => React.createElement(ColorPicker, {\n value: typeof props.value === 'string' ? props.value : null,\n onChange: (next: string | null) => props.setValue(next),\n resetLabel: t('staff.timesheets.projects.form.colorAuto', 'Auto'),\n }),\n },\n {\n id: 'projectType',\n type: 'text',\n label: t('staff.timesheets.projects.form.projectType', 'Project type'),\n placeholder: t('staff.timesheets.projects.form.projectTypePlaceholder', 'e.g. Internal, Client, R&D'),\n },\n {\n id: 'startDate',\n type: 'date',\n label: t('staff.timesheets.projects.form.startDate', 'Start date'),\n },\n {\n id: 'costCenter',\n type: 'text',\n label: t('staff.timesheets.projects.form.costCenter', 'Cost center'),\n placeholder: t('staff.timesheets.projects.form.costCenterPlaceholder', 'Cost center code'),\n },\n ]\n}\n\n/**\n * The group ids the project form renders, in render order.\n *\n * They are the addressable half of `crud-form:staff.staff_time_project:group:<id>`:\n * a contributed widget names one of these to land inside that card rather than at\n * the end of the form. Renaming one silently unbinds every widget aimed at it, so\n * the list is pinned by `__tests__/projectFormGroupIds.test.ts` and treated as a\n * frozen contract surface.\n *\n * `compact` hosts (the timesheet's inline create dialog) render the first two only.\n */\nexport const PROJECT_FORM_GROUP_IDS = [\n 'basics',\n 'billing',\n 'budget',\n 'status',\n 'team',\n 'rounding',\n 'details',\n] as const\n\nexport const PROJECT_FORM_COMPACT_GROUP_IDS = ['basics', 'billing'] as const\n\nexport type ProjectFormGroupId = (typeof PROJECT_FORM_GROUP_IDS)[number]\n\nexport type ProjectFormGroupOptions = {\n /**\n * Quick-create hosts (the timesheet's inline project dialog) render the form\n * inside a dialog, where the budget card, the team chips and the rounding\n * notice have no room and no meaning yet.\n */\n compact?: boolean\n}\n\nexport function createProjectFormGroups(\n t: TranslateFn,\n options: ProjectFormGroupOptions = {},\n): CrudFormGroup[] {\n if (options.compact) {\n return [\n {\n id: 'basics',\n column: 1,\n title: t('staff.time_tracking.projects.form.groupBasics', 'Basics'),\n fields: ['name', 'code', 'customerId', 'description'],\n },\n {\n id: 'billing',\n column: 1,\n title: t('staff.time_tracking.projects.form.groupBilling', 'Billing'),\n description: t(\n 'staff.time_tracking.projects.form.groupBillingHint',\n 'You can leave this empty and fill it in before the first report.',\n ),\n fields: ['hourlyRate', 'currencyCode', 'billableByDefault'],\n },\n ]\n }\n return [\n {\n id: 'basics',\n column: 1,\n title: t('staff.time_tracking.projects.form.groupBasics', 'Basics'),\n fields: ['name', 'code', 'customerId', 'description'],\n },\n {\n id: 'billing',\n column: 1,\n title: t('staff.time_tracking.projects.form.groupBilling', 'Billing'),\n description: t(\n 'staff.time_tracking.projects.form.groupBillingHint',\n 'You can leave this empty and fill it in before the first report.',\n ),\n fields: ['hourlyRate', 'currencyCode', 'billableByDefault'],\n },\n {\n id: 'budget',\n column: 1,\n title: t('staff.time_tracking.projects.form.groupBudget', 'Budget'),\n component: (ctx) => React.createElement(ProjectBudgetSection, {\n enabled: ctx.values.budgetEnabled === true,\n kind: (ctx.values.budgetKind as ProjectBudgetKind | undefined) ?? 'hours',\n value: readText(ctx.values, 'budgetValue'),\n warnAtPercent: readText(ctx.values, 'budgetWarnAtPercent') || String(DEFAULT_BUDGET_WARN_AT_PERCENT),\n currencyCode: readText(ctx.values, 'currencyCode') || null,\n onChange: (patch: {\n enabled?: boolean\n kind?: ProjectBudgetKind\n value?: string\n warnAtPercent?: string\n }) => {\n if (patch.enabled !== undefined) ctx.setValue('budgetEnabled', patch.enabled)\n if (patch.kind !== undefined) ctx.setValue('budgetKind', patch.kind)\n if (patch.value !== undefined) ctx.setValue('budgetValue', patch.value)\n if (patch.warnAtPercent !== undefined) ctx.setValue('budgetWarnAtPercent', patch.warnAtPercent)\n },\n }),\n },\n {\n id: 'status',\n column: 2,\n title: t('staff.time_tracking.projects.form.groupStatus', 'Status'),\n fields: ['status'],\n },\n {\n id: 'team',\n column: 2,\n title: t('staff.time_tracking.projects.form.groupTeam', 'Team'),\n component: (ctx) => React.createElement(ProjectTeamSection, {\n projectId: typeof ctx.values.id === 'string' ? ctx.values.id : null,\n }),\n },\n {\n id: 'rounding',\n column: 2,\n bare: true,\n component: () => React.createElement(ProjectRoundingNotice, {}),\n },\n {\n id: 'details',\n column: 2,\n title: t('staff.timesheets.projects.form.groupDetails', 'Additional Information'),\n fields: ['color', 'projectType', 'startDate', 'costCenter'],\n },\n ]\n}\n\nfunction trimmedOrNull(value: string | null | undefined): string | null {\n if (typeof value !== 'string') return null\n const trimmed = value.trim()\n return trimmed.length > 0 ? trimmed : null\n}\n\nfunction numericOrNull(value: string | null | undefined): string | null {\n const trimmed = trimmedOrNull(value)\n if (trimmed === null) return null\n return trimmed.replace(',', '.')\n}\n\nfunction buildCustomerSnapshot(values: ProjectFormValues): Record<string, unknown> | null {\n const name = trimmedOrNull(values.customerName)\n if (!values.customerId || !name) return null\n const snapshot: Record<string, unknown> = { name }\n const kind = trimmedOrNull(values.customerKind)\n if (kind) snapshot.kind = kind\n const taxId = trimmedOrNull(values.customerTaxId)\n if (taxId) snapshot.taxId = taxId\n return snapshot\n}\n\nexport function buildProjectPayload(values: ProjectFormValues): Record<string, unknown> {\n const budgetEnabled = values.budgetEnabled === true\n const budgetKind: ProjectBudgetKind = budgetEnabled\n ? (values.budgetKind && values.budgetKind !== 'none' ? values.budgetKind : 'hours')\n : 'none'\n const warnAt = Number.parseInt(trimmedOrNull(values.budgetWarnAtPercent) ?? '', 10)\n\n const payload: Record<string, unknown> = {\n name: values.name.trim(),\n code: values.code.trim().toUpperCase(),\n customerId: values.customerId ?? null,\n customerSnapshot: buildCustomerSnapshot(values),\n description: trimmedOrNull(values.description),\n projectType: trimmedOrNull(values.projectType),\n color: trimmedOrNull(values.color),\n startDate: values.startDate || null,\n costCenter: trimmedOrNull(values.costCenter),\n hourlyRate: numericOrNull(values.hourlyRate),\n billableByDefault: values.billableByDefault !== false,\n budgetKind,\n budgetValue: budgetEnabled ? numericOrNull(values.budgetValue) : null,\n budgetWarnAtPercent: Number.isFinite(warnAt) ? warnAt : DEFAULT_BUDGET_WARN_AT_PERCENT,\n }\n // D-3: the currency is chosen once, at creation. Every later change belongs to\n // the dedicated change-currency endpoint, which carries the non-conversion\n // acknowledgement and the locked-report refusal \u2014 and `staffTimeProjectUpdateSchema`\n // has no `currencyCode` at all. Emitting it on update would be stripped in\n // silence and report a successful save that changed nothing, so the update\n // payload never carries the key.\n if (!values.id) {\n payload.currencyCode = trimmedOrNull(values.currencyCode)\n } else {\n payload.id = values.id\n }\n if (values.status) payload.status = values.status\n // The form renders custom-field inputs whenever `entityIds` is passed, but this\n // builder rebuilds the body from named fields \u2014 so every `cf_*` value has to be\n // carried across explicitly or the save silently discards what the user typed.\n Object.assign(payload, pickCustomFieldValues(values as Record<string, unknown>))\n return payload\n}\n"],
|
|
5
|
-
"mappings": "AAAA,YAAY,WAAW;AACvB,SAAS,SAAS;AAGlB,SAAS,aAAa;AACtB,SAAS,mBAAmB;AAC5B,SAAS,mBAAmB;AAC5B,SAAS,0BAA0B;AACnC,SAAS,+BAA+B;AACxC,SAAS,6BAA6B;AACtC,SAAS,+BAA+B;AACxC,SAAS,mCAAmC;AAC5C;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAEK;
|
|
4
|
+
"sourcesContent": ["import * as React from 'react'\nimport { z } from 'zod'\nimport type { CrudField, CrudFormGroup } from '@open-mercato/ui/backend/CrudForm'\nimport type { TranslateFn } from '@open-mercato/shared/lib/i18n/context'\nimport { Input } from '@open-mercato/ui/primitives/input'\nimport { SwitchField } from '@open-mercato/ui/primitives/switch-field'\nimport { ColorPicker } from '../../../../lib/timesheets-ui/ColorPicker'\nimport { PROJECT_COLOR_KEYS } from '../../../../lib/timesheets-ui/colors'\nimport { PROJECT_CODE_MAX_LENGTH } from '../../../../lib/time-tracking/projectCode'\nimport { CustomerPickerBinding } from '../../../../lib/time-tracking-ui/CustomerPicker'\nimport { ProjectCodeFieldBinding } from '../../../../lib/time-tracking-ui/ProjectCodeField'\nimport { ProjectCurrencyFieldBinding } from '../../../../lib/time-tracking-ui/ProjectCurrencyField'\nimport {\n DEFAULT_BUDGET_WARN_AT_PERCENT,\n ProjectBudgetSection,\n ProjectRoundingNotice,\n ProjectTeamSection,\n ProjectDefaultAssigneeField,\n type ProjectBudgetKind,\n} from '../../../../lib/time-tracking-ui/ProjectFormSections'\n\nexport type ProjectFormValues = {\n id?: string\n updatedAt?: string | null\n name: string\n code: string\n codeManual?: boolean\n customerId?: string | null\n customerName?: string | null\n customerKind?: string | null\n customerTaxId?: string | null\n description?: string | null\n hourlyRate?: string | null\n currencyCode?: string | null\n currencyLocked?: boolean\n entryCount?: number\n billableByDefault?: boolean\n budgetEnabled?: boolean\n budgetKind?: ProjectBudgetKind\n budgetValue?: string | null\n budgetWarnAtPercent?: string | null\n projectType?: string | null\n color?: string | null\n startDate?: string | null\n costCenter?: string | null\n status?: string\n defaultAssigneeStaffMemberId?: string | null\n /**\n * Custom-field values rendered by `CrudForm` from `entityIds`. They are keyed\n * `cf_<key>` / `cf:<key>` and are opaque here: this form neither declares nor\n * validates them, it only has to stop dropping them on the way to the command.\n */\n [customFieldKey: `cf_${string}`]: unknown\n [prefixedCustomFieldKey: `cf:${string}`]: unknown\n}\n\nconst CUSTOM_FIELD_KEY_PATTERN = /^cf[_:]/\n\nexport function pickCustomFieldValues(values: Record<string, unknown>): Record<string, unknown> {\n const picked: Record<string, unknown> = {}\n for (const [key, value] of Object.entries(values)) {\n if (CUSTOM_FIELD_KEY_PATTERN.test(key)) picked[key] = value\n }\n return picked\n}\n\nconst decimalPattern = /^\\d+([.,]\\d{1,4})?$/\n\nexport function createProjectFormSchema() {\n return z.object({\n id: z.string().optional(),\n updatedAt: z.string().optional().nullable(),\n name: z.string().min(1, 'staff.time_tracking.projects.validation.nameRequired'),\n code: z\n .string()\n .min(1, 'staff.time_tracking.projects.validation.codeRequired')\n .max(PROJECT_CODE_MAX_LENGTH)\n .regex(/^[A-Za-z0-9-]+$/, 'staff.time_tracking.projects.validation.codeFormat'),\n codeManual: z.boolean().optional(),\n // D-9 / US-B1: time is organised per customer, so a project cannot be saved without one.\n customerId: z.string().uuid('staff.time_tracking.projects.validation.customerRequired'),\n customerName: z.string().optional().nullable(),\n customerKind: z.string().optional().nullable(),\n customerTaxId: z.string().optional().nullable(),\n description: z.string().max(2000).optional().nullable(),\n hourlyRate: z\n .string()\n .regex(decimalPattern, 'staff.time_tracking.projects.validation.rateFormat')\n .optional()\n .nullable()\n .or(z.literal('')),\n currencyCode: z.string().min(3).max(10).optional().nullable().or(z.literal('')),\n currencyLocked: z.boolean().optional(),\n entryCount: z.number().optional(),\n billableByDefault: z.boolean().optional(),\n budgetEnabled: z.boolean().optional(),\n budgetKind: z.enum(['none', 'hours', 'amount']).optional(),\n budgetValue: z\n .string()\n .regex(decimalPattern, 'staff.time_tracking.projects.validation.budgetFormat')\n .optional()\n .nullable()\n .or(z.literal('')),\n budgetWarnAtPercent: z.string().optional().nullable(),\n projectType: z.string().max(100).optional().nullable(),\n color: z\n .string()\n .refine(\n (value) => (PROJECT_COLOR_KEYS as readonly string[]).includes(value),\n { message: 'staff.time_tracking.projects.validation.color' },\n )\n .optional()\n .nullable(),\n startDate: z.string().optional().nullable(),\n costCenter: z.string().max(100).optional().nullable(),\n status: z.enum(['active', 'on_hold', 'completed']).optional(),\n defaultAssigneeStaffMemberId: z.string().optional().nullable(),\n })\n}\n\nfunction readText(values: Record<string, unknown> | undefined, key: string): string {\n const value = values?.[key]\n return typeof value === 'string' ? value : ''\n}\n\nexport type ProjectFormFieldOptions = {\n /**\n * Called after the change-currency action succeeded. Hosts editing a persisted\n * project use it to reload the record, so the form picks up the currency the\n * action wrote AND the `updatedAt` it bumped \u2014 otherwise the next save would\n * collide with a version the same user had just superseded.\n */\n onCurrencyChanged?: (currencyCode: string) => void\n}\n\nexport function createProjectFormFields(\n t: TranslateFn,\n options: ProjectFormFieldOptions = {},\n): CrudField[] {\n return [\n {\n id: 'name',\n type: 'text',\n label: t('staff.time_tracking.projects.form.name', 'Project name'),\n placeholder: t('staff.time_tracking.projects.form.namePlaceholder', 'e.g. Nordvik \u2014 service portal'),\n required: true,\n },\n {\n id: 'code',\n type: 'custom',\n label: t('staff.time_tracking.projects.form.code', 'Project code'),\n rendersOwnError: true,\n component: (props) => React.createElement(ProjectCodeFieldBinding, {\n value: props.value,\n values: props.values,\n error: props.error,\n disabled: props.disabled,\n setValue: props.setValue,\n setFormValue: props.setFormValue,\n }),\n },\n {\n id: 'customerId',\n type: 'custom',\n label: t('staff.time_tracking.projects.form.customer', 'Customer'),\n description: t(\n 'staff.time_tracking.projects.form.customerHint',\n 'Time is organised per customer \u2014 a project cannot be saved without one.',\n ),\n required: true,\n component: (props) => React.createElement(CustomerPickerBinding, {\n value: props.value,\n values: props.values,\n disabled: props.disabled,\n setValue: props.setValue,\n setFormValue: props.setFormValue,\n }),\n },\n {\n id: 'description',\n type: 'textarea',\n label: t('staff.time_tracking.projects.form.description', 'Description'),\n placeholder: t(\n 'staff.time_tracking.projects.form.descriptionPlaceholder',\n 'Scope of work, what was agreed with the customer\u2026',\n ),\n rows: 4,\n },\n {\n id: 'hourlyRate',\n type: 'custom',\n label: t('staff.time_tracking.projects.form.hourlyRate', 'Hourly rate'),\n layout: 'half',\n component: (props) => React.createElement(\n 'div',\n { className: 'flex items-center gap-2' },\n React.createElement(Input, {\n inputMode: 'decimal',\n value: typeof props.value === 'string' ? props.value : '',\n disabled: props.disabled,\n 'aria-invalid': Boolean(props.error),\n onChange: (event: React.ChangeEvent<HTMLInputElement>) => props.setValue(event.target.value),\n }),\n React.createElement(\n 'span',\n { className: 'shrink-0 text-sm text-muted-foreground' },\n t('staff.time_tracking.projects.form.perHour', '/ h'),\n ),\n ),\n },\n {\n id: 'currencyCode',\n type: 'custom',\n label: t('staff.time_tracking.projects.form.currency', 'Currency'),\n layout: 'half',\n component: (props) => React.createElement(ProjectCurrencyFieldBinding, {\n value: props.value,\n values: props.values,\n disabled: props.disabled,\n setValue: props.setValue,\n onCurrencyChanged: options.onCurrencyChanged,\n }),\n },\n {\n id: 'billableByDefault',\n type: 'custom',\n label: t('staff.time_tracking.projects.form.billableByDefault', 'Billable by default'),\n component: (props) => React.createElement(SwitchField, {\n checked: props.value !== false,\n disabled: props.disabled,\n onCheckedChange: (next: boolean) => props.setValue(next === true),\n label: t('staff.time_tracking.projects.form.billableByDefault', 'Billable by default'),\n description: t(\n 'staff.time_tracking.projects.form.billableByDefaultHint',\n 'New entries in this project start as billable.',\n ),\n }),\n },\n {\n id: 'status',\n type: 'select',\n label: t('staff.time_tracking.projects.form.status', 'Status'),\n options: [\n { value: 'active', label: t('staff.timesheets.projects.statuses.active', 'Active') },\n { value: 'on_hold', label: t('staff.timesheets.projects.statuses.onHold', 'On Hold') },\n { value: 'completed', label: t('staff.timesheets.projects.statuses.completed', 'Completed') },\n ],\n },\n {\n id: 'color',\n type: 'custom',\n label: t('staff.timesheets.projects.form.color', 'Project color'),\n component: (props) => React.createElement(ColorPicker, {\n value: typeof props.value === 'string' ? props.value : null,\n onChange: (next: string | null) => props.setValue(next),\n resetLabel: t('staff.timesheets.projects.form.colorAuto', 'Auto'),\n }),\n },\n {\n id: 'projectType',\n type: 'text',\n label: t('staff.timesheets.projects.form.projectType', 'Project type'),\n placeholder: t('staff.timesheets.projects.form.projectTypePlaceholder', 'e.g. Internal, Client, R&D'),\n },\n {\n id: 'startDate',\n type: 'date',\n label: t('staff.timesheets.projects.form.startDate', 'Start date'),\n },\n {\n id: 'costCenter',\n type: 'text',\n label: t('staff.timesheets.projects.form.costCenter', 'Cost center'),\n placeholder: t('staff.timesheets.projects.form.costCenterPlaceholder', 'Cost center code'),\n },\n ]\n}\n\n/**\n * The group ids the project form renders, in render order.\n *\n * They are the addressable half of `crud-form:staff.staff_time_project:group:<id>`:\n * a contributed widget names one of these to land inside that card rather than at\n * the end of the form. Renaming one silently unbinds every widget aimed at it, so\n * the list is pinned by `__tests__/projectFormGroupIds.test.ts` and treated as a\n * frozen contract surface.\n *\n * `compact` hosts (the timesheet's inline create dialog) render the first two only.\n */\nexport const PROJECT_FORM_GROUP_IDS = [\n 'basics',\n 'billing',\n 'budget',\n 'status',\n 'team',\n 'rounding',\n 'details',\n] as const\n\nexport const PROJECT_FORM_COMPACT_GROUP_IDS = ['basics', 'billing'] as const\n\nexport type ProjectFormGroupId = (typeof PROJECT_FORM_GROUP_IDS)[number]\n\nexport type ProjectFormGroupOptions = {\n /**\n * Quick-create hosts (the timesheet's inline project dialog) render the form\n * inside a dialog, where the budget card, the team chips and the rounding\n * notice have no room and no meaning yet.\n */\n compact?: boolean\n}\n\nexport function createProjectFormGroups(\n t: TranslateFn,\n options: ProjectFormGroupOptions = {},\n): CrudFormGroup[] {\n if (options.compact) {\n return [\n {\n id: 'basics',\n column: 1,\n title: t('staff.time_tracking.projects.form.groupBasics', 'Basics'),\n fields: ['name', 'code', 'customerId', 'description'],\n },\n {\n id: 'billing',\n column: 1,\n title: t('staff.time_tracking.projects.form.groupBilling', 'Billing'),\n description: t(\n 'staff.time_tracking.projects.form.groupBillingHint',\n 'You can leave this empty and fill it in before the first report.',\n ),\n fields: ['hourlyRate', 'currencyCode', 'billableByDefault'],\n },\n ]\n }\n return [\n {\n id: 'basics',\n column: 1,\n title: t('staff.time_tracking.projects.form.groupBasics', 'Basics'),\n fields: ['name', 'code', 'customerId', 'description'],\n },\n {\n id: 'billing',\n column: 1,\n title: t('staff.time_tracking.projects.form.groupBilling', 'Billing'),\n description: t(\n 'staff.time_tracking.projects.form.groupBillingHint',\n 'You can leave this empty and fill it in before the first report.',\n ),\n fields: ['hourlyRate', 'currencyCode', 'billableByDefault'],\n },\n {\n id: 'budget',\n column: 1,\n title: t('staff.time_tracking.projects.form.groupBudget', 'Budget'),\n component: (ctx) => React.createElement(ProjectBudgetSection, {\n enabled: ctx.values.budgetEnabled === true,\n kind: (ctx.values.budgetKind as ProjectBudgetKind | undefined) ?? 'hours',\n value: readText(ctx.values, 'budgetValue'),\n warnAtPercent: readText(ctx.values, 'budgetWarnAtPercent') || String(DEFAULT_BUDGET_WARN_AT_PERCENT),\n currencyCode: readText(ctx.values, 'currencyCode') || null,\n onChange: (patch: {\n enabled?: boolean\n kind?: ProjectBudgetKind\n value?: string\n warnAtPercent?: string\n }) => {\n if (patch.enabled !== undefined) ctx.setValue('budgetEnabled', patch.enabled)\n if (patch.kind !== undefined) ctx.setValue('budgetKind', patch.kind)\n if (patch.value !== undefined) ctx.setValue('budgetValue', patch.value)\n if (patch.warnAtPercent !== undefined) ctx.setValue('budgetWarnAtPercent', patch.warnAtPercent)\n },\n }),\n },\n {\n id: 'status',\n column: 2,\n title: t('staff.time_tracking.projects.form.groupStatus', 'Status'),\n fields: ['status'],\n },\n {\n id: 'team',\n column: 2,\n title: t('staff.time_tracking.projects.form.groupTeam', 'Team'),\n component: (ctx) => {\n const projectId = typeof ctx.values.id === 'string' ? ctx.values.id : null\n const defaultAssignee = ctx.values.defaultAssigneeStaffMemberId\n return React.createElement(\n React.Fragment,\n null,\n React.createElement(ProjectTeamSection, { projectId }),\n projectId\n ? React.createElement(ProjectDefaultAssigneeField, {\n projectId,\n value: typeof defaultAssignee === 'string' && defaultAssignee.length > 0 ? defaultAssignee : null,\n onChange: (next: string | null) => ctx.setValue('defaultAssigneeStaffMemberId', next),\n })\n : null,\n )\n },\n },\n {\n id: 'rounding',\n column: 2,\n bare: true,\n component: () => React.createElement(ProjectRoundingNotice, {}),\n },\n {\n id: 'details',\n column: 2,\n title: t('staff.timesheets.projects.form.groupDetails', 'Additional Information'),\n fields: ['color', 'projectType', 'startDate', 'costCenter'],\n },\n ]\n}\n\nfunction trimmedOrNull(value: string | null | undefined): string | null {\n if (typeof value !== 'string') return null\n const trimmed = value.trim()\n return trimmed.length > 0 ? trimmed : null\n}\n\nfunction numericOrNull(value: string | null | undefined): string | null {\n const trimmed = trimmedOrNull(value)\n if (trimmed === null) return null\n return trimmed.replace(',', '.')\n}\n\nfunction buildCustomerSnapshot(values: ProjectFormValues): Record<string, unknown> | null {\n const name = trimmedOrNull(values.customerName)\n if (!values.customerId || !name) return null\n const snapshot: Record<string, unknown> = { name }\n const kind = trimmedOrNull(values.customerKind)\n if (kind) snapshot.kind = kind\n const taxId = trimmedOrNull(values.customerTaxId)\n if (taxId) snapshot.taxId = taxId\n return snapshot\n}\n\nexport function buildProjectPayload(values: ProjectFormValues): Record<string, unknown> {\n const budgetEnabled = values.budgetEnabled === true\n const budgetKind: ProjectBudgetKind = budgetEnabled\n ? (values.budgetKind && values.budgetKind !== 'none' ? values.budgetKind : 'hours')\n : 'none'\n const warnAt = Number.parseInt(trimmedOrNull(values.budgetWarnAtPercent) ?? '', 10)\n\n const payload: Record<string, unknown> = {\n name: values.name.trim(),\n code: values.code.trim().toUpperCase(),\n customerId: values.customerId ?? null,\n customerSnapshot: buildCustomerSnapshot(values),\n description: trimmedOrNull(values.description),\n projectType: trimmedOrNull(values.projectType),\n color: trimmedOrNull(values.color),\n startDate: values.startDate || null,\n costCenter: trimmedOrNull(values.costCenter),\n hourlyRate: numericOrNull(values.hourlyRate),\n billableByDefault: values.billableByDefault !== false,\n budgetKind,\n budgetValue: budgetEnabled ? numericOrNull(values.budgetValue) : null,\n budgetWarnAtPercent: Number.isFinite(warnAt) ? warnAt : DEFAULT_BUDGET_WARN_AT_PERCENT,\n }\n // D-3: the currency is chosen once, at creation. Every later change belongs to\n // the dedicated change-currency endpoint, which carries the non-conversion\n // acknowledgement and the locked-report refusal \u2014 and `staffTimeProjectUpdateSchema`\n // has no `currencyCode` at all. Emitting it on update would be stripped in\n // silence and report a successful save that changed nothing, so the update\n // payload never carries the key.\n if (!values.id) {\n payload.currencyCode = trimmedOrNull(values.currencyCode)\n } else {\n payload.id = values.id\n if (values.defaultAssigneeStaffMemberId !== undefined) {\n payload.defaultAssigneeStaffMemberId = values.defaultAssigneeStaffMemberId || null\n }\n }\n if (values.status) payload.status = values.status\n // The form renders custom-field inputs whenever `entityIds` is passed, but this\n // builder rebuilds the body from named fields \u2014 so every `cf_*` value has to be\n // carried across explicitly or the save silently discards what the user typed.\n Object.assign(payload, pickCustomFieldValues(values as Record<string, unknown>))\n return payload\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|