@open-mercato/core 0.6.4-develop.4217.1.c9aa050183 → 0.6.4-develop.4239.1.4a264a5828
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 +37 -0
- package/dist/generated/entities/staff_time_entry/index.js.map +7 -0
- package/dist/generated/entities/staff_time_entry_segment/index.js +23 -0
- package/dist/generated/entities/staff_time_entry_segment/index.js.map +7 -0
- package/dist/generated/entities/staff_time_project/index.js +35 -0
- package/dist/generated/entities/staff_time_project/index.js.map +7 -0
- package/dist/generated/entities/staff_time_project_member/index.js +29 -0
- package/dist/generated/entities/staff_time_project_member/index.js.map +7 -0
- package/dist/generated/entities.ids.generated.js +5 -1
- package/dist/generated/entities.ids.generated.js.map +2 -2
- package/dist/generated/entity-fields-registry.js +64 -0
- package/dist/generated/entity-fields-registry.js.map +2 -2
- package/dist/helpers/integration/timesheetFixtures.js +50 -0
- package/dist/helpers/integration/timesheetFixtures.js.map +7 -0
- package/dist/modules/attachments/api/library/[id]/route.js +20 -16
- package/dist/modules/attachments/api/library/[id]/route.js.map +2 -2
- package/dist/modules/attachments/api/route.js +18 -14
- package/dist/modules/attachments/api/route.js.map +2 -2
- package/dist/modules/auth/api/roles/acl/route.js +10 -4
- package/dist/modules/auth/api/roles/acl/route.js.map +2 -2
- package/dist/modules/auth/api/sidebar/preferences/route.js +27 -20
- package/dist/modules/auth/api/sidebar/preferences/route.js.map +2 -2
- package/dist/modules/auth/api/users/acl/route.js +16 -11
- package/dist/modules/auth/api/users/acl/route.js.map +2 -2
- package/dist/modules/auth/commands/users.js +87 -71
- package/dist/modules/auth/commands/users.js.map +2 -2
- package/dist/modules/auth/services/sidebarPreferencesService.js +39 -30
- package/dist/modules/auth/services/sidebarPreferencesService.js.map +2 -2
- package/dist/modules/business_rules/backend/logs/[id]/page.js +24 -5
- package/dist/modules/business_rules/backend/logs/[id]/page.js.map +2 -2
- package/dist/modules/catalog/api/offers/route.js +15 -5
- package/dist/modules/catalog/api/offers/route.js.map +2 -2
- package/dist/modules/catalog/commands/categories.js +61 -12
- package/dist/modules/catalog/commands/categories.js.map +2 -2
- package/dist/modules/catalog/commands/products.js +79 -54
- package/dist/modules/catalog/commands/products.js.map +2 -2
- package/dist/modules/catalog/commands/variants.js +29 -16
- package/dist/modules/catalog/commands/variants.js.map +2 -2
- package/dist/modules/currencies/backend/currencies/[id]/page.js +19 -2
- package/dist/modules/currencies/backend/currencies/[id]/page.js.map +2 -2
- package/dist/modules/currencies/commands/currencies.js +15 -8
- package/dist/modules/currencies/commands/currencies.js.map +2 -2
- package/dist/modules/customer_accounts/api/admin/users.js +27 -26
- package/dist/modules/customer_accounts/api/admin/users.js.map +2 -2
- package/dist/modules/customer_accounts/api/password/reset-confirm.js +5 -5
- package/dist/modules/customer_accounts/api/password/reset-confirm.js.map +2 -2
- package/dist/modules/customer_accounts/api/portal/users/[id]/roles.js +11 -10
- package/dist/modules/customer_accounts/api/portal/users/[id]/roles.js.map +2 -2
- package/dist/modules/customer_accounts/backend/customer_accounts/roles/[id]/page.js +27 -7
- package/dist/modules/customer_accounts/backend/customer_accounts/roles/[id]/page.js.map +2 -2
- package/dist/modules/customer_accounts/backend/customer_accounts/users/[id]/page.js +27 -7
- package/dist/modules/customer_accounts/backend/customer_accounts/users/[id]/page.js.map +2 -2
- package/dist/modules/customers/backend/customers/people/[id]/page.js +29 -8
- package/dist/modules/customers/backend/customers/people/[id]/page.js.map +2 -2
- package/dist/modules/customers/commands/addresses.js +35 -21
- package/dist/modules/customers/commands/addresses.js.map +2 -2
- package/dist/modules/customers/commands/companies.js +163 -162
- package/dist/modules/customers/commands/companies.js.map +2 -2
- package/dist/modules/customers/commands/deals.js +3 -4
- package/dist/modules/customers/commands/deals.js.map +2 -2
- package/dist/modules/customers/commands/interactions.js +19 -22
- package/dist/modules/customers/commands/interactions.js.map +2 -2
- package/dist/modules/customers/commands/people.js +18 -15
- package/dist/modules/customers/commands/people.js.map +2 -2
- package/dist/modules/customers/commands/personCompanyLinks.js +105 -94
- package/dist/modules/customers/commands/personCompanyLinks.js.map +2 -2
- package/dist/modules/customers/commands/pipeline-stages.js +30 -23
- package/dist/modules/customers/commands/pipeline-stages.js.map +2 -2
- package/dist/modules/customers/commands/pipelines.js +27 -20
- package/dist/modules/customers/commands/pipelines.js.map +2 -2
- package/dist/modules/customers/commands/tags.js +13 -5
- package/dist/modules/customers/commands/tags.js.map +2 -2
- package/dist/modules/dashboards/api/users/widgets/route.js +0 -1
- package/dist/modules/dashboards/api/users/widgets/route.js.map +2 -2
- package/dist/modules/dashboards/api/widgets/data/route.js +29 -1
- package/dist/modules/dashboards/api/widgets/data/route.js.map +2 -2
- package/dist/modules/data_sync/lib/sync-engine.js +4 -4
- package/dist/modules/data_sync/lib/sync-engine.js.map +2 -2
- package/dist/modules/data_sync/lib/sync-run-service.js +51 -27
- package/dist/modules/data_sync/lib/sync-run-service.js.map +2 -2
- package/dist/modules/directory/commands/organizations.js +192 -158
- package/dist/modules/directory/commands/organizations.js.map +3 -3
- package/dist/modules/inbox_ops/api/emails/[id]/reprocess/route.js +22 -16
- package/dist/modules/inbox_ops/api/emails/[id]/reprocess/route.js.map +2 -2
- package/dist/modules/messages/commands/messages.js +77 -75
- package/dist/modules/messages/commands/messages.js.map +2 -2
- package/dist/modules/messages/commands/shared.js +132 -132
- package/dist/modules/messages/commands/shared.js.map +2 -2
- package/dist/modules/perspectives/api/[tableId]/route.js +37 -26
- package/dist/modules/perspectives/api/[tableId]/route.js.map +2 -2
- package/dist/modules/progress/acl.js +8 -4
- package/dist/modules/progress/acl.js.map +2 -2
- package/dist/modules/resources/commands/resources.js +125 -117
- package/dist/modules/resources/commands/resources.js.map +2 -2
- package/dist/modules/resources/commands/tags.js +7 -3
- package/dist/modules/resources/commands/tags.js.map +2 -2
- package/dist/modules/sales/api/quotes/send/route.js +12 -11
- package/dist/modules/sales/api/quotes/send/route.js.map +2 -2
- package/dist/modules/sales/commands/documents.js +629 -478
- package/dist/modules/sales/commands/documents.js.map +2 -2
- package/dist/modules/sales/commands/payments.js +146 -146
- package/dist/modules/sales/commands/payments.js.map +2 -2
- package/dist/modules/sales/commands/returns.js +68 -60
- package/dist/modules/sales/commands/returns.js.map +2 -2
- package/dist/modules/staff/acl.js +10 -1
- package/dist/modules/staff/acl.js.map +2 -2
- package/dist/modules/staff/analytics.js +33 -0
- package/dist/modules/staff/analytics.js.map +7 -0
- package/dist/modules/staff/api/guards.js +31 -0
- package/dist/modules/staff/api/guards.js.map +7 -0
- package/dist/modules/staff/api/interceptors.js +96 -0
- package/dist/modules/staff/api/interceptors.js.map +7 -0
- package/dist/modules/staff/api/timesheets/my-projects/[projectId]/route.js +170 -0
- package/dist/modules/staff/api/timesheets/my-projects/[projectId]/route.js.map +7 -0
- package/dist/modules/staff/api/timesheets/my-projects/route.js +103 -0
- package/dist/modules/staff/api/timesheets/my-projects/route.js.map +7 -0
- package/dist/modules/staff/api/timesheets/projects/kpis/route.js +147 -0
- package/dist/modules/staff/api/timesheets/projects/kpis/route.js.map +7 -0
- package/dist/modules/staff/api/timesheets/time-entries/[id]/segments/[segmentId]/route.js +171 -0
- package/dist/modules/staff/api/timesheets/time-entries/[id]/segments/[segmentId]/route.js.map +7 -0
- package/dist/modules/staff/api/timesheets/time-entries/[id]/segments/route.js +180 -0
- package/dist/modules/staff/api/timesheets/time-entries/[id]/segments/route.js.map +7 -0
- package/dist/modules/staff/api/timesheets/time-entries/[id]/timer-start/route.js +155 -0
- package/dist/modules/staff/api/timesheets/time-entries/[id]/timer-start/route.js.map +7 -0
- package/dist/modules/staff/api/timesheets/time-entries/[id]/timer-stop/route.js +173 -0
- package/dist/modules/staff/api/timesheets/time-entries/[id]/timer-stop/route.js.map +7 -0
- package/dist/modules/staff/api/timesheets/time-entries/bulk/route.js +260 -0
- package/dist/modules/staff/api/timesheets/time-entries/bulk/route.js.map +7 -0
- package/dist/modules/staff/api/timesheets/time-entries/route.js +188 -0
- package/dist/modules/staff/api/timesheets/time-entries/route.js.map +7 -0
- package/dist/modules/staff/api/timesheets/time-projects/[id]/employees/route.js +159 -0
- package/dist/modules/staff/api/timesheets/time-projects/[id]/employees/route.js.map +7 -0
- package/dist/modules/staff/api/timesheets/time-projects/route.js +230 -0
- package/dist/modules/staff/api/timesheets/time-projects/route.js.map +7 -0
- package/dist/modules/staff/backend/staff/timesheets/page.js +710 -0
- package/dist/modules/staff/backend/staff/timesheets/page.js.map +7 -0
- package/dist/modules/staff/backend/staff/timesheets/page.meta.js +22 -0
- package/dist/modules/staff/backend/staff/timesheets/page.meta.js.map +7 -0
- package/dist/modules/staff/backend/staff/timesheets/projects/[id]/edit/page.js +125 -0
- package/dist/modules/staff/backend/staff/timesheets/projects/[id]/edit/page.js.map +7 -0
- package/dist/modules/staff/backend/staff/timesheets/projects/[id]/edit/page.meta.js +16 -0
- package/dist/modules/staff/backend/staff/timesheets/projects/[id]/edit/page.meta.js.map +7 -0
- package/dist/modules/staff/backend/staff/timesheets/projects/[id]/page.js +418 -0
- package/dist/modules/staff/backend/staff/timesheets/projects/[id]/page.js.map +7 -0
- package/dist/modules/staff/backend/staff/timesheets/projects/[id]/page.meta.js +16 -0
- package/dist/modules/staff/backend/staff/timesheets/projects/[id]/page.meta.js.map +7 -0
- package/dist/modules/staff/backend/staff/timesheets/projects/create/page.js +79 -0
- package/dist/modules/staff/backend/staff/timesheets/projects/create/page.js.map +7 -0
- package/dist/modules/staff/backend/staff/timesheets/projects/create/page.meta.js +16 -0
- package/dist/modules/staff/backend/staff/timesheets/projects/create/page.meta.js.map +7 -0
- package/dist/modules/staff/backend/staff/timesheets/projects/page.js +602 -0
- package/dist/modules/staff/backend/staff/timesheets/projects/page.js.map +7 -0
- package/dist/modules/staff/backend/staff/timesheets/projects/page.meta.js +25 -0
- package/dist/modules/staff/backend/staff/timesheets/projects/page.meta.js.map +7 -0
- package/dist/modules/staff/backend/staff/timesheets/projects/projectFormConfig.js +123 -0
- package/dist/modules/staff/backend/staff/timesheets/projects/projectFormConfig.js.map +7 -0
- package/dist/modules/staff/cli.js +38 -1
- package/dist/modules/staff/cli.js.map +2 -2
- package/dist/modules/staff/commands/index.js +2 -0
- package/dist/modules/staff/commands/index.js.map +2 -2
- package/dist/modules/staff/commands/leave-requests.js +30 -28
- package/dist/modules/staff/commands/leave-requests.js.map +3 -3
- package/dist/modules/staff/commands/team-members.js +21 -20
- package/dist/modules/staff/commands/team-members.js.map +2 -2
- package/dist/modules/staff/commands/timesheets-entries.js +409 -0
- package/dist/modules/staff/commands/timesheets-entries.js.map +7 -0
- package/dist/modules/staff/commands/timesheets-projects.js +618 -0
- package/dist/modules/staff/commands/timesheets-projects.js.map +7 -0
- package/dist/modules/staff/data/enrichers.js +104 -0
- package/dist/modules/staff/data/enrichers.js.map +7 -0
- package/dist/modules/staff/data/entities.js +226 -1
- package/dist/modules/staff/data/entities.js.map +2 -2
- package/dist/modules/staff/data/validators.js +113 -1
- package/dist/modules/staff/data/validators.js.map +2 -2
- package/dist/modules/staff/events.js +13 -1
- package/dist/modules/staff/events.js.map +2 -2
- package/dist/modules/staff/lib/crud.js +7 -1
- package/dist/modules/staff/lib/crud.js.map +2 -2
- package/dist/modules/staff/lib/staffMemberResolver.js +15 -0
- package/dist/modules/staff/lib/staffMemberResolver.js.map +7 -0
- package/dist/modules/staff/lib/timesheets-projects/computeProjectHoursTrend.js +60 -0
- package/dist/modules/staff/lib/timesheets-projects/computeProjectHoursTrend.js.map +7 -0
- package/dist/modules/staff/lib/timesheets-projects/computeProjectsKpis.js +260 -0
- package/dist/modules/staff/lib/timesheets-projects/computeProjectsKpis.js.map +7 -0
- package/dist/modules/staff/lib/timesheets-projects/dateBuckets.js +41 -0
- package/dist/modules/staff/lib/timesheets-projects/dateBuckets.js.map +7 -0
- package/dist/modules/staff/lib/timesheets-projects/initials.js +10 -0
- package/dist/modules/staff/lib/timesheets-projects/initials.js.map +7 -0
- package/dist/modules/staff/lib/timesheets-projects/kpiMath.js +12 -0
- package/dist/modules/staff/lib/timesheets-projects/kpiMath.js.map +7 -0
- package/dist/modules/staff/lib/timesheets-projects/listProjectMembersPreview.js +55 -0
- package/dist/modules/staff/lib/timesheets-projects/listProjectMembersPreview.js.map +7 -0
- package/dist/modules/staff/lib/timesheets-projects-ui/HoursSparkline.js +66 -0
- package/dist/modules/staff/lib/timesheets-projects-ui/HoursSparkline.js.map +7 -0
- package/dist/modules/staff/lib/timesheets-projects-ui/ProjectCard.js +81 -0
- package/dist/modules/staff/lib/timesheets-projects-ui/ProjectCard.js.map +7 -0
- package/dist/modules/staff/lib/timesheets-projects-ui/ProjectMembersAvatarStack.js +58 -0
- package/dist/modules/staff/lib/timesheets-projects-ui/ProjectMembersAvatarStack.js.map +7 -0
- package/dist/modules/staff/lib/timesheets-projects-ui/ProjectsKpiStrip.js +152 -0
- package/dist/modules/staff/lib/timesheets-projects-ui/ProjectsKpiStrip.js.map +7 -0
- package/dist/modules/staff/lib/timesheets-projects-ui/SavedViewTabs.js +37 -0
- package/dist/modules/staff/lib/timesheets-projects-ui/SavedViewTabs.js.map +7 -0
- package/dist/modules/staff/lib/timesheets-projects-ui/ViewModeToggle.js +57 -0
- package/dist/modules/staff/lib/timesheets-projects-ui/ViewModeToggle.js.map +7 -0
- package/dist/modules/staff/lib/timesheets-projects-ui/useProjectsViewMode.js +50 -0
- package/dist/modules/staff/lib/timesheets-projects-ui/useProjectsViewMode.js.map +7 -0
- package/dist/modules/staff/lib/timesheets-ui/AddRowDropdown.js +163 -0
- package/dist/modules/staff/lib/timesheets-ui/AddRowDropdown.js.map +7 -0
- package/dist/modules/staff/lib/timesheets-ui/CalendarPicker.js +209 -0
- package/dist/modules/staff/lib/timesheets-ui/CalendarPicker.js.map +7 -0
- package/dist/modules/staff/lib/timesheets-ui/ColorPicker.js +52 -0
- package/dist/modules/staff/lib/timesheets-ui/ColorPicker.js.map +7 -0
- package/dist/modules/staff/lib/timesheets-ui/CreateProjectDialog.js +77 -0
- package/dist/modules/staff/lib/timesheets-ui/CreateProjectDialog.js.map +7 -0
- package/dist/modules/staff/lib/timesheets-ui/ListView.js +173 -0
- package/dist/modules/staff/lib/timesheets-ui/ListView.js.map +7 -0
- package/dist/modules/staff/lib/timesheets-ui/ProjectColorDot.js +32 -0
- package/dist/modules/staff/lib/timesheets-ui/ProjectColorDot.js.map +7 -0
- package/dist/modules/staff/lib/timesheets-ui/TimerBar.js +270 -0
- package/dist/modules/staff/lib/timesheets-ui/TimerBar.js.map +7 -0
- package/dist/modules/staff/lib/timesheets-ui/ViewSwitcher.js +57 -0
- package/dist/modules/staff/lib/timesheets-ui/ViewSwitcher.js.map +7 -0
- package/dist/modules/staff/lib/timesheets-ui/colors.js +43 -0
- package/dist/modules/staff/lib/timesheets-ui/colors.js.map +7 -0
- package/dist/modules/staff/migrations/Migration20260326135612.js +24 -0
- package/dist/modules/staff/migrations/Migration20260326135612.js.map +7 -0
- package/dist/modules/staff/migrations/Migration20260413102715.js +23 -0
- package/dist/modules/staff/migrations/Migration20260413102715.js.map +7 -0
- package/dist/modules/staff/migrations/Migration20260413111602.js +13 -0
- package/dist/modules/staff/migrations/Migration20260413111602.js.map +7 -0
- package/dist/modules/staff/migrations/Migration20260511112759.js +19 -0
- package/dist/modules/staff/migrations/Migration20260511112759.js.map +7 -0
- package/dist/modules/staff/search.js +35 -0
- package/dist/modules/staff/search.js.map +2 -2
- package/dist/modules/staff/setup.js +15 -1
- package/dist/modules/staff/setup.js.map +2 -2
- package/dist/modules/staff/widgets/dashboard/timesheets-hours-by-project/config.js +16 -0
- package/dist/modules/staff/widgets/dashboard/timesheets-hours-by-project/config.js.map +7 -0
- package/dist/modules/staff/widgets/dashboard/timesheets-hours-by-project/widget.client.js +126 -0
- package/dist/modules/staff/widgets/dashboard/timesheets-hours-by-project/widget.client.js.map +7 -0
- package/dist/modules/staff/widgets/dashboard/timesheets-hours-by-project/widget.js +26 -0
- package/dist/modules/staff/widgets/dashboard/timesheets-hours-by-project/widget.js.map +7 -0
- package/dist/modules/staff/widgets/dashboard/timesheets-time-reporting/config.js +15 -0
- package/dist/modules/staff/widgets/dashboard/timesheets-time-reporting/config.js.map +7 -0
- package/dist/modules/staff/widgets/dashboard/timesheets-time-reporting/widget.client.js +238 -0
- package/dist/modules/staff/widgets/dashboard/timesheets-time-reporting/widget.client.js.map +7 -0
- package/dist/modules/staff/widgets/dashboard/timesheets-time-reporting/widget.js +26 -0
- package/dist/modules/staff/widgets/dashboard/timesheets-time-reporting/widget.js.map +7 -0
- package/dist/modules/staff/widgets/injection/timer-sidebar-indicator/widget.js +145 -0
- package/dist/modules/staff/widgets/injection/timer-sidebar-indicator/widget.js.map +7 -0
- package/dist/modules/staff/widgets/injection-table.js +12 -0
- package/dist/modules/staff/widgets/injection-table.js.map +7 -0
- package/dist/modules/sync_excel/api/import/route.js +19 -17
- package/dist/modules/sync_excel/api/import/route.js.map +2 -2
- package/dist/modules/translations/commands/translations.js +22 -19
- package/dist/modules/translations/commands/translations.js.map +2 -2
- package/dist/modules/workflows/backend/events/[id]/page.js +24 -6
- package/dist/modules/workflows/backend/events/[id]/page.js.map +2 -2
- package/dist/modules/workflows/backend/instances/[id]/page.js +27 -5
- package/dist/modules/workflows/backend/instances/[id]/page.js.map +2 -2
- package/dist/modules/workflows/backend/tasks/[id]/page.js +25 -6
- package/dist/modules/workflows/backend/tasks/[id]/page.js.map +2 -2
- package/generated/entities/staff_time_entry/index.ts +17 -0
- package/generated/entities/staff_time_entry_segment/index.ts +10 -0
- package/generated/entities/staff_time_project/index.ts +16 -0
- package/generated/entities/staff_time_project_member/index.ts +13 -0
- package/generated/entities.ids.generated.ts +5 -1
- package/generated/entity-fields-registry.ts +64 -0
- package/package.json +7 -7
- package/src/helpers/integration/timesheetFixtures.ts +61 -0
- package/src/modules/attachments/api/library/[id]/route.ts +24 -17
- package/src/modules/attachments/api/route.ts +20 -14
- package/src/modules/auth/api/roles/acl/route.ts +11 -5
- package/src/modules/auth/api/sidebar/preferences/route.ts +33 -24
- package/src/modules/auth/api/users/acl/route.ts +17 -12
- package/src/modules/auth/commands/users.ts +96 -80
- package/src/modules/auth/services/sidebarPreferencesService.ts +40 -32
- package/src/modules/business_rules/backend/logs/[id]/page.tsx +32 -7
- package/src/modules/catalog/api/offers/route.ts +20 -5
- package/src/modules/catalog/commands/categories.ts +61 -12
- package/src/modules/catalog/commands/products.ts +93 -60
- package/src/modules/catalog/commands/variants.ts +29 -16
- package/src/modules/currencies/backend/currencies/[id]/page.tsx +21 -2
- package/src/modules/currencies/commands/currencies.ts +27 -14
- package/src/modules/currencies/i18n/de.json +1 -0
- package/src/modules/currencies/i18n/en.json +1 -0
- package/src/modules/currencies/i18n/es.json +1 -0
- package/src/modules/currencies/i18n/pl.json +1 -0
- package/src/modules/customer_accounts/api/admin/users.ts +31 -26
- package/src/modules/customer_accounts/api/password/reset-confirm.ts +5 -6
- package/src/modules/customer_accounts/api/portal/users/[id]/roles.ts +14 -13
- package/src/modules/customer_accounts/backend/customer_accounts/roles/[id]/page.tsx +34 -11
- package/src/modules/customer_accounts/backend/customer_accounts/users/[id]/page.tsx +34 -11
- package/src/modules/customers/backend/customers/people/[id]/page.tsx +35 -11
- package/src/modules/customers/commands/addresses.ts +35 -23
- package/src/modules/customers/commands/companies.ts +166 -165
- package/src/modules/customers/commands/deals.ts +2 -4
- package/src/modules/customers/commands/interactions.ts +20 -26
- package/src/modules/customers/commands/people.ts +18 -15
- package/src/modules/customers/commands/personCompanyLinks.ts +109 -100
- package/src/modules/customers/commands/pipeline-stages.ts +31 -27
- package/src/modules/customers/commands/pipelines.ts +29 -23
- package/src/modules/customers/commands/tags.ts +13 -5
- package/src/modules/dashboards/api/users/widgets/route.ts +0 -1
- package/src/modules/dashboards/api/widgets/data/route.ts +36 -1
- package/src/modules/data_sync/lib/sync-engine.ts +4 -5
- package/src/modules/data_sync/lib/sync-run-service.ts +57 -28
- package/src/modules/directory/commands/organizations.ts +203 -166
- package/src/modules/inbox_ops/api/emails/[id]/reprocess/route.ts +26 -18
- package/src/modules/messages/commands/messages.ts +82 -80
- package/src/modules/messages/commands/shared.ts +138 -133
- package/src/modules/perspectives/api/[tableId]/route.ts +38 -27
- package/src/modules/progress/acl.ts +4 -0
- package/src/modules/resources/commands/resources.ts +127 -117
- package/src/modules/resources/commands/tags.ts +7 -3
- package/src/modules/sales/api/quotes/send/route.ts +17 -12
- package/src/modules/sales/commands/documents.ts +673 -481
- package/src/modules/sales/commands/payments.ts +158 -152
- package/src/modules/sales/commands/returns.ts +74 -63
- package/src/modules/staff/acl.ts +11 -0
- package/src/modules/staff/analytics.ts +30 -0
- package/src/modules/staff/api/guards.ts +59 -0
- package/src/modules/staff/api/interceptors.ts +122 -0
- package/src/modules/staff/api/timesheets/my-projects/[projectId]/route.ts +191 -0
- package/src/modules/staff/api/timesheets/my-projects/route.ts +115 -0
- package/src/modules/staff/api/timesheets/projects/kpis/route.ts +159 -0
- package/src/modules/staff/api/timesheets/time-entries/[id]/segments/[segmentId]/route.ts +187 -0
- package/src/modules/staff/api/timesheets/time-entries/[id]/segments/route.ts +191 -0
- package/src/modules/staff/api/timesheets/time-entries/[id]/timer-start/route.ts +168 -0
- package/src/modules/staff/api/timesheets/time-entries/[id]/timer-stop/route.ts +191 -0
- package/src/modules/staff/api/timesheets/time-entries/bulk/route.ts +292 -0
- package/src/modules/staff/api/timesheets/time-entries/route.ts +193 -0
- package/src/modules/staff/api/timesheets/time-projects/[id]/employees/route.ts +167 -0
- package/src/modules/staff/api/timesheets/time-projects/route.ts +244 -0
- package/src/modules/staff/backend/staff/timesheets/page.meta.ts +20 -0
- package/src/modules/staff/backend/staff/timesheets/page.tsx +899 -0
- package/src/modules/staff/backend/staff/timesheets/projects/[id]/edit/page.meta.ts +12 -0
- package/src/modules/staff/backend/staff/timesheets/projects/[id]/edit/page.tsx +141 -0
- package/src/modules/staff/backend/staff/timesheets/projects/[id]/page.meta.ts +12 -0
- package/src/modules/staff/backend/staff/timesheets/projects/[id]/page.tsx +579 -0
- package/src/modules/staff/backend/staff/timesheets/projects/create/page.meta.ts +12 -0
- package/src/modules/staff/backend/staff/timesheets/projects/create/page.tsx +90 -0
- package/src/modules/staff/backend/staff/timesheets/projects/page.meta.ts +23 -0
- package/src/modules/staff/backend/staff/timesheets/projects/page.tsx +765 -0
- package/src/modules/staff/backend/staff/timesheets/projects/projectFormConfig.ts +138 -0
- package/src/modules/staff/cli.ts +40 -1
- package/src/modules/staff/commands/index.ts +2 -0
- package/src/modules/staff/commands/leave-requests.ts +37 -29
- package/src/modules/staff/commands/team-members.ts +25 -20
- package/src/modules/staff/commands/timesheets-entries.ts +504 -0
- package/src/modules/staff/commands/timesheets-projects.ts +699 -0
- package/src/modules/staff/data/enrichers.ts +134 -0
- package/src/modules/staff/data/entities.ts +198 -0
- package/src/modules/staff/data/validators.ts +129 -0
- package/src/modules/staff/events.ts +13 -0
- package/src/modules/staff/i18n/de.json +209 -1
- package/src/modules/staff/i18n/en.json +209 -1
- package/src/modules/staff/i18n/es.json +209 -1
- package/src/modules/staff/i18n/pl.json +209 -1
- package/src/modules/staff/lib/crud.ts +8 -0
- package/src/modules/staff/lib/staffMemberResolver.ts +22 -0
- package/src/modules/staff/lib/timesheets-projects/computeProjectHoursTrend.ts +89 -0
- package/src/modules/staff/lib/timesheets-projects/computeProjectsKpis.ts +311 -0
- package/src/modules/staff/lib/timesheets-projects/dateBuckets.ts +37 -0
- package/src/modules/staff/lib/timesheets-projects/initials.ts +6 -0
- package/src/modules/staff/lib/timesheets-projects/kpiMath.ts +8 -0
- package/src/modules/staff/lib/timesheets-projects/listProjectMembersPreview.ts +83 -0
- package/src/modules/staff/lib/timesheets-projects-ui/HoursSparkline.tsx +75 -0
- package/src/modules/staff/lib/timesheets-projects-ui/ProjectCard.tsx +110 -0
- package/src/modules/staff/lib/timesheets-projects-ui/ProjectMembersAvatarStack.tsx +73 -0
- package/src/modules/staff/lib/timesheets-projects-ui/ProjectsKpiStrip.tsx +185 -0
- package/src/modules/staff/lib/timesheets-projects-ui/SavedViewTabs.tsx +53 -0
- package/src/modules/staff/lib/timesheets-projects-ui/ViewModeToggle.tsx +63 -0
- package/src/modules/staff/lib/timesheets-projects-ui/useProjectsViewMode.ts +63 -0
- package/src/modules/staff/lib/timesheets-ui/AddRowDropdown.tsx +188 -0
- package/src/modules/staff/lib/timesheets-ui/CalendarPicker.tsx +229 -0
- package/src/modules/staff/lib/timesheets-ui/ColorPicker.tsx +65 -0
- package/src/modules/staff/lib/timesheets-ui/CreateProjectDialog.tsx +99 -0
- package/src/modules/staff/lib/timesheets-ui/ListView.tsx +230 -0
- package/src/modules/staff/lib/timesheets-ui/ProjectColorDot.tsx +40 -0
- package/src/modules/staff/lib/timesheets-ui/TimerBar.tsx +327 -0
- package/src/modules/staff/lib/timesheets-ui/ViewSwitcher.tsx +60 -0
- package/src/modules/staff/lib/timesheets-ui/colors.ts +58 -0
- package/src/modules/staff/migrations/.snapshot-open-mercato.json +1148 -0
- package/src/modules/staff/migrations/Migration20260326135612.ts +26 -0
- package/src/modules/staff/migrations/Migration20260413102715.ts +25 -0
- package/src/modules/staff/migrations/Migration20260413111602.ts +13 -0
- package/src/modules/staff/migrations/Migration20260511112759.ts +21 -0
- package/src/modules/staff/search.ts +35 -0
- package/src/modules/staff/setup.ts +15 -0
- package/src/modules/staff/widgets/dashboard/timesheets-hours-by-project/config.ts +17 -0
- package/src/modules/staff/widgets/dashboard/timesheets-hours-by-project/widget.client.tsx +158 -0
- package/src/modules/staff/widgets/dashboard/timesheets-hours-by-project/widget.ts +25 -0
- package/src/modules/staff/widgets/dashboard/timesheets-time-reporting/config.ts +15 -0
- package/src/modules/staff/widgets/dashboard/timesheets-time-reporting/widget.client.tsx +297 -0
- package/src/modules/staff/widgets/dashboard/timesheets-time-reporting/widget.ts +25 -0
- package/src/modules/staff/widgets/injection/timer-sidebar-indicator/widget.tsx +161 -0
- package/src/modules/staff/widgets/injection-table.ts +10 -0
- package/src/modules/sync_excel/api/import/route.ts +23 -18
- package/src/modules/translations/commands/translations.ts +49 -41
- package/src/modules/workflows/backend/events/[id]/page.tsx +32 -10
- package/src/modules/workflows/backend/instances/[id]/page.tsx +33 -9
- package/src/modules/workflows/backend/tasks/[id]/page.tsx +33 -10
- package/src/modules/workflows/i18n/de.json +1 -0
- package/src/modules/workflows/i18n/en.json +1 -0
- package/src/modules/workflows/i18n/es.json +1 -0
- package/src/modules/workflows/i18n/pl.json +1 -0
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../../src/modules/staff/lib/timesheets-ui/ProjectColorDot.tsx"],
|
|
4
|
+
"sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { resolveProjectColorHex } from './colors'\n\nexport type ProjectColorDotSize = 'xs' | 'sm' | 'md'\n\nexport type ProjectColorDotProps = {\n colorKey: string | null | undefined\n projectName: string | null | undefined\n size?: ProjectColorDotSize\n className?: string\n title?: string\n}\n\nconst SIZE_CLASS: Record<ProjectColorDotSize, string> = {\n xs: 'h-2 w-2',\n sm: 'h-2.5 w-2.5',\n md: 'h-3 w-3',\n}\n\nexport function ProjectColorDot({\n colorKey,\n projectName,\n size = 'sm',\n className,\n title,\n}: ProjectColorDotProps) {\n const hex = resolveProjectColorHex(colorKey, projectName)\n const base = 'inline-block shrink-0 rounded-full'\n const classes = [base, SIZE_CLASS[size], className].filter(Boolean).join(' ')\n return (\n <span\n aria-hidden=\"true\"\n title={title}\n className={classes}\n style={{ backgroundColor: hex }}\n />\n )\n}\n"],
|
|
5
|
+
"mappings": ";AAgCI;AA7BJ,SAAS,8BAA8B;AAYvC,MAAM,aAAkD;AAAA,EACtD,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AACN;AAEO,SAAS,gBAAgB;AAAA,EAC9B;AAAA,EACA;AAAA,EACA,OAAO;AAAA,EACP;AAAA,EACA;AACF,GAAyB;AACvB,QAAM,MAAM,uBAAuB,UAAU,WAAW;AACxD,QAAM,OAAO;AACb,QAAM,UAAU,CAAC,MAAM,WAAW,IAAI,GAAG,SAAS,EAAE,OAAO,OAAO,EAAE,KAAK,GAAG;AAC5E,SACE;AAAA,IAAC;AAAA;AAAA,MACC,eAAY;AAAA,MACZ;AAAA,MACA,WAAW;AAAA,MACX,OAAO,EAAE,iBAAiB,IAAI;AAAA;AAAA,EAChC;AAEJ;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useState, useEffect, useRef, useCallback } from "react";
|
|
4
|
+
import { Play, Square } from "lucide-react";
|
|
5
|
+
import { Button } from "@open-mercato/ui/primitives/button";
|
|
6
|
+
import { IconButton } from "@open-mercato/ui/primitives/icon-button";
|
|
7
|
+
import { useT } from "@open-mercato/shared/lib/i18n/context";
|
|
8
|
+
import { apiCall, apiCallOrThrow } from "@open-mercato/ui/backend/utils/apiCall";
|
|
9
|
+
import { flash } from "@open-mercato/ui/backend/FlashMessages";
|
|
10
|
+
import { ProjectColorDot } from "./ProjectColorDot.js";
|
|
11
|
+
function formatElapsed(seconds) {
|
|
12
|
+
const h = Math.floor(seconds / 3600);
|
|
13
|
+
const m = Math.floor(seconds % 3600 / 60);
|
|
14
|
+
const s = seconds % 60;
|
|
15
|
+
return `${h}:${String(m).padStart(2, "0")}:${String(s).padStart(2, "0")}`;
|
|
16
|
+
}
|
|
17
|
+
function getToday() {
|
|
18
|
+
const now = /* @__PURE__ */ new Date();
|
|
19
|
+
const year = now.getFullYear();
|
|
20
|
+
const month = String(now.getMonth() + 1).padStart(2, "0");
|
|
21
|
+
const day = String(now.getDate()).padStart(2, "0");
|
|
22
|
+
return `${year}-${month}-${day}`;
|
|
23
|
+
}
|
|
24
|
+
function TimerBar({ projects, staffMemberId, onTimerStopped }) {
|
|
25
|
+
const t = useT();
|
|
26
|
+
const [activeEntryId, setActiveEntryId] = useState(null);
|
|
27
|
+
const [activeProjectId, setActiveProjectId] = useState(null);
|
|
28
|
+
const [elapsedSeconds, setElapsedSeconds] = useState(0);
|
|
29
|
+
const [description, setDescription] = useState("");
|
|
30
|
+
const [selectedProjectId, setSelectedProjectId] = useState(null);
|
|
31
|
+
const [isStarting, setIsStarting] = useState(false);
|
|
32
|
+
const [isStopping, setIsStopping] = useState(false);
|
|
33
|
+
const [showProjectDropdown, setShowProjectDropdown] = useState(false);
|
|
34
|
+
const [projectFilter, setProjectFilter] = useState("");
|
|
35
|
+
const dropdownRef = useRef(null);
|
|
36
|
+
const intervalRef = useRef(null);
|
|
37
|
+
const isRunning = activeEntryId !== null;
|
|
38
|
+
const activeProject = projects.find((p) => p.id === activeProjectId);
|
|
39
|
+
const selectedProject = projects.find((p) => p.id === selectedProjectId);
|
|
40
|
+
const filteredProjects = projects.filter(
|
|
41
|
+
(p) => p.name.toLowerCase().includes(projectFilter.toLowerCase())
|
|
42
|
+
);
|
|
43
|
+
const startElapsedCounter = useCallback((startedAt) => {
|
|
44
|
+
const startTime = new Date(startedAt).getTime();
|
|
45
|
+
const now = Date.now();
|
|
46
|
+
const initialElapsed = Math.max(0, Math.floor((now - startTime) / 1e3));
|
|
47
|
+
setElapsedSeconds(initialElapsed);
|
|
48
|
+
if (intervalRef.current) clearInterval(intervalRef.current);
|
|
49
|
+
intervalRef.current = setInterval(() => {
|
|
50
|
+
setElapsedSeconds((prev) => prev + 1);
|
|
51
|
+
}, 1e3);
|
|
52
|
+
}, []);
|
|
53
|
+
const stopElapsedCounter = useCallback(() => {
|
|
54
|
+
if (intervalRef.current) {
|
|
55
|
+
clearInterval(intervalRef.current);
|
|
56
|
+
intervalRef.current = null;
|
|
57
|
+
}
|
|
58
|
+
setElapsedSeconds(0);
|
|
59
|
+
}, []);
|
|
60
|
+
useEffect(() => {
|
|
61
|
+
if (!staffMemberId) return;
|
|
62
|
+
const today = getToday();
|
|
63
|
+
const checkActiveTimer = async () => {
|
|
64
|
+
const response = await apiCall(
|
|
65
|
+
`/api/staff/timesheets/time-entries?staffMemberId=${staffMemberId}&from=${today}&to=${today}&pageSize=50`
|
|
66
|
+
);
|
|
67
|
+
if (!response.ok) return;
|
|
68
|
+
const data = response.result;
|
|
69
|
+
const items = data?.items ?? data?.data ?? [];
|
|
70
|
+
const activeEntry = items.find(
|
|
71
|
+
(entry) => entry.started_at && !entry.ended_at
|
|
72
|
+
);
|
|
73
|
+
if (activeEntry) {
|
|
74
|
+
setActiveEntryId(String(activeEntry.id ?? ""));
|
|
75
|
+
setActiveProjectId(String(activeEntry.time_project_id ?? ""));
|
|
76
|
+
setDescription(String(activeEntry.notes ?? ""));
|
|
77
|
+
startElapsedCounter(String(activeEntry.started_at ?? ""));
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
checkActiveTimer();
|
|
81
|
+
}, [staffMemberId, startElapsedCounter]);
|
|
82
|
+
useEffect(() => {
|
|
83
|
+
return () => {
|
|
84
|
+
if (intervalRef.current) clearInterval(intervalRef.current);
|
|
85
|
+
};
|
|
86
|
+
}, []);
|
|
87
|
+
useEffect(() => {
|
|
88
|
+
function handleClickOutside(event) {
|
|
89
|
+
if (dropdownRef.current && !dropdownRef.current.contains(event.target)) {
|
|
90
|
+
setShowProjectDropdown(false);
|
|
91
|
+
setProjectFilter("");
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
if (showProjectDropdown) {
|
|
95
|
+
document.addEventListener("mousedown", handleClickOutside);
|
|
96
|
+
}
|
|
97
|
+
return () => document.removeEventListener("mousedown", handleClickOutside);
|
|
98
|
+
}, [showProjectDropdown]);
|
|
99
|
+
const handleStart = async () => {
|
|
100
|
+
if (!selectedProjectId || !staffMemberId) return;
|
|
101
|
+
setIsStarting(true);
|
|
102
|
+
try {
|
|
103
|
+
const today = getToday();
|
|
104
|
+
const createResponse = await apiCallOrThrow(
|
|
105
|
+
"/api/staff/timesheets/time-entries",
|
|
106
|
+
{
|
|
107
|
+
method: "POST",
|
|
108
|
+
headers: { "Content-Type": "application/json" },
|
|
109
|
+
body: JSON.stringify({
|
|
110
|
+
staffMemberId,
|
|
111
|
+
timeProjectId: selectedProjectId,
|
|
112
|
+
date: today,
|
|
113
|
+
durationMinutes: 0,
|
|
114
|
+
source: "timer",
|
|
115
|
+
notes: description || null
|
|
116
|
+
})
|
|
117
|
+
}
|
|
118
|
+
);
|
|
119
|
+
const created = createResponse.result;
|
|
120
|
+
const entryId = created?.id;
|
|
121
|
+
await apiCallOrThrow(
|
|
122
|
+
`/api/staff/timesheets/time-entries/${entryId}/timer-start`,
|
|
123
|
+
{ method: "POST" }
|
|
124
|
+
);
|
|
125
|
+
setActiveEntryId(entryId ?? null);
|
|
126
|
+
setActiveProjectId(selectedProjectId);
|
|
127
|
+
startElapsedCounter((/* @__PURE__ */ new Date()).toISOString());
|
|
128
|
+
} catch {
|
|
129
|
+
flash(
|
|
130
|
+
t("staff.timesheets.my.timer.startError", "Failed to start timer"),
|
|
131
|
+
"error"
|
|
132
|
+
);
|
|
133
|
+
} finally {
|
|
134
|
+
setIsStarting(false);
|
|
135
|
+
}
|
|
136
|
+
};
|
|
137
|
+
const handleStop = async () => {
|
|
138
|
+
if (!activeEntryId) return;
|
|
139
|
+
setIsStopping(true);
|
|
140
|
+
try {
|
|
141
|
+
await apiCallOrThrow(
|
|
142
|
+
`/api/staff/timesheets/time-entries/${activeEntryId}/timer-stop`,
|
|
143
|
+
{ method: "POST" }
|
|
144
|
+
);
|
|
145
|
+
setActiveEntryId(null);
|
|
146
|
+
setActiveProjectId(null);
|
|
147
|
+
setDescription("");
|
|
148
|
+
stopElapsedCounter();
|
|
149
|
+
onTimerStopped();
|
|
150
|
+
} catch {
|
|
151
|
+
flash(
|
|
152
|
+
t("staff.timesheets.my.timer.stopError", "Failed to stop timer"),
|
|
153
|
+
"error"
|
|
154
|
+
);
|
|
155
|
+
} finally {
|
|
156
|
+
setIsStopping(false);
|
|
157
|
+
}
|
|
158
|
+
};
|
|
159
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3 rounded-lg border bg-card p-3 mb-4", children: [
|
|
160
|
+
/* @__PURE__ */ jsx(
|
|
161
|
+
"input",
|
|
162
|
+
{
|
|
163
|
+
type: "text",
|
|
164
|
+
value: description,
|
|
165
|
+
onChange: (e) => setDescription(e.target.value),
|
|
166
|
+
readOnly: isRunning,
|
|
167
|
+
placeholder: t(
|
|
168
|
+
"staff.timesheets.my.timer.placeholder",
|
|
169
|
+
"What are you working on?"
|
|
170
|
+
),
|
|
171
|
+
className: "flex-1 bg-transparent border-0 outline-none text-sm placeholder:text-muted-foreground"
|
|
172
|
+
}
|
|
173
|
+
),
|
|
174
|
+
/* @__PURE__ */ jsx("div", { className: "relative", ref: dropdownRef, children: isRunning ? activeProject ? /* @__PURE__ */ jsxs("span", { className: "inline-flex items-center gap-1.5 text-xs font-medium px-2 py-1 rounded border bg-muted", children: [
|
|
175
|
+
/* @__PURE__ */ jsx(ProjectColorDot, { colorKey: activeProject.color, projectName: activeProject.name, size: "xs" }),
|
|
176
|
+
activeProject.name
|
|
177
|
+
] }) : null : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
178
|
+
/* @__PURE__ */ jsx(
|
|
179
|
+
Button,
|
|
180
|
+
{
|
|
181
|
+
type: "button",
|
|
182
|
+
variant: "outline",
|
|
183
|
+
size: "sm",
|
|
184
|
+
onClick: () => {
|
|
185
|
+
setShowProjectDropdown(!showProjectDropdown);
|
|
186
|
+
setProjectFilter("");
|
|
187
|
+
},
|
|
188
|
+
className: "text-xs font-medium",
|
|
189
|
+
children: selectedProject ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
190
|
+
/* @__PURE__ */ jsx(ProjectColorDot, { colorKey: selectedProject.color, projectName: selectedProject.name, size: "xs" }),
|
|
191
|
+
/* @__PURE__ */ jsx("span", { className: "ml-1", children: selectedProject.name })
|
|
192
|
+
] }) : t("staff.timesheets.my.timer.selectProject", "Project")
|
|
193
|
+
}
|
|
194
|
+
),
|
|
195
|
+
showProjectDropdown && /* @__PURE__ */ jsxs("div", { className: "absolute right-0 top-full mt-1 z-50 min-w-[200px] rounded-md border bg-popover p-1 shadow-md", children: [
|
|
196
|
+
/* @__PURE__ */ jsx(
|
|
197
|
+
"input",
|
|
198
|
+
{
|
|
199
|
+
type: "text",
|
|
200
|
+
value: projectFilter,
|
|
201
|
+
onChange: (e) => setProjectFilter(e.target.value),
|
|
202
|
+
placeholder: t(
|
|
203
|
+
"staff.timesheets.my.timer.searchProject",
|
|
204
|
+
"Search projects..."
|
|
205
|
+
),
|
|
206
|
+
className: "w-full bg-transparent border-b px-2 py-1.5 text-xs outline-none placeholder:text-muted-foreground mb-1",
|
|
207
|
+
autoFocus: true
|
|
208
|
+
}
|
|
209
|
+
),
|
|
210
|
+
/* @__PURE__ */ jsx("div", { className: "max-h-[200px] overflow-y-auto", children: filteredProjects.length === 0 ? /* @__PURE__ */ jsx("div", { className: "px-2 py-1.5 text-xs text-muted-foreground", children: t(
|
|
211
|
+
"staff.timesheets.my.timer.noProjects",
|
|
212
|
+
"No projects found"
|
|
213
|
+
) }) : filteredProjects.map((project) => /* @__PURE__ */ jsxs(
|
|
214
|
+
Button,
|
|
215
|
+
{
|
|
216
|
+
type: "button",
|
|
217
|
+
variant: "ghost",
|
|
218
|
+
size: "sm",
|
|
219
|
+
className: "w-full justify-start text-xs h-auto py-1.5",
|
|
220
|
+
onClick: () => {
|
|
221
|
+
setSelectedProjectId(project.id);
|
|
222
|
+
setShowProjectDropdown(false);
|
|
223
|
+
setProjectFilter("");
|
|
224
|
+
},
|
|
225
|
+
children: [
|
|
226
|
+
/* @__PURE__ */ jsx(ProjectColorDot, { colorKey: project.color, projectName: project.name, size: "xs" }),
|
|
227
|
+
/* @__PURE__ */ jsx("span", { className: "ml-1", children: project.name }),
|
|
228
|
+
project.code ? /* @__PURE__ */ jsxs("span", { className: "ml-1 text-muted-foreground", children: [
|
|
229
|
+
"(",
|
|
230
|
+
project.code,
|
|
231
|
+
")"
|
|
232
|
+
] }) : null
|
|
233
|
+
]
|
|
234
|
+
},
|
|
235
|
+
project.id
|
|
236
|
+
)) })
|
|
237
|
+
] })
|
|
238
|
+
] }) }),
|
|
239
|
+
/* @__PURE__ */ jsx("span", { className: "font-mono text-sm tabular-nums min-w-[64px] text-right", children: formatElapsed(elapsedSeconds) }),
|
|
240
|
+
isRunning ? /* @__PURE__ */ jsx(
|
|
241
|
+
IconButton,
|
|
242
|
+
{
|
|
243
|
+
type: "button",
|
|
244
|
+
variant: "outline",
|
|
245
|
+
size: "default",
|
|
246
|
+
onClick: handleStop,
|
|
247
|
+
disabled: isStopping,
|
|
248
|
+
className: "bg-destructive text-destructive-foreground hover:bg-destructive/90",
|
|
249
|
+
"aria-label": t("staff.timesheets.my.timer.stop", "Stop timer"),
|
|
250
|
+
children: /* @__PURE__ */ jsx(Square, { className: "size-4" })
|
|
251
|
+
}
|
|
252
|
+
) : /* @__PURE__ */ jsx(
|
|
253
|
+
IconButton,
|
|
254
|
+
{
|
|
255
|
+
type: "button",
|
|
256
|
+
variant: "outline",
|
|
257
|
+
size: "default",
|
|
258
|
+
onClick: handleStart,
|
|
259
|
+
disabled: isStarting || !selectedProjectId,
|
|
260
|
+
className: "bg-primary text-primary-foreground hover:bg-primary/90",
|
|
261
|
+
"aria-label": t("staff.timesheets.my.timer.start", "Start timer"),
|
|
262
|
+
children: /* @__PURE__ */ jsx(Play, { className: "size-4" })
|
|
263
|
+
}
|
|
264
|
+
)
|
|
265
|
+
] });
|
|
266
|
+
}
|
|
267
|
+
export {
|
|
268
|
+
TimerBar
|
|
269
|
+
};
|
|
270
|
+
//# sourceMappingURL=TimerBar.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../../src/modules/staff/lib/timesheets-ui/TimerBar.tsx"],
|
|
4
|
+
"sourcesContent": ["'use client'\n\nimport { useState, useEffect, useRef, useCallback } from 'react'\nimport { Play, Square } from 'lucide-react'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { IconButton } from '@open-mercato/ui/primitives/icon-button'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { apiCall, apiCallOrThrow } from '@open-mercato/ui/backend/utils/apiCall'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { ProjectColorDot } from './ProjectColorDot'\n\ntype ProjectOption = {\n id: string\n name: string\n code: string | null\n color?: string | null\n}\n\ntype TimerBarProps = {\n projects: ProjectOption[]\n staffMemberId: string | null\n onTimerStopped: () => void\n}\n\nfunction formatElapsed(seconds: number): string {\n const h = Math.floor(seconds / 3600)\n const m = Math.floor((seconds % 3600) / 60)\n const s = seconds % 60\n return `${h}:${String(m).padStart(2, '0')}:${String(s).padStart(2, '0')}`\n}\n\nfunction getToday(): string {\n const now = new Date()\n const year = now.getFullYear()\n const month = String(now.getMonth() + 1).padStart(2, '0')\n const day = String(now.getDate()).padStart(2, '0')\n return `${year}-${month}-${day}`\n}\n\nexport function TimerBar({ projects, staffMemberId, onTimerStopped }: TimerBarProps) {\n const t = useT()\n\n const [activeEntryId, setActiveEntryId] = useState<string | null>(null)\n const [activeProjectId, setActiveProjectId] = useState<string | null>(null)\n const [elapsedSeconds, setElapsedSeconds] = useState(0)\n const [description, setDescription] = useState('')\n const [selectedProjectId, setSelectedProjectId] = useState<string | null>(null)\n const [isStarting, setIsStarting] = useState(false)\n const [isStopping, setIsStopping] = useState(false)\n const [showProjectDropdown, setShowProjectDropdown] = useState(false)\n const [projectFilter, setProjectFilter] = useState('')\n\n const dropdownRef = useRef<HTMLDivElement>(null)\n const intervalRef = useRef<ReturnType<typeof setInterval> | null>(null)\n\n const isRunning = activeEntryId !== null\n\n const activeProject = projects.find((p) => p.id === activeProjectId)\n const selectedProject = projects.find((p) => p.id === selectedProjectId)\n\n const filteredProjects = projects.filter((p) =>\n p.name.toLowerCase().includes(projectFilter.toLowerCase()),\n )\n\n const startElapsedCounter = useCallback((startedAt: string) => {\n const startTime = new Date(startedAt).getTime()\n const now = Date.now()\n const initialElapsed = Math.max(0, Math.floor((now - startTime) / 1000))\n setElapsedSeconds(initialElapsed)\n\n if (intervalRef.current) clearInterval(intervalRef.current)\n intervalRef.current = setInterval(() => {\n setElapsedSeconds((prev) => prev + 1)\n }, 1000)\n }, [])\n\n const stopElapsedCounter = useCallback(() => {\n if (intervalRef.current) {\n clearInterval(intervalRef.current)\n intervalRef.current = null\n }\n setElapsedSeconds(0)\n }, [])\n\n useEffect(() => {\n if (!staffMemberId) return\n\n const today = getToday()\n const checkActiveTimer = async () => {\n const response = await apiCall(\n `/api/staff/timesheets/time-entries?staffMemberId=${staffMemberId}&from=${today}&to=${today}&pageSize=50`,\n )\n if (!response.ok) return\n\n const data = response.result as Record<string, unknown> | null\n const items = (data?.items ?? data?.data ?? []) as Array<Record<string, unknown>>\n\n const activeEntry = items.find(\n (entry: Record<string, unknown>) =>\n entry.started_at && !entry.ended_at,\n )\n\n if (activeEntry) {\n setActiveEntryId(String(activeEntry.id ?? ''))\n setActiveProjectId(String(activeEntry.time_project_id ?? ''))\n setDescription(String(activeEntry.notes ?? ''))\n startElapsedCounter(String(activeEntry.started_at ?? ''))\n }\n }\n\n checkActiveTimer()\n }, [staffMemberId, startElapsedCounter])\n\n useEffect(() => {\n return () => {\n if (intervalRef.current) clearInterval(intervalRef.current)\n }\n }, [])\n\n useEffect(() => {\n function handleClickOutside(event: MouseEvent) {\n if (\n dropdownRef.current &&\n !dropdownRef.current.contains(event.target as Node)\n ) {\n setShowProjectDropdown(false)\n setProjectFilter('')\n }\n }\n\n if (showProjectDropdown) {\n document.addEventListener('mousedown', handleClickOutside)\n }\n return () => document.removeEventListener('mousedown', handleClickOutside)\n }, [showProjectDropdown])\n\n const handleStart = async () => {\n if (!selectedProjectId || !staffMemberId) return\n\n setIsStarting(true)\n try {\n const today = getToday()\n const createResponse = await apiCallOrThrow(\n '/api/staff/timesheets/time-entries',\n {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n staffMemberId,\n timeProjectId: selectedProjectId,\n date: today,\n durationMinutes: 0,\n source: 'timer',\n notes: description || null,\n }),\n },\n )\n\n const created = createResponse.result as Record<string, unknown> | null\n const entryId = created?.id as string | undefined\n\n await apiCallOrThrow(\n `/api/staff/timesheets/time-entries/${entryId}/timer-start`,\n { method: 'POST' },\n )\n\n setActiveEntryId(entryId ?? null)\n setActiveProjectId(selectedProjectId)\n startElapsedCounter(new Date().toISOString())\n } catch {\n flash(\n t('staff.timesheets.my.timer.startError', 'Failed to start timer'),\n 'error',\n )\n } finally {\n setIsStarting(false)\n }\n }\n\n const handleStop = async () => {\n if (!activeEntryId) return\n\n setIsStopping(true)\n try {\n await apiCallOrThrow(\n `/api/staff/timesheets/time-entries/${activeEntryId}/timer-stop`,\n { method: 'POST' },\n )\n\n setActiveEntryId(null)\n setActiveProjectId(null)\n setDescription('')\n stopElapsedCounter()\n onTimerStopped()\n } catch {\n flash(\n t('staff.timesheets.my.timer.stopError', 'Failed to stop timer'),\n 'error',\n )\n } finally {\n setIsStopping(false)\n }\n }\n\n return (\n <div className=\"flex items-center gap-3 rounded-lg border bg-card p-3 mb-4\">\n <input\n type=\"text\"\n value={description}\n onChange={(e) => setDescription(e.target.value)}\n readOnly={isRunning}\n placeholder={t(\n 'staff.timesheets.my.timer.placeholder',\n 'What are you working on?',\n )}\n className=\"flex-1 bg-transparent border-0 outline-none text-sm placeholder:text-muted-foreground\"\n />\n\n <div className=\"relative\" ref={dropdownRef}>\n {isRunning ? (\n activeProject ? (\n <span className=\"inline-flex items-center gap-1.5 text-xs font-medium px-2 py-1 rounded border bg-muted\">\n <ProjectColorDot colorKey={activeProject.color} projectName={activeProject.name} size=\"xs\" />\n {activeProject.name}\n </span>\n ) : null\n ) : (\n <>\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n onClick={() => {\n setShowProjectDropdown(!showProjectDropdown)\n setProjectFilter('')\n }}\n className=\"text-xs font-medium\"\n >\n {selectedProject\n ? (<><ProjectColorDot colorKey={selectedProject.color} projectName={selectedProject.name} size=\"xs\" /><span className=\"ml-1\">{selectedProject.name}</span></>)\n : t('staff.timesheets.my.timer.selectProject', 'Project')}\n </Button>\n\n {showProjectDropdown && (\n <div className=\"absolute right-0 top-full mt-1 z-50 min-w-[200px] rounded-md border bg-popover p-1 shadow-md\">\n <input\n type=\"text\"\n value={projectFilter}\n onChange={(e) => setProjectFilter(e.target.value)}\n placeholder={t(\n 'staff.timesheets.my.timer.searchProject',\n 'Search projects...',\n )}\n className=\"w-full bg-transparent border-b px-2 py-1.5 text-xs outline-none placeholder:text-muted-foreground mb-1\"\n autoFocus\n />\n <div className=\"max-h-[200px] overflow-y-auto\">\n {filteredProjects.length === 0 ? (\n <div className=\"px-2 py-1.5 text-xs text-muted-foreground\">\n {t(\n 'staff.timesheets.my.timer.noProjects',\n 'No projects found',\n )}\n </div>\n ) : (\n filteredProjects.map((project) => (\n <Button\n key={project.id}\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n className=\"w-full justify-start text-xs h-auto py-1.5\"\n onClick={() => {\n setSelectedProjectId(project.id)\n setShowProjectDropdown(false)\n setProjectFilter('')\n }}\n >\n <ProjectColorDot colorKey={project.color} projectName={project.name} size=\"xs\" />\n <span className=\"ml-1\">{project.name}</span>\n {project.code ? (\n <span className=\"ml-1 text-muted-foreground\">\n ({project.code})\n </span>\n ) : null}\n </Button>\n ))\n )}\n </div>\n </div>\n )}\n </>\n )}\n </div>\n\n <span className=\"font-mono text-sm tabular-nums min-w-[64px] text-right\">\n {formatElapsed(elapsedSeconds)}\n </span>\n\n {isRunning ? (\n <IconButton\n type=\"button\"\n variant=\"outline\"\n size=\"default\"\n onClick={handleStop}\n disabled={isStopping}\n className=\"bg-destructive text-destructive-foreground hover:bg-destructive/90\"\n aria-label={t('staff.timesheets.my.timer.stop', 'Stop timer')}\n >\n <Square className=\"size-4\" />\n </IconButton>\n ) : (\n <IconButton\n type=\"button\"\n variant=\"outline\"\n size=\"default\"\n onClick={handleStart}\n disabled={isStarting || !selectedProjectId}\n className=\"bg-primary text-primary-foreground hover:bg-primary/90\"\n aria-label={t('staff.timesheets.my.timer.start', 'Start timer')}\n >\n <Play className=\"size-4\" />\n </IconButton>\n )}\n </div>\n )\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { Button } from "@open-mercato/ui/primitives/button";
|
|
4
|
+
import { useT } from "@open-mercato/shared/lib/i18n/context";
|
|
5
|
+
function ViewSwitcher({ viewMode, onViewModeChange, viewType, onViewTypeChange }) {
|
|
6
|
+
const t = useT();
|
|
7
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-4", children: [
|
|
8
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1 rounded-md border p-1", children: [
|
|
9
|
+
/* @__PURE__ */ jsx(
|
|
10
|
+
Button,
|
|
11
|
+
{
|
|
12
|
+
type: "button",
|
|
13
|
+
size: "sm",
|
|
14
|
+
variant: viewMode === "weekly" ? "default" : "outline",
|
|
15
|
+
onClick: () => onViewModeChange("weekly"),
|
|
16
|
+
children: t("staff.timesheets.my.viewMode.weekly", "Weekly")
|
|
17
|
+
}
|
|
18
|
+
),
|
|
19
|
+
/* @__PURE__ */ jsx(
|
|
20
|
+
Button,
|
|
21
|
+
{
|
|
22
|
+
type: "button",
|
|
23
|
+
size: "sm",
|
|
24
|
+
variant: viewMode === "monthly" ? "default" : "outline",
|
|
25
|
+
onClick: () => onViewModeChange("monthly"),
|
|
26
|
+
children: t("staff.timesheets.my.viewMode.monthly", "Monthly")
|
|
27
|
+
}
|
|
28
|
+
)
|
|
29
|
+
] }),
|
|
30
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1 rounded-md border p-1", children: [
|
|
31
|
+
/* @__PURE__ */ jsx(
|
|
32
|
+
Button,
|
|
33
|
+
{
|
|
34
|
+
type: "button",
|
|
35
|
+
size: "sm",
|
|
36
|
+
variant: viewType === "timesheet" ? "default" : "outline",
|
|
37
|
+
onClick: () => onViewTypeChange("timesheet"),
|
|
38
|
+
children: t("staff.timesheets.my.viewType.timesheet", "Timesheet")
|
|
39
|
+
}
|
|
40
|
+
),
|
|
41
|
+
/* @__PURE__ */ jsx(
|
|
42
|
+
Button,
|
|
43
|
+
{
|
|
44
|
+
type: "button",
|
|
45
|
+
size: "sm",
|
|
46
|
+
variant: viewType === "list" ? "default" : "outline",
|
|
47
|
+
onClick: () => onViewTypeChange("list"),
|
|
48
|
+
children: t("staff.timesheets.my.viewType.list", "List view")
|
|
49
|
+
}
|
|
50
|
+
)
|
|
51
|
+
] })
|
|
52
|
+
] });
|
|
53
|
+
}
|
|
54
|
+
export {
|
|
55
|
+
ViewSwitcher
|
|
56
|
+
};
|
|
57
|
+
//# sourceMappingURL=ViewSwitcher.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../../src/modules/staff/lib/timesheets-ui/ViewSwitcher.tsx"],
|
|
4
|
+
"sourcesContent": ["\"use client\"\n\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\n\ntype ViewMode = 'weekly' | 'monthly'\ntype ViewType = 'timesheet' | 'list'\n\ninterface ViewSwitcherProps {\n viewMode: ViewMode\n onViewModeChange: (mode: ViewMode) => void\n viewType: ViewType\n onViewTypeChange: (type: ViewType) => void\n}\n\nexport function ViewSwitcher({ viewMode, onViewModeChange, viewType, onViewTypeChange }: ViewSwitcherProps) {\n const t = useT()\n\n return (\n <div className=\"flex items-center gap-4\">\n <div className=\"flex items-center gap-1 rounded-md border p-1\">\n <Button\n type=\"button\"\n size=\"sm\"\n variant={viewMode === 'weekly' ? 'default' : 'outline'}\n onClick={() => onViewModeChange('weekly')}\n >\n {t('staff.timesheets.my.viewMode.weekly', 'Weekly')}\n </Button>\n <Button\n type=\"button\"\n size=\"sm\"\n variant={viewMode === 'monthly' ? 'default' : 'outline'}\n onClick={() => onViewModeChange('monthly')}\n >\n {t('staff.timesheets.my.viewMode.monthly', 'Monthly')}\n </Button>\n </div>\n\n <div className=\"flex items-center gap-1 rounded-md border p-1\">\n <Button\n type=\"button\"\n size=\"sm\"\n variant={viewType === 'timesheet' ? 'default' : 'outline'}\n onClick={() => onViewTypeChange('timesheet')}\n >\n {t('staff.timesheets.my.viewType.timesheet', 'Timesheet')}\n </Button>\n <Button\n type=\"button\"\n size=\"sm\"\n variant={viewType === 'list' ? 'default' : 'outline'}\n onClick={() => onViewTypeChange('list')}\n >\n {t('staff.timesheets.my.viewType.list', 'List view')}\n </Button>\n </div>\n </div>\n )\n}\n"],
|
|
5
|
+
"mappings": ";AAoBM,SACE,KADF;AAlBN,SAAS,cAAc;AACvB,SAAS,YAAY;AAYd,SAAS,aAAa,EAAE,UAAU,kBAAkB,UAAU,iBAAiB,GAAsB;AAC1G,QAAM,IAAI,KAAK;AAEf,SACE,qBAAC,SAAI,WAAU,2BACb;AAAA,yBAAC,SAAI,WAAU,iDACb;AAAA;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL,MAAK;AAAA,UACL,SAAS,aAAa,WAAW,YAAY;AAAA,UAC7C,SAAS,MAAM,iBAAiB,QAAQ;AAAA,UAEvC,YAAE,uCAAuC,QAAQ;AAAA;AAAA,MACpD;AAAA,MACA;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL,MAAK;AAAA,UACL,SAAS,aAAa,YAAY,YAAY;AAAA,UAC9C,SAAS,MAAM,iBAAiB,SAAS;AAAA,UAExC,YAAE,wCAAwC,SAAS;AAAA;AAAA,MACtD;AAAA,OACF;AAAA,IAEA,qBAAC,SAAI,WAAU,iDACb;AAAA;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL,MAAK;AAAA,UACL,SAAS,aAAa,cAAc,YAAY;AAAA,UAChD,SAAS,MAAM,iBAAiB,WAAW;AAAA,UAE1C,YAAE,0CAA0C,WAAW;AAAA;AAAA,MAC1D;AAAA,MACA;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL,MAAK;AAAA,UACL,SAAS,aAAa,SAAS,YAAY;AAAA,UAC3C,SAAS,MAAM,iBAAiB,MAAM;AAAA,UAErC,YAAE,qCAAqC,WAAW;AAAA;AAAA,MACrD;AAAA,OACF;AAAA,KACF;AAEJ;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
const PROJECT_COLORS = [
|
|
2
|
+
{ key: "blue", hex: "#3B82F6" },
|
|
3
|
+
{ key: "green", hex: "#22C55E" },
|
|
4
|
+
{ key: "purple", hex: "#A855F7" },
|
|
5
|
+
{ key: "red", hex: "#EF4444" },
|
|
6
|
+
{ key: "orange", hex: "#F97316" },
|
|
7
|
+
{ key: "yellow", hex: "#EAB308" },
|
|
8
|
+
{ key: "pink", hex: "#EC4899" },
|
|
9
|
+
{ key: "teal", hex: "#14B8A6" },
|
|
10
|
+
{ key: "indigo", hex: "#6366F1" },
|
|
11
|
+
{ key: "cyan", hex: "#06B6D4" },
|
|
12
|
+
{ key: "emerald", hex: "#10B981" },
|
|
13
|
+
{ key: "slate", hex: "#64748B" }
|
|
14
|
+
];
|
|
15
|
+
const PROJECT_COLOR_KEYS = PROJECT_COLORS.map((c) => c.key);
|
|
16
|
+
const COLOR_BY_KEY = new Map(PROJECT_COLORS.map((c) => [c.key, c.hex]));
|
|
17
|
+
function isProjectColorKey(value) {
|
|
18
|
+
return typeof value === "string" && COLOR_BY_KEY.has(value);
|
|
19
|
+
}
|
|
20
|
+
function hashString(input) {
|
|
21
|
+
let hash = 5381;
|
|
22
|
+
for (let i = 0; i < input.length; i += 1) {
|
|
23
|
+
hash = (hash << 5) + hash + input.charCodeAt(i) | 0;
|
|
24
|
+
}
|
|
25
|
+
return Math.abs(hash);
|
|
26
|
+
}
|
|
27
|
+
function autoColorFromName(name) {
|
|
28
|
+
const safe = (name ?? "").trim().toLowerCase();
|
|
29
|
+
const index = safe.length === 0 ? 0 : hashString(safe) % PROJECT_COLORS.length;
|
|
30
|
+
return PROJECT_COLORS[index];
|
|
31
|
+
}
|
|
32
|
+
function resolveProjectColorHex(explicitKey, name) {
|
|
33
|
+
if (isProjectColorKey(explicitKey)) return COLOR_BY_KEY.get(explicitKey);
|
|
34
|
+
return autoColorFromName(name).hex;
|
|
35
|
+
}
|
|
36
|
+
export {
|
|
37
|
+
PROJECT_COLORS,
|
|
38
|
+
PROJECT_COLOR_KEYS,
|
|
39
|
+
autoColorFromName,
|
|
40
|
+
isProjectColorKey,
|
|
41
|
+
resolveProjectColorHex
|
|
42
|
+
};
|
|
43
|
+
//# sourceMappingURL=colors.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../../src/modules/staff/lib/timesheets-ui/colors.ts"],
|
|
4
|
+
"sourcesContent": ["export const PROJECT_COLORS = [\n { key: 'blue', hex: '#3B82F6' },\n { key: 'green', hex: '#22C55E' },\n { key: 'purple', hex: '#A855F7' },\n { key: 'red', hex: '#EF4444' },\n { key: 'orange', hex: '#F97316' },\n { key: 'yellow', hex: '#EAB308' },\n { key: 'pink', hex: '#EC4899' },\n { key: 'teal', hex: '#14B8A6' },\n { key: 'indigo', hex: '#6366F1' },\n { key: 'cyan', hex: '#06B6D4' },\n { key: 'emerald', hex: '#10B981' },\n { key: 'slate', hex: '#64748B' },\n] as const\n\nexport type ProjectColorKey = typeof PROJECT_COLORS[number]['key']\n\nexport const PROJECT_COLOR_KEYS: ProjectColorKey[] = PROJECT_COLORS.map((c) => c.key)\n\nconst COLOR_BY_KEY = new Map<string, string>(PROJECT_COLORS.map((c) => [c.key, c.hex]))\n\nexport function isProjectColorKey(value: unknown): value is ProjectColorKey {\n return typeof value === 'string' && COLOR_BY_KEY.has(value)\n}\n\n/**\n * Stable, non-cryptographic string hash (djb2). Positive integer output.\n * Used to derive a deterministic fallback color from a project's name.\n */\nfunction hashString(input: string): number {\n let hash = 5381\n for (let i = 0; i < input.length; i += 1) {\n hash = ((hash << 5) + hash + input.charCodeAt(i)) | 0\n }\n return Math.abs(hash)\n}\n\n/**\n * Returns a stable color for a project based on its name when no explicit\n * color is set. Same name \u2192 same color across reloads and devices.\n */\nexport function autoColorFromName(name: string | null | undefined): { key: ProjectColorKey; hex: string } {\n const safe = (name ?? '').trim().toLowerCase()\n const index = safe.length === 0 ? 0 : hashString(safe) % PROJECT_COLORS.length\n return PROJECT_COLORS[index]\n}\n\n/**\n * Resolve the hex for a project, preferring the explicit color key when\n * valid and falling back to the deterministic name-based palette otherwise.\n */\nexport function resolveProjectColorHex(\n explicitKey: string | null | undefined,\n name: string | null | undefined,\n): string {\n if (isProjectColorKey(explicitKey)) return COLOR_BY_KEY.get(explicitKey)!\n return autoColorFromName(name).hex\n}\n"],
|
|
5
|
+
"mappings": "AAAO,MAAM,iBAAiB;AAAA,EAC5B,EAAE,KAAK,QAAQ,KAAK,UAAU;AAAA,EAC9B,EAAE,KAAK,SAAS,KAAK,UAAU;AAAA,EAC/B,EAAE,KAAK,UAAU,KAAK,UAAU;AAAA,EAChC,EAAE,KAAK,OAAO,KAAK,UAAU;AAAA,EAC7B,EAAE,KAAK,UAAU,KAAK,UAAU;AAAA,EAChC,EAAE,KAAK,UAAU,KAAK,UAAU;AAAA,EAChC,EAAE,KAAK,QAAQ,KAAK,UAAU;AAAA,EAC9B,EAAE,KAAK,QAAQ,KAAK,UAAU;AAAA,EAC9B,EAAE,KAAK,UAAU,KAAK,UAAU;AAAA,EAChC,EAAE,KAAK,QAAQ,KAAK,UAAU;AAAA,EAC9B,EAAE,KAAK,WAAW,KAAK,UAAU;AAAA,EACjC,EAAE,KAAK,SAAS,KAAK,UAAU;AACjC;AAIO,MAAM,qBAAwC,eAAe,IAAI,CAAC,MAAM,EAAE,GAAG;AAEpF,MAAM,eAAe,IAAI,IAAoB,eAAe,IAAI,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC;AAE/E,SAAS,kBAAkB,OAA0C;AAC1E,SAAO,OAAO,UAAU,YAAY,aAAa,IAAI,KAAK;AAC5D;AAMA,SAAS,WAAW,OAAuB;AACzC,MAAI,OAAO;AACX,WAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK,GAAG;AACxC,YAAS,QAAQ,KAAK,OAAO,MAAM,WAAW,CAAC,IAAK;AAAA,EACtD;AACA,SAAO,KAAK,IAAI,IAAI;AACtB;AAMO,SAAS,kBAAkB,MAAwE;AACxG,QAAM,QAAQ,QAAQ,IAAI,KAAK,EAAE,YAAY;AAC7C,QAAM,QAAQ,KAAK,WAAW,IAAI,IAAI,WAAW,IAAI,IAAI,eAAe;AACxE,SAAO,eAAe,KAAK;AAC7B;AAMO,SAAS,uBACd,aACA,MACQ;AACR,MAAI,kBAAkB,WAAW,EAAG,QAAO,aAAa,IAAI,WAAW;AACvE,SAAO,kBAAkB,IAAI,EAAE;AACjC;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { Migration } from "@mikro-orm/migrations";
|
|
2
|
+
class Migration20260326135612 extends Migration {
|
|
3
|
+
async up() {
|
|
4
|
+
this.addSql(`create table "staff_time_entries" ("id" uuid not null default gen_random_uuid(), "tenant_id" uuid not null, "organization_id" uuid not null, "staff_member_id" uuid not null, "date" date not null, "duration_minutes" int not null default 0, "started_at" timestamptz null, "ended_at" timestamptz null, "notes" text null, "time_project_id" uuid null, "customer_id" uuid null, "deal_id" uuid null, "order_id" uuid null, "source" text check ("source" in ('manual', 'timer', 'kiosk', 'mobile')) not null default 'manual', "created_at" timestamptz not null, "updated_at" timestamptz not null, "deleted_at" timestamptz null, constraint "staff_time_entries_pkey" primary key ("id"));`);
|
|
5
|
+
this.addSql(`create index "staff_time_entries_project_date_idx" on "staff_time_entries" ("organization_id", "time_project_id", "date");`);
|
|
6
|
+
this.addSql(`create index "staff_time_entries_member_date_idx" on "staff_time_entries" ("organization_id", "staff_member_id", "date");`);
|
|
7
|
+
this.addSql(`create index "staff_time_entries_tenant_org_idx" on "staff_time_entries" ("tenant_id", "organization_id");`);
|
|
8
|
+
this.addSql(`create table "staff_time_entry_segments" ("id" uuid not null default gen_random_uuid(), "tenant_id" uuid not null, "organization_id" uuid not null, "time_entry_id" uuid not null, "started_at" timestamptz not null, "ended_at" timestamptz null, "segment_type" text check ("segment_type" in ('work', 'break')) not null default 'work', "created_at" timestamptz not null, "updated_at" timestamptz not null, "deleted_at" timestamptz null, constraint "staff_time_entry_segments_pkey" primary key ("id"));`);
|
|
9
|
+
this.addSql(`create index "staff_time_entry_segments_entry_idx" on "staff_time_entry_segments" ("time_entry_id");`);
|
|
10
|
+
this.addSql(`create index "staff_time_entry_segments_tenant_org_idx" on "staff_time_entry_segments" ("tenant_id", "organization_id");`);
|
|
11
|
+
this.addSql(`create table "staff_time_projects" ("id" uuid not null default gen_random_uuid(), "tenant_id" uuid not null, "organization_id" uuid not null, "name" text not null, "customer_id" uuid null, "code" text not null, "description" text null, "project_type" text null, "status" text check ("status" in ('active', 'on_hold', 'completed')) not null default 'active', "owner_user_id" uuid null, "cost_center" text null, "start_date" date null, "created_at" timestamptz not null, "updated_at" timestamptz not null, "deleted_at" timestamptz null, constraint "staff_time_projects_pkey" primary key ("id"));`);
|
|
12
|
+
this.addSql(`create index "staff_time_projects_code_unique_idx" on "staff_time_projects" ("organization_id", "tenant_id", "code");`);
|
|
13
|
+
this.addSql(`create index "staff_time_projects_tenant_org_idx" on "staff_time_projects" ("tenant_id", "organization_id");`);
|
|
14
|
+
this.addSql(`create table "staff_time_project_members" ("id" uuid not null default gen_random_uuid(), "tenant_id" uuid not null, "organization_id" uuid not null, "time_project_id" uuid not null, "staff_member_id" uuid not null, "role" text null, "status" text check ("status" in ('active', 'inactive')) not null default 'active', "assigned_start_date" date not null, "assigned_end_date" date null, "created_at" timestamptz not null, "updated_at" timestamptz not null, "deleted_at" timestamptz null, constraint "staff_time_project_members_pkey" primary key ("id"));`);
|
|
15
|
+
this.addSql(`create index "staff_time_project_members_unique_idx" on "staff_time_project_members" ("organization_id", "tenant_id", "time_project_id", "staff_member_id");`);
|
|
16
|
+
this.addSql(`create index "staff_time_project_members_member_idx" on "staff_time_project_members" ("organization_id", "staff_member_id");`);
|
|
17
|
+
this.addSql(`create index "staff_time_project_members_project_idx" on "staff_time_project_members" ("organization_id", "time_project_id");`);
|
|
18
|
+
this.addSql(`create index "staff_time_project_members_tenant_org_idx" on "staff_time_project_members" ("tenant_id", "organization_id");`);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
export {
|
|
22
|
+
Migration20260326135612
|
|
23
|
+
};
|
|
24
|
+
//# sourceMappingURL=Migration20260326135612.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/modules/staff/migrations/Migration20260326135612.ts"],
|
|
4
|
+
"sourcesContent": ["import { Migration } from '@mikro-orm/migrations';\n\nexport class Migration20260326135612 extends Migration {\n\n override async up(): Promise<void> {\n this.addSql(`create table \"staff_time_entries\" (\"id\" uuid not null default gen_random_uuid(), \"tenant_id\" uuid not null, \"organization_id\" uuid not null, \"staff_member_id\" uuid not null, \"date\" date not null, \"duration_minutes\" int not null default 0, \"started_at\" timestamptz null, \"ended_at\" timestamptz null, \"notes\" text null, \"time_project_id\" uuid null, \"customer_id\" uuid null, \"deal_id\" uuid null, \"order_id\" uuid null, \"source\" text check (\"source\" in ('manual', 'timer', 'kiosk', 'mobile')) not null default 'manual', \"created_at\" timestamptz not null, \"updated_at\" timestamptz not null, \"deleted_at\" timestamptz null, constraint \"staff_time_entries_pkey\" primary key (\"id\"));`);\n this.addSql(`create index \"staff_time_entries_project_date_idx\" on \"staff_time_entries\" (\"organization_id\", \"time_project_id\", \"date\");`);\n this.addSql(`create index \"staff_time_entries_member_date_idx\" on \"staff_time_entries\" (\"organization_id\", \"staff_member_id\", \"date\");`);\n this.addSql(`create index \"staff_time_entries_tenant_org_idx\" on \"staff_time_entries\" (\"tenant_id\", \"organization_id\");`);\n\n this.addSql(`create table \"staff_time_entry_segments\" (\"id\" uuid not null default gen_random_uuid(), \"tenant_id\" uuid not null, \"organization_id\" uuid not null, \"time_entry_id\" uuid not null, \"started_at\" timestamptz not null, \"ended_at\" timestamptz null, \"segment_type\" text check (\"segment_type\" in ('work', 'break')) not null default 'work', \"created_at\" timestamptz not null, \"updated_at\" timestamptz not null, \"deleted_at\" timestamptz null, constraint \"staff_time_entry_segments_pkey\" primary key (\"id\"));`);\n this.addSql(`create index \"staff_time_entry_segments_entry_idx\" on \"staff_time_entry_segments\" (\"time_entry_id\");`);\n this.addSql(`create index \"staff_time_entry_segments_tenant_org_idx\" on \"staff_time_entry_segments\" (\"tenant_id\", \"organization_id\");`);\n\n this.addSql(`create table \"staff_time_projects\" (\"id\" uuid not null default gen_random_uuid(), \"tenant_id\" uuid not null, \"organization_id\" uuid not null, \"name\" text not null, \"customer_id\" uuid null, \"code\" text not null, \"description\" text null, \"project_type\" text null, \"status\" text check (\"status\" in ('active', 'on_hold', 'completed')) not null default 'active', \"owner_user_id\" uuid null, \"cost_center\" text null, \"start_date\" date null, \"created_at\" timestamptz not null, \"updated_at\" timestamptz not null, \"deleted_at\" timestamptz null, constraint \"staff_time_projects_pkey\" primary key (\"id\"));`);\n this.addSql(`create index \"staff_time_projects_code_unique_idx\" on \"staff_time_projects\" (\"organization_id\", \"tenant_id\", \"code\");`);\n this.addSql(`create index \"staff_time_projects_tenant_org_idx\" on \"staff_time_projects\" (\"tenant_id\", \"organization_id\");`);\n\n this.addSql(`create table \"staff_time_project_members\" (\"id\" uuid not null default gen_random_uuid(), \"tenant_id\" uuid not null, \"organization_id\" uuid not null, \"time_project_id\" uuid not null, \"staff_member_id\" uuid not null, \"role\" text null, \"status\" text check (\"status\" in ('active', 'inactive')) not null default 'active', \"assigned_start_date\" date not null, \"assigned_end_date\" date null, \"created_at\" timestamptz not null, \"updated_at\" timestamptz not null, \"deleted_at\" timestamptz null, constraint \"staff_time_project_members_pkey\" primary key (\"id\"));`);\n this.addSql(`create index \"staff_time_project_members_unique_idx\" on \"staff_time_project_members\" (\"organization_id\", \"tenant_id\", \"time_project_id\", \"staff_member_id\");`);\n this.addSql(`create index \"staff_time_project_members_member_idx\" on \"staff_time_project_members\" (\"organization_id\", \"staff_member_id\");`);\n this.addSql(`create index \"staff_time_project_members_project_idx\" on \"staff_time_project_members\" (\"organization_id\", \"time_project_id\");`);\n this.addSql(`create index \"staff_time_project_members_tenant_org_idx\" on \"staff_time_project_members\" (\"tenant_id\", \"organization_id\");`);\n }\n\n}\n"],
|
|
5
|
+
"mappings": "AAAA,SAAS,iBAAiB;AAEnB,MAAM,gCAAgC,UAAU;AAAA,EAErD,MAAe,KAAoB;AACjC,SAAK,OAAO,mqBAAmqB;AAC/qB,SAAK,OAAO,4HAA4H;AACxI,SAAK,OAAO,2HAA2H;AACvI,SAAK,OAAO,4GAA4G;AAExH,SAAK,OAAO,mfAAmf;AAC/f,SAAK,OAAO,sGAAsG;AAClH,SAAK,OAAO,0HAA0H;AAEtI,SAAK,OAAO,mlBAAmlB;AAC/lB,SAAK,OAAO,uHAAuH;AACnI,SAAK,OAAO,8GAA8G;AAE1H,SAAK,OAAO,yiBAAyiB;AACrjB,SAAK,OAAO,8JAA8J;AAC1K,SAAK,OAAO,8HAA8H;AAC1I,SAAK,OAAO,+HAA+H;AAC3I,SAAK,OAAO,4HAA4H;AAAA,EAC1I;AAEF;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { Migration } from "@mikro-orm/migrations";
|
|
2
|
+
class Migration20260413102715 extends Migration {
|
|
3
|
+
async up() {
|
|
4
|
+
this.addSql(`alter table "staff_time_project_members" add column "show_in_grid" boolean not null default false;`);
|
|
5
|
+
this.addSql(`
|
|
6
|
+
update "staff_time_project_members" m
|
|
7
|
+
set "show_in_grid" = true
|
|
8
|
+
where exists (
|
|
9
|
+
select 1 from "staff_time_entries" e
|
|
10
|
+
where e."time_project_id" = m."time_project_id"
|
|
11
|
+
and e."staff_member_id" = m."staff_member_id"
|
|
12
|
+
and e."deleted_at" is null
|
|
13
|
+
);
|
|
14
|
+
`);
|
|
15
|
+
}
|
|
16
|
+
async down() {
|
|
17
|
+
this.addSql(`alter table "staff_time_project_members" drop column "show_in_grid";`);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
export {
|
|
21
|
+
Migration20260413102715
|
|
22
|
+
};
|
|
23
|
+
//# sourceMappingURL=Migration20260413102715.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/modules/staff/migrations/Migration20260413102715.ts"],
|
|
4
|
+
"sourcesContent": ["import { Migration } from '@mikro-orm/migrations';\n\nexport class Migration20260413102715 extends Migration {\n\n override async up(): Promise<void> {\n this.addSql(`alter table \"staff_time_project_members\" add column \"show_in_grid\" boolean not null default false;`);\n // Backfill: preserve grid visibility for memberships that already have time entries,\n // so existing users don't lose rows the first time the new visibility filter is applied.\n this.addSql(`\n update \"staff_time_project_members\" m\n set \"show_in_grid\" = true\n where exists (\n select 1 from \"staff_time_entries\" e\n where e.\"time_project_id\" = m.\"time_project_id\"\n and e.\"staff_member_id\" = m.\"staff_member_id\"\n and e.\"deleted_at\" is null\n );\n `);\n }\n\n override async down(): Promise<void> {\n this.addSql(`alter table \"staff_time_project_members\" drop column \"show_in_grid\";`);\n }\n\n}\n"],
|
|
5
|
+
"mappings": "AAAA,SAAS,iBAAiB;AAEnB,MAAM,gCAAgC,UAAU;AAAA,EAErD,MAAe,KAAoB;AACjC,SAAK,OAAO,oGAAoG;AAGhH,SAAK,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,KASX;AAAA,EACH;AAAA,EAEA,MAAe,OAAsB;AACnC,SAAK,OAAO,sEAAsE;AAAA,EACpF;AAEF;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Migration } from "@mikro-orm/migrations";
|
|
2
|
+
class Migration20260413111602 extends Migration {
|
|
3
|
+
async up() {
|
|
4
|
+
this.addSql(`alter table "staff_time_projects" add column "color" varchar(20) null;`);
|
|
5
|
+
}
|
|
6
|
+
async down() {
|
|
7
|
+
this.addSql(`alter table "staff_time_projects" drop column "color";`);
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
export {
|
|
11
|
+
Migration20260413111602
|
|
12
|
+
};
|
|
13
|
+
//# sourceMappingURL=Migration20260413111602.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/modules/staff/migrations/Migration20260413111602.ts"],
|
|
4
|
+
"sourcesContent": ["import { Migration } from '@mikro-orm/migrations';\n\nexport class Migration20260413111602 extends Migration {\n\n override async up(): Promise<void> {\n this.addSql(`alter table \"staff_time_projects\" add column \"color\" varchar(20) null;`);\n }\n\n override async down(): Promise<void> {\n this.addSql(`alter table \"staff_time_projects\" drop column \"color\";`);\n }\n\n}\n"],
|
|
5
|
+
"mappings": "AAAA,SAAS,iBAAiB;AAEnB,MAAM,gCAAgC,UAAU;AAAA,EAErD,MAAe,KAAoB;AACjC,SAAK,OAAO,wEAAwE;AAAA,EACtF;AAAA,EAEA,MAAe,OAAsB;AACnC,SAAK,OAAO,wDAAwD;AAAA,EACtE;AAEF;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { Migration } from "@mikro-orm/migrations";
|
|
2
|
+
class Migration20260511112759 extends Migration {
|
|
3
|
+
async up() {
|
|
4
|
+
this.addSql(`drop index if exists "staff_time_projects_code_unique_idx";`);
|
|
5
|
+
this.addSql(`create unique index "staff_time_projects_code_unique_idx" on "staff_time_projects" ("organization_id", "tenant_id", "code") where "deleted_at" is null;`);
|
|
6
|
+
this.addSql(`drop index if exists "staff_time_project_members_unique_idx";`);
|
|
7
|
+
this.addSql(`create unique index "staff_time_project_members_unique_idx" on "staff_time_project_members" ("organization_id", "tenant_id", "time_project_id", "staff_member_id") where "deleted_at" is null;`);
|
|
8
|
+
}
|
|
9
|
+
async down() {
|
|
10
|
+
this.addSql(`drop index if exists "staff_time_project_members_unique_idx";`);
|
|
11
|
+
this.addSql(`create index "staff_time_project_members_unique_idx" on "staff_time_project_members" ("organization_id", "tenant_id", "time_project_id", "staff_member_id");`);
|
|
12
|
+
this.addSql(`drop index if exists "staff_time_projects_code_unique_idx";`);
|
|
13
|
+
this.addSql(`create index "staff_time_projects_code_unique_idx" on "staff_time_projects" ("organization_id", "tenant_id", "code");`);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
export {
|
|
17
|
+
Migration20260511112759
|
|
18
|
+
};
|
|
19
|
+
//# sourceMappingURL=Migration20260511112759.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/modules/staff/migrations/Migration20260511112759.ts"],
|
|
4
|
+
"sourcesContent": ["import { Migration } from '@mikro-orm/migrations';\n\nexport class Migration20260511112759 extends Migration {\n\n override async up(): Promise<void> {\n this.addSql(`drop index if exists \"staff_time_projects_code_unique_idx\";`);\n this.addSql(`create unique index \"staff_time_projects_code_unique_idx\" on \"staff_time_projects\" (\"organization_id\", \"tenant_id\", \"code\") where \"deleted_at\" is null;`);\n\n this.addSql(`drop index if exists \"staff_time_project_members_unique_idx\";`);\n this.addSql(`create unique index \"staff_time_project_members_unique_idx\" on \"staff_time_project_members\" (\"organization_id\", \"tenant_id\", \"time_project_id\", \"staff_member_id\") where \"deleted_at\" is null;`);\n }\n\n override async down(): Promise<void> {\n this.addSql(`drop index if exists \"staff_time_project_members_unique_idx\";`);\n this.addSql(`create index \"staff_time_project_members_unique_idx\" on \"staff_time_project_members\" (\"organization_id\", \"tenant_id\", \"time_project_id\", \"staff_member_id\");`);\n\n this.addSql(`drop index if exists \"staff_time_projects_code_unique_idx\";`);\n this.addSql(`create index \"staff_time_projects_code_unique_idx\" on \"staff_time_projects\" (\"organization_id\", \"tenant_id\", \"code\");`);\n }\n\n}\n"],
|
|
5
|
+
"mappings": "AAAA,SAAS,iBAAiB;AAEnB,MAAM,gCAAgC,UAAU;AAAA,EAErD,MAAe,KAAoB;AACjC,SAAK,OAAO,6DAA6D;AACzE,SAAK,OAAO,yJAAyJ;AAErK,SAAK,OAAO,+DAA+D;AAC3E,SAAK,OAAO,gMAAgM;AAAA,EAC9M;AAAA,EAEA,MAAe,OAAsB;AACnC,SAAK,OAAO,+DAA+D;AAC3E,SAAK,OAAO,8JAA8J;AAE1K,SAAK,OAAO,6DAA6D;AACzE,SAAK,OAAO,uHAAuH;AAAA,EACrI;AAEF;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|