@open-mercato/core 0.7.0 → 0.7.1-develop.7102.1.b41f7e3e51
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 +1 -1
- package/dist/helpers/integration/api.js +13 -1
- package/dist/helpers/integration/api.js.map +2 -2
- package/dist/helpers/integration/communicationChannelsFixtures.js +19 -0
- package/dist/helpers/integration/communicationChannelsFixtures.js.map +2 -2
- package/dist/modules/api_keys/api/keys/route.js +1 -1
- package/dist/modules/api_keys/api/keys/route.js.map +2 -2
- package/dist/modules/api_keys/backend/api-keys/page.js +3 -1
- package/dist/modules/api_keys/backend/api-keys/page.js.map +2 -2
- package/dist/modules/api_keys/di.js +9 -0
- package/dist/modules/api_keys/di.js.map +7 -0
- package/dist/modules/api_keys/services/principalService.js +31 -0
- package/dist/modules/api_keys/services/principalService.js.map +7 -0
- package/dist/modules/attachments/api/route.js +2 -2
- package/dist/modules/attachments/api/route.js.map +2 -2
- package/dist/modules/attachments/components/AttachmentLibrary.js +2 -0
- package/dist/modules/attachments/components/AttachmentLibrary.js.map +2 -2
- package/dist/modules/attachments/di.js +11 -1
- package/dist/modules/attachments/di.js.map +2 -2
- package/dist/modules/attachments/index.js.map +1 -1
- package/dist/modules/attachments/lib/attachment-service.js +313 -0
- package/dist/modules/attachments/lib/attachment-service.js.map +7 -0
- package/dist/modules/attachments/lib/scoped-upload-service.js +15 -2
- package/dist/modules/attachments/lib/scoped-upload-service.js.map +2 -2
- package/dist/modules/attachments/lib/upload-limits.js +6 -2
- package/dist/modules/attachments/lib/upload-limits.js.map +2 -2
- package/dist/modules/audit_logs/backend/audit-logs/page.js +6 -0
- package/dist/modules/audit_logs/backend/audit-logs/page.js.map +2 -2
- package/dist/modules/audit_logs/lib/display-helpers.js +19 -11
- package/dist/modules/audit_logs/lib/display-helpers.js.map +2 -2
- package/dist/modules/audit_logs/services/actionLogService.js +57 -12
- package/dist/modules/audit_logs/services/actionLogService.js.map +3 -3
- package/dist/modules/auth/acl.js +30 -5
- package/dist/modules/auth/acl.js.map +2 -2
- package/dist/modules/auth/api/feature-check.js +8 -2
- package/dist/modules/auth/api/feature-check.js.map +2 -2
- package/dist/modules/auth/api/login.js +4 -1
- package/dist/modules/auth/api/login.js.map +2 -2
- package/dist/modules/auth/api/reset/validate.js +55 -0
- package/dist/modules/auth/api/reset/validate.js.map +7 -0
- package/dist/modules/auth/api/roles/acl/route.js +28 -33
- package/dist/modules/auth/api/roles/acl/route.js.map +2 -2
- package/dist/modules/auth/api/session/refresh.js +25 -1
- package/dist/modules/auth/api/session/refresh.js.map +2 -2
- package/dist/modules/auth/api/users/acl/route.js +96 -51
- package/dist/modules/auth/api/users/acl/route.js.map +2 -2
- package/dist/modules/auth/api/users/route.js +13 -5
- package/dist/modules/auth/api/users/route.js.map +2 -2
- package/dist/modules/auth/backend/roles/[id]/edit/page.meta.js +5 -1
- package/dist/modules/auth/backend/roles/[id]/edit/page.meta.js.map +2 -2
- package/dist/modules/auth/backend/roles/page.js +3 -1
- package/dist/modules/auth/backend/roles/page.js.map +2 -2
- package/dist/modules/auth/backend/users/[id]/edit/page.meta.js +5 -1
- package/dist/modules/auth/backend/users/[id]/edit/page.meta.js.map +2 -2
- package/dist/modules/auth/backend/users/page.js +2 -1
- package/dist/modules/auth/backend/users/page.js.map +2 -2
- package/dist/modules/auth/commands/acl.js +254 -0
- package/dist/modules/auth/commands/acl.js.map +7 -0
- package/dist/modules/auth/components/AclEditor.js +39 -30
- package/dist/modules/auth/components/AclEditor.js.map +2 -2
- package/dist/modules/auth/data/entities.js.map +2 -2
- package/dist/modules/auth/data/validators.js +5 -1
- package/dist/modules/auth/data/validators.js.map +2 -2
- package/dist/modules/auth/di.js +35 -9
- package/dist/modules/auth/di.js.map +2 -2
- package/dist/modules/auth/frontend/reset/[token]/page.js +46 -0
- package/dist/modules/auth/frontend/reset/[token]/page.js.map +2 -2
- package/dist/modules/auth/lib/grantChecks.js.map +2 -2
- package/dist/modules/auth/lib/userIdFilter.js +16 -0
- package/dist/modules/auth/lib/userIdFilter.js.map +7 -0
- package/dist/modules/auth/services/authService.js +16 -2
- package/dist/modules/auth/services/authService.js.map +2 -2
- package/dist/modules/auth/services/principalService.js +200 -0
- package/dist/modules/auth/services/principalService.js.map +7 -0
- package/dist/modules/auth/services/rbacService.js +67 -24
- package/dist/modules/auth/services/rbacService.js.map +3 -3
- package/dist/modules/auth/services/roleOrganizationScope.js +41 -0
- package/dist/modules/auth/services/roleOrganizationScope.js.map +7 -0
- package/dist/modules/business_rules/backend/logs/page.js +3 -1
- package/dist/modules/business_rules/backend/logs/page.js.map +2 -2
- package/dist/modules/business_rules/backend/rules/page.js +3 -1
- package/dist/modules/business_rules/backend/rules/page.js.map +2 -2
- package/dist/modules/business_rules/backend/sets/page.js +3 -1
- package/dist/modules/business_rules/backend/sets/page.js.map +2 -2
- package/dist/modules/business_rules/lib/expression-evaluator.js +9 -9
- package/dist/modules/business_rules/lib/expression-evaluator.js.map +2 -2
- package/dist/modules/business_rules/lib/rule-evaluator.js +10 -9
- package/dist/modules/business_rules/lib/rule-evaluator.js.map +2 -2
- package/dist/modules/catalog/ai-agents.js +1 -1
- package/dist/modules/catalog/ai-agents.js.map +1 -1
- package/dist/modules/catalog/ai-tools/merchandising-pack.js +2 -2
- package/dist/modules/catalog/ai-tools/merchandising-pack.js.map +2 -2
- package/dist/modules/catalog/backend/catalog/products/MerchandisingAssistantSheet.js +5 -2
- package/dist/modules/catalog/backend/catalog/products/MerchandisingAssistantSheet.js.map +2 -2
- package/dist/modules/catalog/components/categories/CategoriesDataTable.js +2 -0
- package/dist/modules/catalog/components/categories/CategoriesDataTable.js.map +2 -2
- package/dist/modules/catalog/components/products/ProductsDataTable.js +7 -1
- package/dist/modules/catalog/components/products/ProductsDataTable.js.map +2 -2
- package/dist/modules/catalog/widgets/injection/merchandising-assistant-trigger/widget.client.js +2 -0
- package/dist/modules/catalog/widgets/injection/merchandising-assistant-trigger/widget.client.js.map +2 -2
- package/dist/modules/communication_channels/api/post/channels/[id]/test-send/route.js +9 -1
- package/dist/modules/communication_channels/api/post/channels/[id]/test-send/route.js.map +2 -2
- package/dist/modules/communication_channels/api/post/test-seed/route.js +95 -10
- package/dist/modules/communication_channels/api/post/test-seed/route.js.map +2 -2
- package/dist/modules/communication_channels/backend/communication_channels/channels/page.js +3 -0
- package/dist/modules/communication_channels/backend/communication_channels/channels/page.js.map +2 -2
- package/dist/modules/communication_channels/commands/ingest-inbound-message.js +14 -1
- package/dist/modules/communication_channels/commands/ingest-inbound-message.js.map +2 -2
- package/dist/modules/communication_channels/di.js +7 -1
- package/dist/modules/communication_channels/di.js.map +2 -2
- package/dist/modules/communication_channels/lib/email-capabilities.js +4 -1
- package/dist/modules/communication_channels/lib/email-capabilities.js.map +2 -2
- package/dist/modules/communication_channels/lib/outbound-recipient.js +33 -0
- package/dist/modules/communication_channels/lib/outbound-recipient.js.map +7 -0
- package/dist/modules/communication_channels/lib/resolve-channel-type.js +51 -0
- package/dist/modules/communication_channels/lib/resolve-channel-type.js.map +7 -0
- package/dist/modules/communication_channels/lib/test-seed.js +41 -2
- package/dist/modules/communication_channels/lib/test-seed.js.map +2 -2
- package/dist/modules/configs/lib/system-status.js +9 -0
- package/dist/modules/configs/lib/system-status.js.map +2 -2
- package/dist/modules/currencies/backend/currencies/page.js +3 -1
- package/dist/modules/currencies/backend/currencies/page.js.map +2 -2
- package/dist/modules/currencies/backend/exchange-rates/page.js +3 -1
- package/dist/modules/currencies/backend/exchange-rates/page.js.map +2 -2
- package/dist/modules/currencies/services/rateFetchingService.js +6 -1
- package/dist/modules/currencies/services/rateFetchingService.js.map +2 -2
- package/dist/modules/customer_accounts/api/admin/domain-mappings.js +9 -0
- package/dist/modules/customer_accounts/api/admin/domain-mappings.js.map +2 -2
- package/dist/modules/customer_accounts/backend/customer_accounts/roles/page.js +3 -1
- package/dist/modules/customer_accounts/backend/customer_accounts/roles/page.js.map +2 -2
- package/dist/modules/customer_accounts/backend/customer_accounts/users/PortalUsersPageClient.js +3 -1
- package/dist/modules/customer_accounts/backend/customer_accounts/users/PortalUsersPageClient.js.map +2 -2
- package/dist/modules/customer_accounts/services/domainMappingService.js +10 -0
- package/dist/modules/customer_accounts/services/domainMappingService.js.map +2 -2
- package/dist/modules/customers/ai-tools/companies-pack.js +4 -1
- package/dist/modules/customers/ai-tools/companies-pack.js.map +2 -2
- package/dist/modules/customers/ai-tools/deal-analyzer-pack.js +13 -2
- package/dist/modules/customers/ai-tools/deal-analyzer-pack.js.map +2 -2
- package/dist/modules/customers/ai-tools/deals-pack.js +52 -6
- package/dist/modules/customers/ai-tools/deals-pack.js.map +2 -2
- package/dist/modules/customers/ai-tools/people-pack.js +4 -1
- package/dist/modules/customers/ai-tools/people-pack.js.map +2 -2
- package/dist/modules/customers/api/activities/route.js +48 -6
- package/dist/modules/customers/api/activities/route.js.map +2 -2
- package/dist/modules/customers/api/companies/[id]/people/route.js +20 -64
- package/dist/modules/customers/api/companies/[id]/people/route.js.map +2 -2
- package/dist/modules/customers/api/companies/[id]/route.js +17 -94
- package/dist/modules/customers/api/companies/[id]/route.js.map +2 -2
- package/dist/modules/customers/api/dashboard/widgets/customer-todos/route.js +8 -5
- package/dist/modules/customers/api/dashboard/widgets/customer-todos/route.js.map +2 -2
- package/dist/modules/customers/api/deals/[id]/companies/route.js +1 -1
- package/dist/modules/customers/api/deals/[id]/companies/route.js.map +2 -2
- package/dist/modules/customers/api/deals/[id]/people/route.js +1 -1
- package/dist/modules/customers/api/deals/[id]/people/route.js.map +2 -2
- package/dist/modules/customers/api/deals/[id]/route.js +8 -25
- package/dist/modules/customers/api/deals/[id]/route.js.map +2 -2
- package/dist/modules/customers/api/deals/[id]/stats/route.js +3 -22
- package/dist/modules/customers/api/deals/[id]/stats/route.js.map +2 -2
- package/dist/modules/customers/api/deals/aggregate/route.js +11 -4
- package/dist/modules/customers/api/deals/aggregate/route.js.map +2 -2
- package/dist/modules/customers/api/deals/map/route.js +2 -1
- package/dist/modules/customers/api/deals/map/route.js.map +2 -2
- package/dist/modules/customers/api/deals/route.js +38 -1
- package/dist/modules/customers/api/deals/route.js.map +2 -2
- package/dist/modules/customers/api/entity-roles-factory.js +4 -4
- package/dist/modules/customers/api/entity-roles-factory.js.map +2 -2
- package/dist/modules/customers/api/interactions/route.js +3 -1
- package/dist/modules/customers/api/interactions/route.js.map +2 -2
- package/dist/modules/customers/api/interactions/tasks/route.js +27 -4
- package/dist/modules/customers/api/interactions/tasks/route.js.map +2 -2
- package/dist/modules/customers/api/people/[id]/companies/[linkId]/route.js +4 -3
- package/dist/modules/customers/api/people/[id]/companies/[linkId]/route.js.map +2 -2
- package/dist/modules/customers/api/people/[id]/companies/context.js +1 -1
- package/dist/modules/customers/api/people/[id]/companies/context.js.map +2 -2
- package/dist/modules/customers/api/people/[id]/companies/enriched/route.js +1 -1
- package/dist/modules/customers/api/people/[id]/companies/enriched/route.js.map +2 -2
- package/dist/modules/customers/api/people/[id]/route.js +11 -10
- package/dist/modules/customers/api/people/[id]/route.js.map +2 -2
- package/dist/modules/customers/api/people/check-phone/route.js +51 -9
- package/dist/modules/customers/api/people/check-phone/route.js.map +2 -2
- package/dist/modules/customers/api/todos/route.js +30 -5
- package/dist/modules/customers/api/todos/route.js.map +2 -2
- package/dist/modules/customers/backend/customers/companies/page.js +4 -2
- package/dist/modules/customers/backend/customers/companies/page.js.map +2 -2
- package/dist/modules/customers/backend/customers/deals/[id]/page.js +6 -1
- package/dist/modules/customers/backend/customers/deals/[id]/page.js.map +2 -2
- package/dist/modules/customers/backend/customers/deals/page.js +5 -2
- package/dist/modules/customers/backend/customers/deals/page.js.map +2 -2
- package/dist/modules/customers/backend/customers/deals/pipeline/components/Lane.js +4 -13
- package/dist/modules/customers/backend/customers/deals/pipeline/components/Lane.js.map +2 -2
- package/dist/modules/customers/backend/customers/deals/pipeline/components/StatusFilterPopover.js +85 -14
- package/dist/modules/customers/backend/customers/deals/pipeline/components/StatusFilterPopover.js.map +2 -2
- package/dist/modules/customers/backend/customers/deals/pipeline/components/toneClasses.js +18 -0
- package/dist/modules/customers/backend/customers/deals/pipeline/components/toneClasses.js.map +7 -0
- package/dist/modules/customers/backend/customers/people/page.js +4 -2
- package/dist/modules/customers/backend/customers/people/page.js.map +2 -2
- package/dist/modules/customers/backend/hooks/useEmailDuplicateCheck.js +9 -3
- package/dist/modules/customers/backend/hooks/useEmailDuplicateCheck.js.map +2 -2
- package/dist/modules/customers/commands/deals.js +21 -34
- package/dist/modules/customers/commands/deals.js.map +2 -2
- package/dist/modules/customers/commands/interactions.js.map +1 -1
- package/dist/modules/customers/commands/personCompanyLinks.js +131 -2
- package/dist/modules/customers/commands/personCompanyLinks.js.map +2 -2
- package/dist/modules/customers/components/CustomerTodosTable.js +1 -0
- package/dist/modules/customers/components/CustomerTodosTable.js.map +2 -2
- package/dist/modules/customers/components/DealsKpiStrip.js +7 -6
- package/dist/modules/customers/components/DealsKpiStrip.js.map +2 -2
- package/dist/modules/customers/components/calendar/AgendaList.js +2 -2
- package/dist/modules/customers/components/calendar/AgendaList.js.map +2 -2
- package/dist/modules/customers/components/calendar/CalendarEventEditor.js +1 -1
- package/dist/modules/customers/components/calendar/CalendarEventEditor.js.map +2 -2
- package/dist/modules/customers/components/calendar/CalendarScreen.js +1 -1
- package/dist/modules/customers/components/calendar/CalendarScreen.js.map +2 -2
- package/dist/modules/customers/components/calendar/CalendarSettingsModal.js +1 -1
- package/dist/modules/customers/components/calendar/CalendarSettingsModal.js.map +2 -2
- package/dist/modules/customers/components/calendar/EventBlock.js +1 -1
- package/dist/modules/customers/components/calendar/EventBlock.js.map +2 -2
- package/dist/modules/customers/components/calendar/EventPeekPopover.js +3 -2
- package/dist/modules/customers/components/calendar/EventPeekPopover.js.map +2 -2
- package/dist/modules/customers/components/calendar/editor/PeopleField.js +40 -5
- package/dist/modules/customers/components/calendar/editor/PeopleField.js.map +2 -2
- package/dist/modules/customers/components/calendar/editor/hooks.js +2 -1
- package/dist/modules/customers/components/calendar/editor/hooks.js.map +2 -2
- package/dist/modules/customers/components/calendar/types.js +1 -1
- package/dist/modules/customers/components/calendar/types.js.map +2 -2
- package/dist/modules/customers/components/detail/CompanyKpiBar.js +5 -4
- package/dist/modules/customers/components/detail/CompanyKpiBar.js.map +2 -2
- package/dist/modules/customers/components/detail/CompanyPeopleSection.js +3 -1
- package/dist/modules/customers/components/detail/CompanyPeopleSection.js.map +2 -2
- package/dist/modules/customers/components/detail/DealForm.js +19 -7
- package/dist/modules/customers/components/detail/DealForm.js.map +2 -2
- package/dist/modules/customers/components/detail/DealsSection.js +6 -5
- package/dist/modules/customers/components/detail/DealsSection.js.map +2 -2
- package/dist/modules/customers/components/detail/EntityTagsDialog.js +35 -11
- package/dist/modules/customers/components/detail/EntityTagsDialog.js.map +2 -2
- package/dist/modules/customers/components/detail/PersonCompaniesSection.js +3 -1
- package/dist/modules/customers/components/detail/PersonCompaniesSection.js.map +2 -2
- package/dist/modules/customers/components/detail/hooks/usePersonTasks.js +19 -13
- package/dist/modules/customers/components/detail/hooks/usePersonTasks.js.map +2 -2
- package/dist/modules/customers/components/detail/schedule/ParticipantsField.js +4 -4
- package/dist/modules/customers/components/detail/schedule/ParticipantsField.js.map +2 -2
- package/dist/modules/customers/components/detail/schedule/useScheduleFormState.js +3 -3
- package/dist/modules/customers/components/detail/schedule/useScheduleFormState.js.map +2 -2
- package/dist/modules/customers/components/detail/utils.js +5 -5
- package/dist/modules/customers/components/detail/utils.js.map +2 -2
- package/dist/modules/customers/data/entities.js.map +1 -1
- package/dist/modules/customers/data/validators.js +32 -3
- package/dist/modules/customers/data/validators.js.map +2 -2
- package/dist/modules/customers/events.js +5 -0
- package/dist/modules/customers/events.js.map +2 -2
- package/dist/modules/customers/lib/calendar/conflicts.js +8 -2
- package/dist/modules/customers/lib/calendar/conflicts.js.map +2 -2
- package/dist/modules/customers/lib/calendar/editorPayload.js +3 -2
- package/dist/modules/customers/lib/calendar/editorPayload.js.map +2 -2
- package/dist/modules/customers/lib/calendar/mapItem.js +8 -3
- package/dist/modules/customers/lib/calendar/mapItem.js.map +2 -2
- package/dist/modules/customers/lib/calendar/participantIdentity.js +9 -0
- package/dist/modules/customers/lib/calendar/participantIdentity.js.map +7 -0
- package/dist/modules/customers/lib/closureStage.js +45 -0
- package/dist/modules/customers/lib/closureStage.js.map +7 -0
- package/dist/modules/customers/lib/dealStatus.js +30 -0
- package/dist/modules/customers/lib/dealStatus.js.map +2 -2
- package/dist/modules/customers/lib/detailReadAccess.js +12 -0
- package/dist/modules/customers/lib/detailReadAccess.js.map +7 -0
- package/dist/modules/customers/lib/findPeopleByAddresses.js +1 -0
- package/dist/modules/customers/lib/findPeopleByAddresses.js.map +2 -2
- package/dist/modules/customers/lib/personCompanies.js +100 -2
- package/dist/modules/customers/lib/personCompanies.js.map +2 -2
- package/dist/modules/customers/lib/todoCompatibility.js +12 -0
- package/dist/modules/customers/lib/todoCompatibility.js.map +2 -2
- package/dist/modules/dashboards/lib/widgetScope.js +6 -1
- package/dist/modules/dashboards/lib/widgetScope.js.map +2 -2
- package/dist/modules/data_sync/backend/data-sync/page.js +3 -1
- package/dist/modules/data_sync/backend/data-sync/page.js.map +2 -2
- package/dist/modules/data_sync/lib/abandoned-run.js +19 -0
- package/dist/modules/data_sync/lib/abandoned-run.js.map +7 -0
- package/dist/modules/data_sync/lib/sync-engine.js +72 -6
- package/dist/modules/data_sync/lib/sync-engine.js.map +2 -2
- package/dist/modules/data_sync/workers/sync-export.js +5 -1
- package/dist/modules/data_sync/workers/sync-export.js.map +2 -2
- package/dist/modules/data_sync/workers/sync-import.js +5 -1
- package/dist/modules/data_sync/workers/sync-import.js.map +2 -2
- package/dist/modules/devices/acl.js +9 -1
- package/dist/modules/devices/acl.js.map +2 -2
- package/dist/modules/devices/api/admin/devices/[id]/route.js +5 -32
- package/dist/modules/devices/api/admin/devices/[id]/route.js.map +2 -2
- package/dist/modules/devices/api/admin/devices/route.js +14 -1
- package/dist/modules/devices/api/admin/devices/route.js.map +2 -2
- package/dist/modules/devices/api/deviceList.js +99 -12
- package/dist/modules/devices/api/deviceList.js.map +2 -2
- package/dist/modules/devices/api/deviceSerialization.js +46 -0
- package/dist/modules/devices/api/deviceSerialization.js.map +7 -0
- package/dist/modules/devices/api/openapi.js +3 -1
- package/dist/modules/devices/api/openapi.js.map +2 -2
- package/dist/modules/devices/api/route.js +9 -1
- package/dist/modules/devices/api/route.js.map +2 -2
- package/dist/modules/devices/backend/devices/[id]/page.js +10 -26
- package/dist/modules/devices/backend/devices/[id]/page.js.map +2 -2
- package/dist/modules/devices/backend/devices/create/page.js +17 -1
- package/dist/modules/devices/backend/devices/create/page.js.map +2 -2
- package/dist/modules/devices/backend/devices/page.js +28 -34
- package/dist/modules/devices/backend/devices/page.js.map +2 -2
- package/dist/modules/devices/backend/devices/useDeviceUserLabels.js +34 -0
- package/dist/modules/devices/backend/devices/useDeviceUserLabels.js.map +7 -0
- package/dist/modules/devices/backend/devices/userOptions.js +52 -0
- package/dist/modules/devices/backend/devices/userOptions.js.map +7 -0
- package/dist/modules/devices/setup.js +6 -2
- package/dist/modules/devices/setup.js.map +2 -2
- package/dist/modules/directory/backend/directory/organizations/page.js +2 -1
- package/dist/modules/directory/backend/directory/organizations/page.js.map +2 -2
- package/dist/modules/directory/backend/directory/tenants/page.js +2 -1
- package/dist/modules/directory/backend/directory/tenants/page.js.map +2 -2
- package/dist/modules/directory/di.js +9 -0
- package/dist/modules/directory/di.js.map +2 -2
- package/dist/modules/directory/services/organizationHierarchyService.js +29 -0
- package/dist/modules/directory/services/organizationHierarchyService.js.map +7 -0
- package/dist/modules/directory/services/organizationScopeService.js +56 -0
- package/dist/modules/directory/services/organizationScopeService.js.map +7 -0
- package/dist/modules/directory/utils/organizationScope.js.map +2 -2
- package/dist/modules/entities/api/records.js +4 -2
- package/dist/modules/entities/api/records.js.map +2 -2
- package/dist/modules/entities/backend/entities/user/[entityId]/records/page.js +3 -1
- package/dist/modules/entities/backend/entities/user/[entityId]/records/page.js.map +2 -2
- package/dist/modules/eudr/api/plots/route.js +5 -1
- package/dist/modules/eudr/api/plots/route.js.map +2 -2
- package/dist/modules/eudr/backend/eudr/evidence-submissions/page.js +3 -0
- package/dist/modules/eudr/backend/eudr/evidence-submissions/page.js.map +2 -2
- package/dist/modules/eudr/backend/eudr/plots/page.js +3 -0
- package/dist/modules/eudr/backend/eudr/plots/page.js.map +2 -2
- package/dist/modules/eudr/backend/eudr/product-mappings/page.js +3 -0
- package/dist/modules/eudr/backend/eudr/product-mappings/page.js.map +2 -2
- package/dist/modules/eudr/backend/eudr/risk-assessments/page.js +3 -0
- package/dist/modules/eudr/backend/eudr/risk-assessments/page.js.map +2 -2
- package/dist/modules/eudr/backend/eudr/statements/page.js +3 -0
- package/dist/modules/eudr/backend/eudr/statements/page.js.map +2 -2
- package/dist/modules/eudr/commands/statements.js +0 -3
- package/dist/modules/eudr/commands/statements.js.map +2 -2
- package/dist/modules/eudr/data/validators.js +4 -1
- package/dist/modules/eudr/data/validators.js.map +2 -2
- package/dist/modules/feature_toggles/components/FeatureTogglesTable.js +1 -0
- package/dist/modules/feature_toggles/components/FeatureTogglesTable.js.map +2 -2
- package/dist/modules/feature_toggles/components/OverridesTable.js +1 -0
- package/dist/modules/feature_toggles/components/OverridesTable.js.map +2 -2
- package/dist/modules/feature_toggles/defaults.json +0 -8
- package/dist/modules/inbox_ops/backend/inbox-ops/log/page.js +3 -0
- package/dist/modules/inbox_ops/backend/inbox-ops/log/page.js.map +2 -2
- package/dist/modules/inbox_ops/backend/inbox-ops/page.js +3 -0
- package/dist/modules/inbox_ops/backend/inbox-ops/page.js.map +2 -2
- package/dist/modules/inbox_ops/lib/htmlToPlainText.js +1 -12
- package/dist/modules/inbox_ops/lib/htmlToPlainText.js.map +2 -2
- package/dist/modules/integrations/api/[id]/credentials/route.js +6 -1
- package/dist/modules/integrations/api/[id]/credentials/route.js.map +2 -2
- package/dist/modules/integrations/backend/integrations/[id]/page.js +38 -29
- package/dist/modules/integrations/backend/integrations/[id]/page.js.map +2 -2
- package/dist/modules/integrations/backend/integrations/bundle/[id]/page.js +36 -9
- package/dist/modules/integrations/backend/integrations/bundle/[id]/page.js.map +2 -2
- package/dist/modules/integrations/backend/integrations/credential-secret-fields.js +55 -0
- package/dist/modules/integrations/backend/integrations/credential-secret-fields.js.map +7 -0
- package/dist/modules/integrations/data/validators.js +11 -3
- package/dist/modules/integrations/data/validators.js.map +2 -2
- package/dist/modules/integrations/lib/credentials-masking.js +6 -2
- package/dist/modules/integrations/lib/credentials-masking.js.map +2 -2
- package/dist/modules/messages/api/[id]/route.js +29 -1
- package/dist/modules/messages/api/[id]/route.js.map +2 -2
- package/dist/modules/messages/api/openapi.js +17 -2
- package/dist/modules/messages/api/openapi.js.map +2 -2
- package/dist/modules/messages/api/route.js +17 -2
- package/dist/modules/messages/api/route.js.map +2 -2
- package/dist/modules/messages/components/MessagesInboxPageClient.js +7 -14
- package/dist/modules/messages/components/MessagesInboxPageClient.js.map +2 -2
- package/dist/modules/messages/components/inboxFilters.js +15 -0
- package/dist/modules/messages/components/inboxFilters.js.map +2 -2
- package/dist/modules/messages/components/message-detail/hooks/useMessageDetailsConversation.js +11 -1
- package/dist/modules/messages/components/message-detail/hooks/useMessageDetailsConversation.js.map +2 -2
- package/dist/modules/messages/components/message-detail/panels/MessageHeader.js +3 -1
- package/dist/modules/messages/components/message-detail/panels/MessageHeader.js.map +2 -2
- package/dist/modules/messages/components/message-detail/panels/thread-panel.js +2 -1
- package/dist/modules/messages/components/message-detail/panels/thread-panel.js.map +2 -2
- package/dist/modules/messages/components/messageListLabels.js +14 -2
- package/dist/modules/messages/components/messageListLabels.js.map +2 -2
- package/dist/modules/messages/data/validators.js +18 -4
- package/dist/modules/messages/data/validators.js.map +2 -2
- package/dist/modules/messages/lib/channel-sender-identity.js +26 -0
- package/dist/modules/messages/lib/channel-sender-identity.js.map +7 -0
- package/dist/modules/messages/lib/composeSourceChannelType.js +41 -0
- package/dist/modules/messages/lib/composeSourceChannelType.js.map +7 -0
- package/dist/modules/payment_gateways/api/webhook/[provider]/route.js +4 -6
- package/dist/modules/payment_gateways/api/webhook/[provider]/route.js.map +2 -2
- package/dist/modules/payment_gateways/backend/payment-gateways/page.js +3 -1
- package/dist/modules/payment_gateways/backend/payment-gateways/page.js.map +2 -2
- package/dist/modules/payment_gateways/lib/webhook-processor.js +7 -0
- package/dist/modules/payment_gateways/lib/webhook-processor.js.map +2 -2
- package/dist/modules/planner/backend/planner/availability-rulesets/page.js +3 -0
- package/dist/modules/planner/backend/planner/availability-rulesets/page.js.map +2 -2
- package/dist/modules/push_notifications/backend/push_notifications/page.js +3 -1
- package/dist/modules/push_notifications/backend/push_notifications/page.js.map +2 -2
- package/dist/modules/push_notifications/backend/push_notifications/send/page.js +1 -1
- package/dist/modules/push_notifications/backend/push_notifications/send/page.js.map +2 -2
- package/dist/modules/query_index/lib/engine.js +150 -51
- package/dist/modules/query_index/lib/engine.js.map +2 -2
- package/dist/modules/query_index/lib/search-entity-policy.js +14 -0
- package/dist/modules/query_index/lib/search-entity-policy.js.map +7 -0
- package/dist/modules/query_index/lib/search-tokens.js +79 -3
- package/dist/modules/query_index/lib/search-tokens.js.map +2 -2
- package/dist/modules/resources/backend/resources/resource-types/page.js +3 -1
- package/dist/modules/resources/backend/resources/resource-types/page.js.map +2 -2
- package/dist/modules/resources/backend/resources/resources/page.js +3 -1
- package/dist/modules/resources/backend/resources/resources/page.js.map +2 -2
- package/dist/modules/sales/backend/sales/channels/offers/page.js +3 -0
- package/dist/modules/sales/backend/sales/channels/offers/page.js.map +2 -2
- package/dist/modules/sales/backend/sales/channels/page.js +3 -0
- package/dist/modules/sales/backend/sales/channels/page.js.map +2 -2
- package/dist/modules/sales/backend/sales/documents/[id]/page.js +10 -8
- package/dist/modules/sales/backend/sales/documents/[id]/page.js.map +2 -2
- package/dist/modules/sales/commands/documents.js +79 -1
- package/dist/modules/sales/commands/documents.js.map +2 -2
- package/dist/modules/sales/components/PriceWithCurrency.js +7 -5
- package/dist/modules/sales/components/PriceWithCurrency.js.map +2 -2
- package/dist/modules/sales/components/channels/SalesChannelOffersPanel.js +3 -0
- package/dist/modules/sales/components/channels/SalesChannelOffersPanel.js.map +2 -2
- package/dist/modules/sales/components/documents/AdjustmentsSection.js +8 -6
- package/dist/modules/sales/components/documents/AdjustmentsSection.js.map +2 -2
- package/dist/modules/sales/components/documents/ItemsSection.js +51 -22
- package/dist/modules/sales/components/documents/ItemsSection.js.map +2 -2
- package/dist/modules/sales/components/documents/LineItemDialog.js +83 -18
- package/dist/modules/sales/components/documents/LineItemDialog.js.map +2 -2
- package/dist/modules/sales/components/documents/PaymentsSection.js +23 -9
- package/dist/modules/sales/components/documents/PaymentsSection.js.map +2 -2
- package/dist/modules/sales/components/documents/ReturnsSection.js +8 -6
- package/dist/modules/sales/components/documents/ReturnsSection.js.map +2 -2
- package/dist/modules/sales/components/documents/SalesDocumentsTable.js +68 -14
- package/dist/modules/sales/components/documents/SalesDocumentsTable.js.map +2 -2
- package/dist/modules/sales/components/documents/SalesOrderDraftLines.js +6 -5
- package/dist/modules/sales/components/documents/SalesOrderDraftLines.js.map +2 -2
- package/dist/modules/sales/components/documents/ShipmentDialog.js +5 -4
- package/dist/modules/sales/components/documents/ShipmentDialog.js.map +2 -2
- package/dist/modules/sales/components/documents/ShipmentsSection.js +8 -6
- package/dist/modules/sales/components/documents/ShipmentsSection.js.map +2 -2
- package/dist/modules/sales/components/documents/lineItemShipmentLock.js +54 -0
- package/dist/modules/sales/components/documents/lineItemShipmentLock.js.map +7 -0
- package/dist/modules/sales/components/documents/lineItemUtils.js +2 -2
- package/dist/modules/sales/components/documents/lineItemUtils.js.map +2 -2
- package/dist/modules/sales/data/entities.js +8 -2
- package/dist/modules/sales/data/entities.js.map +2 -2
- package/dist/modules/sales/extension-points.js +1 -0
- package/dist/modules/sales/extension-points.js.map +2 -2
- package/dist/modules/sales/lib/salesChannelsToggleSeed.js +33 -0
- package/dist/modules/sales/lib/salesChannelsToggleSeed.js.map +7 -0
- package/dist/modules/sales/migrations/Migration20260821120000_sales_notes_addresses_context_idx.js +32 -0
- package/dist/modules/sales/migrations/Migration20260821120000_sales_notes_addresses_context_idx.js.map +7 -0
- package/dist/modules/sales/setup.js +2 -0
- package/dist/modules/sales/setup.js.map +2 -2
- package/dist/modules/sales/widgets/injection/payment-gateway-status-column/widget.js +10 -2
- package/dist/modules/sales/widgets/injection/payment-gateway-status-column/widget.js.map +2 -2
- package/dist/modules/sales/widgets/injection-table.js +4 -7
- package/dist/modules/sales/widgets/injection-table.js.map +2 -2
- package/dist/modules/staff/backend/staff/leave-requests/page.js +3 -0
- package/dist/modules/staff/backend/staff/leave-requests/page.js.map +2 -2
- package/dist/modules/staff/backend/staff/my-leave-requests/page.js +3 -0
- package/dist/modules/staff/backend/staff/my-leave-requests/page.js.map +2 -2
- package/dist/modules/staff/backend/staff/team-members/page.js +3 -0
- package/dist/modules/staff/backend/staff/team-members/page.js.map +2 -2
- package/dist/modules/staff/backend/staff/team-roles/page.js +3 -0
- package/dist/modules/staff/backend/staff/team-roles/page.js.map +2 -2
- package/dist/modules/staff/backend/staff/teams/[id]/edit/page.js +3 -0
- package/dist/modules/staff/backend/staff/teams/[id]/edit/page.js.map +2 -2
- package/dist/modules/staff/backend/staff/teams/page.js +3 -0
- package/dist/modules/staff/backend/staff/teams/page.js.map +2 -2
- package/dist/modules/staff/backend/staff/timesheets/page.js +29 -18
- package/dist/modules/staff/backend/staff/timesheets/page.js.map +2 -2
- package/dist/modules/staff/backend/staff/timesheets/projects/page.js +3 -0
- package/dist/modules/staff/backend/staff/timesheets/projects/page.js.map +2 -2
- package/dist/modules/sync_excel/lib/adapters/customers.js +1 -0
- package/dist/modules/sync_excel/lib/adapters/customers.js.map +2 -2
- package/dist/modules/warranty_claims/api/assignees/route.js +3 -3
- package/dist/modules/warranty_claims/api/assignees/route.js.map +2 -2
- package/dist/modules/warranty_claims/api/portal/attachments/route.js +2 -2
- package/dist/modules/warranty_claims/api/portal/attachments/route.js.map +2 -2
- package/dist/modules/warranty_claims/api/portal/claims/route.js +12 -9
- package/dist/modules/warranty_claims/api/portal/claims/route.js.map +2 -2
- package/dist/modules/warranty_claims/backend/page.js +3 -0
- package/dist/modules/warranty_claims/backend/page.js.map +2 -2
- package/dist/modules/warranty_claims/backend/warranty_claims/registrations/page.js +3 -0
- package/dist/modules/warranty_claims/backend/warranty_claims/registrations/page.js.map +2 -2
- package/dist/modules/warranty_claims/backend/warranty_claims/troubleshooting-guides/page.js +3 -0
- package/dist/modules/warranty_claims/backend/warranty_claims/troubleshooting-guides/page.js.map +2 -2
- package/dist/modules/warranty_claims/backend/warranty_claims/vendor-policies/page.js +3 -0
- package/dist/modules/warranty_claims/backend/warranty_claims/vendor-policies/page.js.map +2 -2
- package/dist/modules/warranty_claims/frontend/[orgSlug]/portal/claims/page.js +3 -0
- package/dist/modules/warranty_claims/frontend/[orgSlug]/portal/claims/page.js.map +2 -2
- package/dist/modules/wms/api/warehouseSearch.js +21 -0
- package/dist/modules/wms/api/warehouseSearch.js.map +7 -0
- package/dist/modules/wms/api/warehouses/route.js +13 -9
- package/dist/modules/wms/api/warehouses/route.js.map +2 -2
- package/dist/modules/wms/api/zones/route.js +15 -2
- package/dist/modules/wms/api/zones/route.js.map +2 -2
- package/dist/modules/wms/commands/configuration.js +121 -9
- package/dist/modules/wms/commands/configuration.js.map +2 -2
- package/dist/modules/wms/commands/inventory-actions.js +3 -0
- package/dist/modules/wms/commands/inventory-actions.js.map +2 -2
- package/dist/modules/wms/commands/shared.js +9 -1
- package/dist/modules/wms/commands/shared.js.map +2 -2
- package/dist/modules/wms/components/backend/WarehouseEditDialog.js +158 -0
- package/dist/modules/wms/components/backend/WarehouseEditDialog.js.map +7 -0
- package/dist/modules/wms/components/backend/WmsConfigurationPage.js +76 -111
- package/dist/modules/wms/components/backend/WmsConfigurationPage.js.map +3 -3
- package/dist/modules/wms/components/backend/WmsInventoryConsolePage.js +1 -0
- package/dist/modules/wms/components/backend/WmsInventoryConsolePage.js.map +2 -2
- package/dist/modules/wms/components/backend/WmsLotsListPage.js +1 -0
- package/dist/modules/wms/components/backend/WmsLotsListPage.js.map +2 -2
- package/dist/modules/wms/components/backend/inventoryMutationLoaders.js +27 -20
- package/dist/modules/wms/components/backend/inventoryMutationLoaders.js.map +2 -2
- package/dist/modules/wms/components/backend/warehouseFormOptions.js +66 -0
- package/dist/modules/wms/components/backend/warehouseFormOptions.js.map +7 -0
- package/dist/modules/workflows/backend/definitions/page.js +3 -1
- package/dist/modules/workflows/backend/definitions/page.js.map +2 -2
- package/dist/modules/workflows/backend/events/page.js +3 -1
- package/dist/modules/workflows/backend/events/page.js.map +2 -2
- package/dist/modules/workflows/backend/instances/page.js +3 -1
- package/dist/modules/workflows/backend/instances/page.js.map +2 -2
- package/dist/modules/workflows/backend/tasks/page.js +3 -1
- package/dist/modules/workflows/backend/tasks/page.js.map +2 -2
- package/dist/modules/workflows/lib/activity-executor.js +4 -0
- package/dist/modules/workflows/lib/activity-executor.js.map +2 -2
- package/package.json +9 -10
- package/src/helpers/integration/api.ts +33 -1
- package/src/helpers/integration/communicationChannelsFixtures.ts +69 -1
- package/src/modules/api_keys/api/keys/route.ts +3 -1
- package/src/modules/api_keys/backend/api-keys/page.tsx +4 -1
- package/src/modules/api_keys/di.ts +7 -0
- package/src/modules/api_keys/services/principalService.ts +33 -0
- package/src/modules/attachments/AGENTS.md +15 -0
- package/src/modules/attachments/api/route.ts +2 -2
- package/src/modules/attachments/components/AttachmentLibrary.tsx +3 -0
- package/src/modules/attachments/di.ts +16 -0
- package/src/modules/attachments/i18n/de.json +5 -0
- package/src/modules/attachments/i18n/en.json +5 -0
- package/src/modules/attachments/i18n/es.json +5 -0
- package/src/modules/attachments/i18n/ko.json +5 -0
- package/src/modules/attachments/i18n/pl.json +5 -0
- package/src/modules/attachments/index.ts +10 -0
- package/src/modules/attachments/lib/attachment-service.ts +468 -0
- package/src/modules/attachments/lib/scoped-upload-service.ts +46 -0
- package/src/modules/attachments/lib/upload-limits.ts +6 -2
- package/src/modules/audit_logs/backend/audit-logs/page.tsx +8 -0
- package/src/modules/audit_logs/lib/display-helpers.tsx +42 -32
- package/src/modules/audit_logs/services/actionLogService.ts +74 -11
- package/src/modules/auth/acl.ts +30 -6
- package/src/modules/auth/api/feature-check.ts +10 -3
- package/src/modules/auth/api/login.ts +9 -1
- package/src/modules/auth/api/reset/validate.ts +57 -0
- package/src/modules/auth/api/roles/acl/route.ts +42 -39
- package/src/modules/auth/api/session/refresh.ts +32 -1
- package/src/modules/auth/api/users/acl/route.ts +177 -53
- package/src/modules/auth/api/users/route.ts +18 -5
- package/src/modules/auth/backend/roles/[id]/edit/page.meta.ts +5 -2
- package/src/modules/auth/backend/roles/page.tsx +4 -2
- package/src/modules/auth/backend/users/[id]/edit/page.meta.ts +5 -2
- package/src/modules/auth/backend/users/page.tsx +3 -2
- package/src/modules/auth/commands/acl.ts +495 -0
- package/src/modules/auth/components/AclEditor.tsx +63 -33
- package/src/modules/auth/data/entities.ts +4 -1
- package/src/modules/auth/data/validators.ts +5 -0
- package/src/modules/auth/di.ts +46 -16
- package/src/modules/auth/frontend/reset/[token]/page.tsx +74 -0
- package/src/modules/auth/i18n/de.json +389 -0
- package/src/modules/auth/i18n/en.json +389 -0
- package/src/modules/auth/i18n/es.json +389 -0
- package/src/modules/auth/i18n/ko.json +389 -0
- package/src/modules/auth/i18n/pl.json +391 -2
- package/src/modules/auth/lib/grantChecks.ts +6 -0
- package/src/modules/auth/lib/userIdFilter.ts +31 -0
- package/src/modules/auth/services/authService.ts +18 -2
- package/src/modules/auth/services/principalService.ts +266 -0
- package/src/modules/auth/services/rbacService.ts +110 -24
- package/src/modules/auth/services/roleOrganizationScope.ts +70 -0
- package/src/modules/business_rules/backend/logs/page.tsx +4 -1
- package/src/modules/business_rules/backend/rules/page.tsx +4 -1
- package/src/modules/business_rules/backend/sets/page.tsx +4 -1
- package/src/modules/business_rules/lib/expression-evaluator.ts +9 -9
- package/src/modules/business_rules/lib/rule-evaluator.ts +10 -9
- package/src/modules/catalog/ai-agents.ts +1 -1
- package/src/modules/catalog/ai-tools/merchandising-pack.ts +2 -2
- package/src/modules/catalog/backend/catalog/products/MerchandisingAssistantSheet.tsx +12 -5
- package/src/modules/catalog/components/categories/CategoriesDataTable.tsx +3 -0
- package/src/modules/catalog/components/products/ProductsDataTable.tsx +7 -0
- package/src/modules/catalog/i18n/de.json +1 -0
- package/src/modules/catalog/i18n/en.json +1 -0
- package/src/modules/catalog/i18n/es.json +1 -0
- package/src/modules/catalog/i18n/ko.json +1 -0
- package/src/modules/catalog/i18n/pl.json +1 -0
- package/src/modules/catalog/widgets/injection/merchandising-assistant-trigger/widget.client.tsx +4 -0
- package/src/modules/communication_channels/api/post/channels/[id]/test-send/route.ts +17 -1
- package/src/modules/communication_channels/api/post/test-seed/route.ts +155 -16
- package/src/modules/communication_channels/backend/communication_channels/channels/page.tsx +4 -0
- package/src/modules/communication_channels/commands/ingest-inbound-message.ts +38 -1
- package/src/modules/communication_channels/di.ts +7 -0
- package/src/modules/communication_channels/lib/adapter.ts +14 -0
- package/src/modules/communication_channels/lib/email-capabilities.ts +4 -0
- package/src/modules/communication_channels/lib/outbound-recipient.ts +71 -0
- package/src/modules/communication_channels/lib/resolve-channel-type.ts +99 -0
- package/src/modules/communication_channels/lib/test-seed.ts +64 -4
- package/src/modules/configs/i18n/de.json +2 -0
- package/src/modules/configs/i18n/en.json +2 -0
- package/src/modules/configs/i18n/es.json +2 -0
- package/src/modules/configs/i18n/ko.json +2 -0
- package/src/modules/configs/i18n/pl.json +2 -0
- package/src/modules/configs/lib/system-status.ts +9 -0
- package/src/modules/currencies/AGENTS.md +3 -0
- package/src/modules/currencies/backend/currencies/page.tsx +4 -1
- package/src/modules/currencies/backend/exchange-rates/page.tsx +4 -1
- package/src/modules/currencies/services/README.md +45 -0
- package/src/modules/currencies/services/rateFetchingService.ts +6 -1
- package/src/modules/customer_accounts/api/admin/domain-mappings.ts +7 -0
- package/src/modules/customer_accounts/backend/customer_accounts/roles/page.tsx +4 -1
- package/src/modules/customer_accounts/backend/customer_accounts/users/PortalUsersPageClient.tsx +4 -1
- package/src/modules/customer_accounts/services/domainMappingService.ts +10 -0
- package/src/modules/customers/ai-tools/companies-pack.ts +4 -1
- package/src/modules/customers/ai-tools/deal-analyzer-pack.ts +17 -2
- package/src/modules/customers/ai-tools/deals-pack.ts +66 -1
- package/src/modules/customers/ai-tools/people-pack.ts +4 -1
- package/src/modules/customers/api/activities/route.ts +45 -0
- package/src/modules/customers/api/companies/[id]/people/route.ts +24 -73
- package/src/modules/customers/api/companies/[id]/route.ts +24 -107
- package/src/modules/customers/api/dashboard/widgets/customer-todos/route.ts +16 -8
- package/src/modules/customers/api/deals/[id]/companies/route.ts +4 -1
- package/src/modules/customers/api/deals/[id]/people/route.ts +4 -1
- package/src/modules/customers/api/deals/[id]/route.ts +17 -28
- package/src/modules/customers/api/deals/[id]/stats/route.ts +10 -25
- package/src/modules/customers/api/deals/aggregate/route.ts +14 -4
- package/src/modules/customers/api/deals/map/route.ts +1 -0
- package/src/modules/customers/api/deals/route.ts +50 -1
- package/src/modules/customers/api/entity-roles-factory.ts +8 -4
- package/src/modules/customers/api/interactions/route.ts +8 -2
- package/src/modules/customers/api/interactions/tasks/route.ts +24 -1
- package/src/modules/customers/api/people/[id]/companies/[linkId]/route.ts +12 -4
- package/src/modules/customers/api/people/[id]/companies/context.ts +4 -1
- package/src/modules/customers/api/people/[id]/companies/enriched/route.ts +4 -1
- package/src/modules/customers/api/people/[id]/route.ts +16 -11
- package/src/modules/customers/api/people/check-phone/route.ts +75 -10
- package/src/modules/customers/api/todos/route.ts +27 -2
- package/src/modules/customers/backend/customers/companies/page.tsx +5 -2
- package/src/modules/customers/backend/customers/deals/[id]/page.tsx +7 -2
- package/src/modules/customers/backend/customers/deals/page.tsx +8 -2
- package/src/modules/customers/backend/customers/deals/pipeline/components/Lane.tsx +5 -14
- package/src/modules/customers/backend/customers/deals/pipeline/components/StatusFilterPopover.tsx +109 -27
- package/src/modules/customers/backend/customers/deals/pipeline/components/toneClasses.ts +21 -0
- package/src/modules/customers/backend/customers/people/page.tsx +5 -2
- package/src/modules/customers/backend/hooks/useEmailDuplicateCheck.ts +12 -4
- package/src/modules/customers/commands/deals.ts +34 -59
- package/src/modules/customers/commands/interactions.ts +1 -1
- package/src/modules/customers/commands/personCompanyLinks.ts +224 -8
- package/src/modules/customers/components/CustomerTodosTable.tsx +2 -0
- package/src/modules/customers/components/DealsKpiStrip.tsx +7 -7
- package/src/modules/customers/components/calendar/AgendaList.tsx +3 -3
- package/src/modules/customers/components/calendar/CalendarEventEditor.tsx +1 -1
- package/src/modules/customers/components/calendar/CalendarScreen.tsx +1 -1
- package/src/modules/customers/components/calendar/CalendarSettingsModal.tsx +1 -1
- package/src/modules/customers/components/calendar/EventBlock.tsx +2 -2
- package/src/modules/customers/components/calendar/EventPeekPopover.tsx +4 -2
- package/src/modules/customers/components/calendar/editor/PeopleField.tsx +61 -5
- package/src/modules/customers/components/calendar/editor/hooks.ts +7 -1
- package/src/modules/customers/components/calendar/types.ts +2 -2
- package/src/modules/customers/components/detail/CompanyKpiBar.tsx +5 -4
- package/src/modules/customers/components/detail/CompanyPeopleSection.tsx +8 -1
- package/src/modules/customers/components/detail/DealForm.tsx +22 -2
- package/src/modules/customers/components/detail/DealsSection.tsx +11 -5
- package/src/modules/customers/components/detail/EntityTagsDialog.tsx +58 -12
- package/src/modules/customers/components/detail/PersonCompaniesSection.tsx +8 -1
- package/src/modules/customers/components/detail/hooks/usePersonTasks.ts +23 -14
- package/src/modules/customers/components/detail/schedule/ParticipantsField.tsx +5 -5
- package/src/modules/customers/components/detail/schedule/useScheduleFormState.ts +5 -5
- package/src/modules/customers/components/detail/types.ts +1 -1
- package/src/modules/customers/components/detail/utils.ts +15 -5
- package/src/modules/customers/data/entities.ts +1 -1
- package/src/modules/customers/data/validators.ts +50 -9
- package/src/modules/customers/events.ts +5 -0
- package/src/modules/customers/i18n/de.json +9 -1
- package/src/modules/customers/i18n/en.json +9 -1
- package/src/modules/customers/i18n/es.json +9 -1
- package/src/modules/customers/i18n/ko.json +9 -1
- package/src/modules/customers/i18n/pl.json +9 -1
- package/src/modules/customers/lib/calendar/conflicts.ts +10 -2
- package/src/modules/customers/lib/calendar/editorPayload.ts +4 -3
- package/src/modules/customers/lib/calendar/mapItem.ts +8 -3
- package/src/modules/customers/lib/calendar/participantIdentity.ts +17 -0
- package/src/modules/customers/lib/closureStage.ts +76 -0
- package/src/modules/customers/lib/dealStatus.ts +42 -0
- package/src/modules/customers/lib/detailReadAccess.ts +35 -0
- package/src/modules/customers/lib/findPeopleByAddresses.ts +8 -6
- package/src/modules/customers/lib/personCompanies.ts +136 -1
- package/src/modules/customers/lib/todoCompatibility.ts +19 -1
- package/src/modules/dashboards/i18n/es.json +4 -4
- package/src/modules/dashboards/i18n/pl.json +7 -7
- package/src/modules/dashboards/lib/widgetScope.ts +6 -0
- package/src/modules/data_sync/AGENTS.md +1 -1
- package/src/modules/data_sync/backend/data-sync/page.tsx +4 -1
- package/src/modules/data_sync/lib/abandoned-run.ts +56 -0
- package/src/modules/data_sync/lib/adapter.ts +36 -0
- package/src/modules/data_sync/lib/sync-engine.ts +113 -5
- package/src/modules/data_sync/workers/sync-export.ts +4 -0
- package/src/modules/data_sync/workers/sync-import.ts +4 -0
- package/src/modules/devices/AGENTS.md +20 -1
- package/src/modules/devices/acl.ts +9 -1
- package/src/modules/devices/api/admin/devices/[id]/route.ts +5 -34
- package/src/modules/devices/api/admin/devices/route.ts +14 -1
- package/src/modules/devices/api/deviceList.ts +135 -11
- package/src/modules/devices/api/deviceSerialization.ts +50 -0
- package/src/modules/devices/api/openapi.ts +9 -1
- package/src/modules/devices/api/route.ts +9 -1
- package/src/modules/devices/backend/devices/[id]/page.tsx +18 -32
- package/src/modules/devices/backend/devices/create/page.tsx +17 -1
- package/src/modules/devices/backend/devices/page.tsx +44 -45
- package/src/modules/devices/backend/devices/useDeviceUserLabels.ts +45 -0
- package/src/modules/devices/backend/devices/userOptions.ts +99 -0
- package/src/modules/devices/i18n/de.json +3 -2
- package/src/modules/devices/i18n/en.json +3 -2
- package/src/modules/devices/i18n/es.json +3 -2
- package/src/modules/devices/i18n/ko.json +3 -2
- package/src/modules/devices/i18n/pl.json +3 -2
- package/src/modules/devices/setup.ts +6 -2
- package/src/modules/directory/backend/directory/organizations/page.tsx +3 -1
- package/src/modules/directory/backend/directory/tenants/page.tsx +3 -1
- package/src/modules/directory/di.ts +14 -2
- package/src/modules/directory/services/organizationHierarchyService.ts +34 -0
- package/src/modules/directory/services/organizationScopeService.ts +85 -0
- package/src/modules/directory/utils/organizationScope.ts +4 -15
- package/src/modules/entities/api/records.ts +2 -0
- package/src/modules/entities/backend/entities/user/[entityId]/records/page.tsx +4 -1
- package/src/modules/eudr/api/plots/route.ts +4 -0
- package/src/modules/eudr/backend/eudr/evidence-submissions/page.tsx +4 -0
- package/src/modules/eudr/backend/eudr/plots/page.tsx +4 -0
- package/src/modules/eudr/backend/eudr/product-mappings/page.tsx +4 -0
- package/src/modules/eudr/backend/eudr/risk-assessments/page.tsx +4 -0
- package/src/modules/eudr/backend/eudr/statements/page.tsx +4 -0
- package/src/modules/eudr/commands/statements.ts +0 -3
- package/src/modules/eudr/data/validators.ts +16 -1
- package/src/modules/feature_toggles/components/FeatureTogglesTable.tsx +2 -1
- package/src/modules/feature_toggles/components/OverridesTable.tsx +2 -1
- package/src/modules/feature_toggles/defaults.json +0 -8
- package/src/modules/inbox_ops/backend/inbox-ops/log/page.tsx +4 -0
- package/src/modules/inbox_ops/backend/inbox-ops/page.tsx +4 -0
- package/src/modules/inbox_ops/lib/htmlToPlainText.ts +1 -17
- package/src/modules/integrations/api/[id]/credentials/route.ts +6 -4
- package/src/modules/integrations/backend/integrations/[id]/page.tsx +61 -31
- package/src/modules/integrations/backend/integrations/bundle/[id]/page.tsx +44 -9
- package/src/modules/integrations/backend/integrations/credential-secret-fields.ts +84 -0
- package/src/modules/integrations/data/validators.ts +12 -2
- package/src/modules/integrations/i18n/de.json +1 -0
- package/src/modules/integrations/i18n/en.json +1 -0
- package/src/modules/integrations/i18n/es.json +1 -0
- package/src/modules/integrations/i18n/ko.json +1 -0
- package/src/modules/integrations/i18n/pl.json +1 -0
- package/src/modules/integrations/lib/credentials-masking.ts +10 -6
- package/src/modules/messages/api/[id]/route.ts +55 -1
- package/src/modules/messages/api/openapi.ts +20 -0
- package/src/modules/messages/api/route.ts +31 -2
- package/src/modules/messages/components/MessagesInboxPageClient.tsx +9 -16
- package/src/modules/messages/components/inboxFilters.ts +36 -0
- package/src/modules/messages/components/message-detail/hooks/useMessageDetailsConversation.ts +14 -1
- package/src/modules/messages/components/message-detail/panels/MessageHeader.tsx +3 -1
- package/src/modules/messages/components/message-detail/panels/thread-panel.tsx +2 -1
- package/src/modules/messages/components/message-detail/types.ts +3 -0
- package/src/modules/messages/components/messageListLabels.ts +52 -3
- package/src/modules/messages/data/validators.ts +43 -4
- package/src/modules/messages/lib/channel-sender-identity.ts +55 -0
- package/src/modules/messages/lib/composeSourceChannelType.ts +95 -0
- package/src/modules/payment_gateways/api/webhook/[provider]/route.ts +4 -6
- package/src/modules/payment_gateways/backend/payment-gateways/page.tsx +4 -1
- package/src/modules/payment_gateways/lib/webhook-processor.ts +11 -0
- package/src/modules/planner/backend/planner/availability-rulesets/page.tsx +4 -0
- package/src/modules/push_notifications/backend/push_notifications/page.tsx +4 -1
- package/src/modules/push_notifications/backend/push_notifications/send/page.tsx +4 -4
- package/src/modules/query_index/lib/engine.ts +249 -61
- package/src/modules/query_index/lib/search-entity-policy.ts +46 -0
- package/src/modules/query_index/lib/search-tokens.ts +135 -3
- package/src/modules/resources/backend/resources/resource-types/page.tsx +4 -1
- package/src/modules/resources/backend/resources/resources/page.tsx +4 -1
- package/src/modules/sales/backend/sales/channels/offers/page.tsx +4 -0
- package/src/modules/sales/backend/sales/channels/page.tsx +4 -0
- package/src/modules/sales/backend/sales/documents/[id]/page.tsx +14 -8
- package/src/modules/sales/commands/documents.ts +93 -0
- package/src/modules/sales/components/PriceWithCurrency.tsx +17 -5
- package/src/modules/sales/components/channels/SalesChannelOffersPanel.tsx +4 -0
- package/src/modules/sales/components/documents/AdjustmentsSection.tsx +6 -5
- package/src/modules/sales/components/documents/ItemsSection.tsx +56 -18
- package/src/modules/sales/components/documents/LineItemDialog.tsx +137 -20
- package/src/modules/sales/components/documents/PaymentsSection.tsx +20 -9
- package/src/modules/sales/components/documents/ReturnsSection.tsx +6 -5
- package/src/modules/sales/components/documents/SalesDocumentsTable.tsx +106 -14
- package/src/modules/sales/components/documents/SalesOrderDraftLines.tsx +6 -5
- package/src/modules/sales/components/documents/ShipmentDialog.tsx +5 -4
- package/src/modules/sales/components/documents/ShipmentsSection.tsx +6 -5
- package/src/modules/sales/components/documents/lineItemShipmentLock.ts +74 -0
- package/src/modules/sales/components/documents/lineItemUtils.ts +7 -2
- package/src/modules/sales/data/entities.ts +6 -0
- package/src/modules/sales/extension-points.ts +1 -0
- package/src/modules/sales/i18n/de.json +8 -0
- package/src/modules/sales/i18n/en.json +8 -0
- package/src/modules/sales/i18n/es.json +8 -0
- package/src/modules/sales/i18n/ko.json +8 -0
- package/src/modules/sales/i18n/pl.json +8 -0
- package/src/modules/sales/lib/salesChannelsToggleSeed.ts +42 -0
- package/src/modules/sales/migrations/.snapshot-open-mercato.json +60 -0
- package/src/modules/sales/migrations/Migration20260821120000_sales_notes_addresses_context_idx.ts +87 -0
- package/src/modules/sales/setup.ts +2 -0
- package/src/modules/sales/widgets/injection/payment-gateway-status-column/widget.ts +9 -1
- package/src/modules/sales/widgets/injection-table.ts +4 -7
- package/src/modules/staff/backend/staff/leave-requests/page.tsx +4 -0
- package/src/modules/staff/backend/staff/my-leave-requests/page.tsx +4 -0
- package/src/modules/staff/backend/staff/team-members/page.tsx +6 -0
- package/src/modules/staff/backend/staff/team-roles/page.tsx +4 -0
- package/src/modules/staff/backend/staff/teams/[id]/edit/page.tsx +4 -0
- package/src/modules/staff/backend/staff/teams/page.tsx +4 -0
- package/src/modules/staff/backend/staff/timesheets/page.tsx +12 -1
- package/src/modules/staff/backend/staff/timesheets/projects/page.tsx +4 -0
- package/src/modules/sync_excel/lib/adapters/customers.ts +5 -0
- package/src/modules/warranty_claims/api/assignees/route.ts +3 -3
- package/src/modules/warranty_claims/api/portal/attachments/route.ts +2 -2
- package/src/modules/warranty_claims/api/portal/claims/route.ts +12 -9
- package/src/modules/warranty_claims/backend/page.tsx +4 -0
- package/src/modules/warranty_claims/backend/warranty_claims/registrations/page.tsx +4 -0
- package/src/modules/warranty_claims/backend/warranty_claims/troubleshooting-guides/page.tsx +4 -0
- package/src/modules/warranty_claims/backend/warranty_claims/vendor-policies/page.tsx +4 -0
- package/src/modules/warranty_claims/frontend/[orgSlug]/portal/claims/page.tsx +4 -0
- package/src/modules/wms/api/warehouseSearch.ts +23 -0
- package/src/modules/wms/api/warehouses/route.ts +13 -9
- package/src/modules/wms/api/zones/route.ts +16 -0
- package/src/modules/wms/commands/configuration.ts +159 -10
- package/src/modules/wms/commands/inventory-actions.ts +3 -0
- package/src/modules/wms/commands/shared.ts +17 -0
- package/src/modules/wms/components/backend/WarehouseEditDialog.tsx +216 -0
- package/src/modules/wms/components/backend/WmsConfigurationPage.tsx +95 -141
- package/src/modules/wms/components/backend/WmsInventoryConsolePage.tsx +2 -0
- package/src/modules/wms/components/backend/WmsLotsListPage.tsx +2 -0
- package/src/modules/wms/components/backend/inventoryMutationLoaders.ts +36 -20
- package/src/modules/wms/components/backend/warehouseFormOptions.ts +72 -0
- package/src/modules/wms/i18n/de.json +2 -0
- package/src/modules/wms/i18n/en.json +2 -0
- package/src/modules/wms/i18n/es.json +2 -0
- package/src/modules/wms/i18n/ko.json +2 -0
- package/src/modules/wms/i18n/pl.json +2 -0
- package/src/modules/workflows/backend/definitions/page.tsx +4 -1
- package/src/modules/workflows/backend/events/page.tsx +4 -1
- package/src/modules/workflows/backend/instances/page.tsx +4 -1
- package/src/modules/workflows/backend/tasks/page.tsx +4 -1
- package/src/modules/workflows/lib/activity-executor.ts +9 -0
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use client"
|
|
2
2
|
|
|
3
3
|
import * as React from 'react'
|
|
4
|
+
import { z } from 'zod'
|
|
4
5
|
import { cn } from '@open-mercato/shared/lib/utils'
|
|
5
6
|
import { useT } from '@open-mercato/shared/lib/i18n/context'
|
|
6
7
|
import { Avatar } from '@open-mercato/ui/primitives/avatar'
|
|
@@ -11,6 +12,15 @@ import { composeAccessibleName } from '../../../lib/calendar/labels'
|
|
|
11
12
|
import { searchPeopleOptions, type PersonOption } from './lookups'
|
|
12
13
|
import { CONTROL_BORDER, DROPDOWN_PANEL_CLASS, PersonChip, UppercaseBadge, useDropdownDismiss } from './inputs'
|
|
13
14
|
|
|
15
|
+
// Mirrors the server-side guest rule in `interactionParticipantSchema`: a
|
|
16
|
+
// participant with no user record is addressable only by a routable email.
|
|
17
|
+
const guestEmailSchema = z.string().email().max(320)
|
|
18
|
+
|
|
19
|
+
function normalizeEmail(email: string | null | undefined): string | null {
|
|
20
|
+
const normalized = email?.trim().toLowerCase()
|
|
21
|
+
return normalized ? normalized : null
|
|
22
|
+
}
|
|
23
|
+
|
|
14
24
|
export function PeopleField({
|
|
15
25
|
mode,
|
|
16
26
|
placeholder,
|
|
@@ -63,12 +73,38 @@ export function PeopleField({
|
|
|
63
73
|
const selectedIds = new Set(value.map((participant) => participant.userId))
|
|
64
74
|
const visibleOptions = options.filter((option) => !selectedIds.has(option.userId))
|
|
65
75
|
|
|
76
|
+
// An external guest has no record to search for, so a typed address that
|
|
77
|
+
// matches nothing is the only way to invite one (#5115). Multi mode only —
|
|
78
|
+
// the single-mode field is the task assignee, which becomes `ownerUserId` and
|
|
79
|
+
// must resolve to a real staff user.
|
|
80
|
+
const typedEmail = normalizeEmail(query)
|
|
81
|
+
const selectedEmails = new Set(
|
|
82
|
+
value.map((participant) => normalizeEmail(participant.email)).filter((email): email is string => email !== null),
|
|
83
|
+
)
|
|
84
|
+
const guestEmail =
|
|
85
|
+
mode === 'multi' &&
|
|
86
|
+
typedEmail !== null &&
|
|
87
|
+
guestEmailSchema.safeParse(typedEmail).success &&
|
|
88
|
+
!selectedEmails.has(typedEmail) &&
|
|
89
|
+
!options.some((option) => normalizeEmail(option.email) === typedEmail)
|
|
90
|
+
? typedEmail
|
|
91
|
+
: null
|
|
92
|
+
const guestLabel = guestEmail
|
|
93
|
+
? t('customers.calendar.editor.addGuest', 'Invite {email} as a guest', { email: guestEmail })
|
|
94
|
+
: ''
|
|
95
|
+
|
|
66
96
|
const customerBadge = (
|
|
67
97
|
<UppercaseBadge className="bg-status-info-bg text-status-info-text">
|
|
68
98
|
{t('customers.calendar.editor.customerBadge', 'Customer')}
|
|
69
99
|
</UppercaseBadge>
|
|
70
100
|
)
|
|
71
101
|
|
|
102
|
+
const guestBadge = (
|
|
103
|
+
<UppercaseBadge className="bg-muted text-muted-foreground">
|
|
104
|
+
{t('customers.calendar.editor.guestBadge', 'Guest')}
|
|
105
|
+
</UppercaseBadge>
|
|
106
|
+
)
|
|
107
|
+
|
|
72
108
|
return (
|
|
73
109
|
<div
|
|
74
110
|
ref={rootRef}
|
|
@@ -84,12 +120,12 @@ export function PeopleField({
|
|
|
84
120
|
CONTROL_BORDER,
|
|
85
121
|
)}
|
|
86
122
|
>
|
|
87
|
-
{value.map((participant) => (
|
|
123
|
+
{value.map((participant, index) => (
|
|
88
124
|
<PersonChip
|
|
89
|
-
key={participant.userId}
|
|
125
|
+
key={participant.userId ?? participant.email ?? index}
|
|
90
126
|
name={participant.name}
|
|
91
|
-
badge={participant.isCustomer ? customerBadge : undefined}
|
|
92
|
-
onRemove={() => onChange(value.filter((
|
|
127
|
+
badge={participant.isCustomer ? customerBadge : participant.userId ? undefined : guestBadge}
|
|
128
|
+
onRemove={() => onChange(value.filter((_, entryIndex) => entryIndex !== index))}
|
|
93
129
|
removeLabel={t('customers.calendar.editor.removePerson', 'Remove {name}', { name: participant.name })}
|
|
94
130
|
/>
|
|
95
131
|
))}
|
|
@@ -113,11 +149,31 @@ export function PeopleField({
|
|
|
113
149
|
{t('customers.calendar.editor.searching', 'Searching…')}
|
|
114
150
|
</p>
|
|
115
151
|
) : null}
|
|
116
|
-
{!loading && visibleOptions.length === 0 ? (
|
|
152
|
+
{!loading && visibleOptions.length === 0 && !guestEmail ? (
|
|
117
153
|
<p className="px-2 py-3 text-center text-xs text-muted-foreground">
|
|
118
154
|
{t('customers.calendar.editor.noResults', 'No results')}
|
|
119
155
|
</p>
|
|
120
156
|
) : null}
|
|
157
|
+
{!loading && guestEmail ? (
|
|
158
|
+
<Button
|
|
159
|
+
type="button"
|
|
160
|
+
variant="ghost"
|
|
161
|
+
role="option"
|
|
162
|
+
aria-selected={false}
|
|
163
|
+
aria-label={guestLabel}
|
|
164
|
+
title={guestLabel}
|
|
165
|
+
onClick={() => {
|
|
166
|
+
const participant: EditorParticipant = { name: guestEmail, email: guestEmail, isCustomer: false }
|
|
167
|
+
onChange([...value, participant])
|
|
168
|
+
setQuery('')
|
|
169
|
+
}}
|
|
170
|
+
className="h-auto w-full justify-start gap-2 whitespace-normal px-2 py-1.5 text-left text-sm font-normal text-foreground"
|
|
171
|
+
>
|
|
172
|
+
<Avatar size="xs" label={guestEmail} />
|
|
173
|
+
<span className="min-w-0 flex-1 truncate">{guestLabel}</span>
|
|
174
|
+
{guestBadge}
|
|
175
|
+
</Button>
|
|
176
|
+
) : null}
|
|
121
177
|
{!loading
|
|
122
178
|
? visibleOptions.map((option) => (
|
|
123
179
|
<Button
|
|
@@ -8,6 +8,7 @@ import { computeDurationMinutes, type EditorFormState, type EditorKindConfig } f
|
|
|
8
8
|
import { findEditorConflictItems } from '../../../lib/calendar/conflicts'
|
|
9
9
|
import type { ConflictScope } from '../../../lib/calendar/preferences'
|
|
10
10
|
import { mapInteractionToCalendarItem } from '../../../lib/calendar/mapItem'
|
|
11
|
+
import { participantActorKey } from '../../../lib/calendar/participantIdentity'
|
|
11
12
|
import { expandOccurrences } from '../../../lib/calendar/recurrence'
|
|
12
13
|
import { getFetchWindow } from '../../../lib/calendar/range'
|
|
13
14
|
import type { CalendarItem } from '../types'
|
|
@@ -72,7 +73,12 @@ export function useConflictProbe(
|
|
|
72
73
|
): string | null {
|
|
73
74
|
const t = useT()
|
|
74
75
|
const [conflict, setConflict] = React.useState<string | null>(null)
|
|
75
|
-
|
|
76
|
+
// Keys on the canonical actor key, not the raw userId — an external guest has
|
|
77
|
+
// no userId, so a userId-only key never changes when guests are added or
|
|
78
|
+
// removed and the probe would keep reporting the previous attendee set.
|
|
79
|
+
const participantsKey = form.participants
|
|
80
|
+
.map((participant) => participantActorKey(participant) ?? '')
|
|
81
|
+
.join(',')
|
|
76
82
|
React.useEffect(() => {
|
|
77
83
|
if (!open || !form.date) {
|
|
78
84
|
setConflict(null)
|
|
@@ -18,7 +18,7 @@ export type CalendarRange = { from: Date; to: Date }
|
|
|
18
18
|
|
|
19
19
|
const calendarParticipantSchema = z
|
|
20
20
|
.object({
|
|
21
|
-
userId: z.string(),
|
|
21
|
+
userId: z.string().optional(),
|
|
22
22
|
name: z.string().optional(),
|
|
23
23
|
email: z.string().optional(),
|
|
24
24
|
})
|
|
@@ -49,7 +49,7 @@ export const calendarInteractionPayloadSchema = z
|
|
|
49
49
|
|
|
50
50
|
export type CalendarInteractionPayload = z.infer<typeof calendarInteractionPayloadSchema>
|
|
51
51
|
|
|
52
|
-
export type CalendarParticipant = { userId
|
|
52
|
+
export type CalendarParticipant = { userId?: string; name?: string; email?: string }
|
|
53
53
|
|
|
54
54
|
export interface CalendarItem {
|
|
55
55
|
id: string
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import * as React from 'react'
|
|
4
4
|
import { EyeOff } from 'lucide-react'
|
|
5
|
-
import { useT } from '@open-mercato/shared/lib/i18n/context'
|
|
5
|
+
import { useT, useLocale } from '@open-mercato/shared/lib/i18n/context'
|
|
6
6
|
import { KpiCard, type KpiTrend } from '@open-mercato/ui/backend/charts/KpiCard'
|
|
7
7
|
import { Button } from '@open-mercato/ui/primitives/button'
|
|
8
8
|
import { IconButton } from '@open-mercato/ui/primitives/icon-button'
|
|
@@ -67,6 +67,7 @@ type CompanyKpiBarProps = {
|
|
|
67
67
|
|
|
68
68
|
export function CompanyKpiBar({ data }: CompanyKpiBarProps) {
|
|
69
69
|
const t = useT()
|
|
70
|
+
const locale = useLocale()
|
|
70
71
|
|
|
71
72
|
const activeDeals = React.useMemo(() => getActiveDeals(data.deals), [data.deals])
|
|
72
73
|
const activeDealsValue = React.useMemo(
|
|
@@ -126,7 +127,7 @@ export function CompanyKpiBar({ data }: CompanyKpiBarProps) {
|
|
|
126
127
|
title: t('customers.companies.dashboard.kpi.activeDeals', 'ACTIVE DEALS'),
|
|
127
128
|
value: activeDealsValue,
|
|
128
129
|
trend: dealTrend,
|
|
129
|
-
formatValue: (v: number) => formatCurrency(v, dealCurrency),
|
|
130
|
+
formatValue: (v: number) => formatCurrency(v, dealCurrency, locale),
|
|
130
131
|
comparisonLabel: `${data.kpis?.activeDealsCount ?? activeDeals.length} ${(data.kpis?.activeDealsCount ?? activeDeals.length) === 1 ? 'pipeline' : 'pipelines'}`,
|
|
131
132
|
},
|
|
132
133
|
{
|
|
@@ -140,7 +141,7 @@ export function CompanyKpiBar({ data }: CompanyKpiBarProps) {
|
|
|
140
141
|
id: 'ltv',
|
|
141
142
|
title: t('customers.companies.dashboard.kpi.ltv', 'CUSTOMER VALUE (LTV)'),
|
|
142
143
|
value: ltvValue,
|
|
143
|
-
formatValue: ltvValue !== null ? (v: number) => formatCurrency(v, dealCurrency) : undefined,
|
|
144
|
+
formatValue: ltvValue !== null ? (v: number) => formatCurrency(v, dealCurrency, locale) : undefined,
|
|
144
145
|
comparisonLabel: ltvValue !== null
|
|
145
146
|
? t('customers.companies.dashboard.kpi.wonDeals', 'won deals total')
|
|
146
147
|
: t('customers.companies.dashboard.kpi.noWonDeals', 'No won deals'),
|
|
@@ -158,7 +159,7 @@ export function CompanyKpiBar({ data }: CompanyKpiBarProps) {
|
|
|
158
159
|
? `${data.kpis?.completedDealsCount ?? data.deals.filter((d) => isWonDealStatus(d.status)).length} ${t('customers.companies.dashboard.kpi.completedDeals', 'completed deals')}`
|
|
159
160
|
: t('customers.companies.dashboard.kpi.noInteractions', 'No interactions yet'),
|
|
160
161
|
},
|
|
161
|
-
], [t, activeDealsValue, dealTrend, dealCurrency, activeDeals.length, activityTrend, ltvValue, clientTenureYears, data.deals, data.interactions.length, data.kpis])
|
|
162
|
+
], [t, locale, activeDealsValue, dealTrend, dealCurrency, activeDeals.length, activityTrend, ltvValue, clientTenureYears, data.deals, data.interactions.length, data.kpis])
|
|
162
163
|
|
|
163
164
|
const visibleTiles = kpiTiles.filter((tile) => !hiddenTiles.has(tile.id))
|
|
164
165
|
|
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
import { useT } from '@open-mercato/shared/lib/i18n/context'
|
|
15
15
|
import { createTranslatorWithFallback } from '@open-mercato/shared/lib/i18n/translate'
|
|
16
16
|
import { useAppEvent } from '@open-mercato/ui/backend/injection/useAppEvent'
|
|
17
|
+
import type { AppEventPayload } from '@open-mercato/shared/modules/widgets/injection'
|
|
17
18
|
import type { SectionAction, TabEmptyStateConfig, Translator } from './types'
|
|
18
19
|
import { CreatePersonDialog } from './CreatePersonDialog'
|
|
19
20
|
import { PersonCard } from './PersonCard'
|
|
@@ -322,13 +323,19 @@ export function CompanyPeopleSection({
|
|
|
322
323
|
void loadVisiblePeople()
|
|
323
324
|
}, [loadVisiblePeople])
|
|
324
325
|
|
|
325
|
-
|
|
326
|
+
const reloadOnCompanyDetach = React.useCallback((event: AppEventPayload) => {
|
|
326
327
|
const payload = event.payload as { companyEntityId?: string | null } | null | undefined
|
|
327
328
|
if (payload && payload.companyEntityId === companyId) {
|
|
328
329
|
void loadVisiblePeople()
|
|
329
330
|
}
|
|
330
331
|
}, [companyId, loadVisiblePeople])
|
|
331
332
|
|
|
333
|
+
useAppEvent('customers.person_company_link.deleted', reloadOnCompanyDetach, [reloadOnCompanyDetach])
|
|
334
|
+
// Legacy profile-only assignments have no link row, so their detach broadcasts this sibling
|
|
335
|
+
// event instead of `customers.person_company_link.deleted` (#5114). Without it, other viewers
|
|
336
|
+
// of the same company keep listing a person who is already gone.
|
|
337
|
+
useAppEvent('customers.person.company_assignment.detached', reloadOnCompanyDetach, [reloadOnCompanyDetach])
|
|
338
|
+
|
|
332
339
|
React.useEffect(() => {
|
|
333
340
|
setListPage(1)
|
|
334
341
|
}, [searchQuery, sortMode])
|
|
@@ -102,6 +102,12 @@ type EntityMultiSelectProps = {
|
|
|
102
102
|
fetchByIds: (ids: string[]) => Promise<EntityOption[]>
|
|
103
103
|
disabled?: boolean
|
|
104
104
|
autoFocus?: boolean
|
|
105
|
+
/**
|
|
106
|
+
* Minimum trimmed query length before a lookup request is issued. Defaults to
|
|
107
|
+
* `1`, so a blank input never queries the address book (issue #5118). Set `0`
|
|
108
|
+
* to opt back into prefetching an unfiltered first page on mount.
|
|
109
|
+
*/
|
|
110
|
+
minQueryLength?: number
|
|
105
111
|
}
|
|
106
112
|
|
|
107
113
|
const DEAL_ENTITY_IDS = [E.customers.customer_deal]
|
|
@@ -353,6 +359,7 @@ function EntityMultiSelect({
|
|
|
353
359
|
fetchByIds,
|
|
354
360
|
disabled = false,
|
|
355
361
|
autoFocus = false,
|
|
362
|
+
minQueryLength = 1,
|
|
356
363
|
}: EntityMultiSelectProps) {
|
|
357
364
|
const [input, setInput] = React.useState('')
|
|
358
365
|
const [suggestions, setSuggestions] = React.useState<EntityOption[]>([])
|
|
@@ -401,11 +408,18 @@ function EntityMultiSelect({
|
|
|
401
408
|
setLoading(false)
|
|
402
409
|
return
|
|
403
410
|
}
|
|
411
|
+
const term = input.trim()
|
|
412
|
+
if (term.length < minQueryLength) {
|
|
413
|
+
setSuggestions([])
|
|
414
|
+
setLoading(false)
|
|
415
|
+
setError(null)
|
|
416
|
+
return
|
|
417
|
+
}
|
|
404
418
|
let cancelled = false
|
|
405
419
|
const handler = window.setTimeout(async () => {
|
|
406
420
|
setLoading(true)
|
|
407
421
|
try {
|
|
408
|
-
const results = await search(
|
|
422
|
+
const results = await search(term)
|
|
409
423
|
if (cancelled) return
|
|
410
424
|
setSuggestions(results)
|
|
411
425
|
setCache((prev) => {
|
|
@@ -429,7 +443,7 @@ function EntityMultiSelect({
|
|
|
429
443
|
cancelled = true
|
|
430
444
|
window.clearTimeout(handler)
|
|
431
445
|
}
|
|
432
|
-
}, [disabled, errorLabel, input, search])
|
|
446
|
+
}, [disabled, errorLabel, input, minQueryLength, search])
|
|
433
447
|
|
|
434
448
|
const filteredSuggestions = React.useMemo(
|
|
435
449
|
() => suggestions.filter((option) => !normalizedValue.includes(option.id)),
|
|
@@ -660,12 +674,14 @@ export function DealPeopleSelector({
|
|
|
660
674
|
options = [],
|
|
661
675
|
disabled = false,
|
|
662
676
|
autoFocus = false,
|
|
677
|
+
minQueryLength,
|
|
663
678
|
}: {
|
|
664
679
|
value: string[]
|
|
665
680
|
onChange: (next: string[]) => void
|
|
666
681
|
options?: EntityOption[]
|
|
667
682
|
disabled?: boolean
|
|
668
683
|
autoFocus?: boolean
|
|
684
|
+
minQueryLength?: number
|
|
669
685
|
}) {
|
|
670
686
|
const t = useT()
|
|
671
687
|
const { searchPeople, fetchPeopleByIds } = useDealAssociationLookups()
|
|
@@ -685,6 +701,7 @@ export function DealPeopleSelector({
|
|
|
685
701
|
fetchByIds={fetchPeopleByIds}
|
|
686
702
|
disabled={disabled}
|
|
687
703
|
autoFocus={autoFocus}
|
|
704
|
+
minQueryLength={minQueryLength}
|
|
688
705
|
/>
|
|
689
706
|
)
|
|
690
707
|
}
|
|
@@ -694,11 +711,13 @@ export function DealCompaniesSelector({
|
|
|
694
711
|
onChange,
|
|
695
712
|
options = [],
|
|
696
713
|
disabled = false,
|
|
714
|
+
minQueryLength,
|
|
697
715
|
}: {
|
|
698
716
|
value: string[]
|
|
699
717
|
onChange: (next: string[]) => void
|
|
700
718
|
options?: EntityOption[]
|
|
701
719
|
disabled?: boolean
|
|
720
|
+
minQueryLength?: number
|
|
702
721
|
}) {
|
|
703
722
|
const t = useT()
|
|
704
723
|
const { searchCompanies, fetchCompaniesByIds } = useDealAssociationLookups()
|
|
@@ -717,6 +736,7 @@ export function DealCompaniesSelector({
|
|
|
717
736
|
search={searchCompanies}
|
|
718
737
|
fetchByIds={fetchCompaniesByIds}
|
|
719
738
|
disabled={disabled}
|
|
739
|
+
minQueryLength={minQueryLength}
|
|
720
740
|
/>
|
|
721
741
|
)
|
|
722
742
|
}
|
|
@@ -12,7 +12,7 @@ import { LinkEntityDialog } from '../linking/LinkEntityDialog'
|
|
|
12
12
|
import { createDealLinkAdapter } from '../linking/adapters/dealAdapter'
|
|
13
13
|
import { LoadingMessage, TabEmptyState } from '@open-mercato/ui/backend/detail'
|
|
14
14
|
import { useOrganizationScopeVersion } from '@open-mercato/shared/lib/frontend/useOrganizationScope'
|
|
15
|
-
import { useT } from '@open-mercato/shared/lib/i18n/context'
|
|
15
|
+
import { useT, useLocale } from '@open-mercato/shared/lib/i18n/context'
|
|
16
16
|
import { hasMoreFromPage } from '@open-mercato/shared/lib/pagination/load-more'
|
|
17
17
|
import { useConfirmDialog } from '@open-mercato/ui/backend/confirm-dialog'
|
|
18
18
|
import { E } from '#generated/entities.ids.generated'
|
|
@@ -275,9 +275,14 @@ function normalizeDeal(deal: Partial<DealSummary> & { id: string; title?: string
|
|
|
275
275
|
}
|
|
276
276
|
}
|
|
277
277
|
|
|
278
|
-
function formatValueLabel(
|
|
278
|
+
function formatValueLabel(
|
|
279
|
+
amount: number | null,
|
|
280
|
+
currency: string | null,
|
|
281
|
+
emptyLabel: string,
|
|
282
|
+
locale?: string,
|
|
283
|
+
): string {
|
|
279
284
|
if (typeof amount === 'number') {
|
|
280
|
-
const formatter = new Intl.NumberFormat(
|
|
285
|
+
const formatter = new Intl.NumberFormat(locale, {
|
|
281
286
|
style: currency ? 'currency' : 'decimal',
|
|
282
287
|
currency: currency ?? undefined,
|
|
283
288
|
maximumFractionDigits: 2,
|
|
@@ -317,6 +322,7 @@ export function DealsSection({
|
|
|
317
322
|
runGuardedMutation,
|
|
318
323
|
}: DealsSectionProps) {
|
|
319
324
|
const tHook = useT()
|
|
325
|
+
const locale = useLocale()
|
|
320
326
|
const { confirm, ConfirmDialogElement } = useConfirmDialog()
|
|
321
327
|
const fallbackTranslator = React.useMemo<Translator>(() => createTranslatorWithFallback(tHook), [tHook])
|
|
322
328
|
const t: Translator = React.useMemo(() => translator ?? fallbackTranslator, [translator, fallbackTranslator])
|
|
@@ -963,8 +969,8 @@ export function DealsSection({
|
|
|
963
969
|
) : null}
|
|
964
970
|
<div className="space-y-4">
|
|
965
971
|
{sortedDeals.map((deal) => {
|
|
966
|
-
const valueLabel = formatValueLabel(deal.valueAmount, deal.valueCurrency ?? null, emptyLabel)
|
|
967
|
-
const expectedLabel = deal.expectedCloseAt ? formatDate(deal.expectedCloseAt) ?? emptyLabel : emptyLabel
|
|
972
|
+
const valueLabel = formatValueLabel(deal.valueAmount, deal.valueCurrency ?? null, emptyLabel, locale)
|
|
973
|
+
const expectedLabel = deal.expectedCloseAt ? formatDate(deal.expectedCloseAt, locale) ?? emptyLabel : emptyLabel
|
|
968
974
|
const probabilityLabel =
|
|
969
975
|
typeof deal.probability === 'number' ? `${deal.probability}%` : emptyLabel
|
|
970
976
|
const isUnlinkPending = pendingAction?.kind === 'remove' && pendingAction.id === deal.id
|
|
@@ -6,6 +6,7 @@ import { EmptyState } from '@open-mercato/ui/primitives/empty-state'
|
|
|
6
6
|
import { VisuallyHidden } from '@radix-ui/react-visually-hidden'
|
|
7
7
|
import { useT } from '@open-mercato/shared/lib/i18n/context'
|
|
8
8
|
import { cn, slugifyTagLabel } from '@open-mercato/shared/lib/utils'
|
|
9
|
+
import { hasMoreFromPage } from '@open-mercato/shared/lib/pagination/load-more'
|
|
9
10
|
import { apiCall, apiCallOrThrow, readApiResultOrThrow } from '@open-mercato/ui/backend/utils/apiCall'
|
|
10
11
|
import { flash } from '@open-mercato/ui/backend/FlashMessages'
|
|
11
12
|
import { useGuardedMutation } from '@open-mercato/ui/backend/injection/useGuardedMutation'
|
|
@@ -388,8 +389,19 @@ export function EntityTagsDialog({
|
|
|
388
389
|
const [creatingKind, setCreatingKind] = React.useState<string | null>(null)
|
|
389
390
|
const [manageTagsOpen, setManageTagsOpen] = React.useState(false)
|
|
390
391
|
const [activeCategoryPage, setActiveCategoryPage] = React.useState(1)
|
|
391
|
-
|
|
392
|
+
// Short-page termination instead of `page < totalPages` — see
|
|
393
|
+
// `hasMoreFromPage`. Like the page number it belongs to whichever category is
|
|
394
|
+
// active: the fetch effect below rewrites it on every category, search and
|
|
395
|
+
// page change, and the reset effect clears it alongside the page so a
|
|
396
|
+
// category with more entries never leaves the affordance behind on one
|
|
397
|
+
// without.
|
|
398
|
+
const [activeCategoryHasMore, setActiveCategoryHasMore] = React.useState(false)
|
|
392
399
|
const [activeCategoryLoading, setActiveCategoryLoading] = React.useState(false)
|
|
400
|
+
// A transport failure is not an end-of-list signal: it leaves the affordance
|
|
401
|
+
// in place and turns the next click into a retry of the page that failed,
|
|
402
|
+
// rather than advancing past it.
|
|
403
|
+
const [activeCategoryLoadFailed, setActiveCategoryLoadFailed] = React.useState(false)
|
|
404
|
+
const [activeCategoryReloadToken, setActiveCategoryReloadToken] = React.useState(0)
|
|
393
405
|
const creationInFlightRef = React.useRef<string | null>(null)
|
|
394
406
|
const mutationContextId = React.useMemo(
|
|
395
407
|
() => `customer-tags:${entityType}:${entityId}`,
|
|
@@ -713,12 +725,15 @@ export function EntityTagsDialog({
|
|
|
713
725
|
React.useEffect(() => {
|
|
714
726
|
if (!open) return
|
|
715
727
|
setActiveCategoryPage(1)
|
|
728
|
+
setActiveCategoryHasMore(false)
|
|
729
|
+
setActiveCategoryLoadFailed(false)
|
|
716
730
|
}, [activeCategoryKind, open, searchValue])
|
|
717
731
|
|
|
718
732
|
React.useEffect(() => {
|
|
719
733
|
if (!open || !activeCategoryKindValue || (activeCategorySource !== 'tags' && activeCategorySource !== 'labels')) {
|
|
720
734
|
setActiveCategoryLoading(false)
|
|
721
|
-
|
|
735
|
+
setActiveCategoryHasMore(false)
|
|
736
|
+
setActiveCategoryLoadFailed(false)
|
|
722
737
|
return
|
|
723
738
|
}
|
|
724
739
|
|
|
@@ -752,16 +767,36 @@ export function EntityTagsDialog({
|
|
|
752
767
|
}))
|
|
753
768
|
|
|
754
769
|
setActiveCategoryLoading(true)
|
|
755
|
-
void apiCall<{ items?: Array<DictEntry | LabelItem>;
|
|
770
|
+
void apiCall<{ items?: Array<DictEntry | LabelItem>; page?: number }>(endpoint, {
|
|
756
771
|
cache: 'no-store',
|
|
757
772
|
headers: { 'x-om-unauthorized-redirect': '0' },
|
|
758
773
|
})
|
|
759
774
|
.then((response) => {
|
|
760
|
-
if (
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
775
|
+
if (cancelled) return
|
|
776
|
+
if (!response.ok) {
|
|
777
|
+
setActiveCategoryLoadFailed(true)
|
|
778
|
+
return
|
|
779
|
+
}
|
|
780
|
+
setActiveCategoryLoadFailed(false)
|
|
781
|
+
const servedEntries = Array.isArray(response.result?.items) ? response.result.items : []
|
|
782
|
+
const fetchedEntries = mapEntries(servedEntries)
|
|
783
|
+
// The two sources paginate differently. `/api/customers/tags` is a
|
|
784
|
+
// query-engine list, so a page past the end comes back empty and the
|
|
785
|
+
// served count alone terminates the sequence. `/api/customers/labels`
|
|
786
|
+
// clamps the requested page to the last one and re-serves it in full
|
|
787
|
+
// forever, so short-page termination needs the second half of the
|
|
788
|
+
// helper's obligation 2: take an echoed page below the one asked for as
|
|
789
|
+
// the end of the list. Same guard as `AttachmentsSection`, whose
|
|
790
|
+
// endpoint clamps the same way.
|
|
791
|
+
const returnedPage =
|
|
792
|
+
typeof response.result?.page === 'number' ? response.result.page : activeCategoryPage
|
|
793
|
+
const servedRequestedPage = returnedPage >= activeCategoryPage
|
|
794
|
+
// Measured on what the endpoint served, before `mergeOptions` folds the
|
|
795
|
+
// page into the entries already on screen.
|
|
796
|
+
setActiveCategoryHasMore(
|
|
797
|
+
servedRequestedPage && hasMoreFromPage(servedEntries.length, REMOTE_CATEGORY_PAGE_SIZE),
|
|
764
798
|
)
|
|
799
|
+
if (!servedRequestedPage) return
|
|
765
800
|
updateCategoryEntries(activeCategoryKindValue, (currentEntries) =>
|
|
766
801
|
activeCategoryPage <= 1
|
|
767
802
|
? mergeOptions(seedEntries, fetchedEntries)
|
|
@@ -770,8 +805,10 @@ export function EntityTagsDialog({
|
|
|
770
805
|
})
|
|
771
806
|
.catch(() => {
|
|
772
807
|
if (cancelled) return
|
|
773
|
-
|
|
774
|
-
|
|
808
|
+
setActiveCategoryLoadFailed(true)
|
|
809
|
+
if (activeCategoryPage <= 1) {
|
|
810
|
+
updateCategoryEntries(activeCategoryKindValue, () => seedEntries)
|
|
811
|
+
}
|
|
775
812
|
})
|
|
776
813
|
.finally(() => {
|
|
777
814
|
if (!cancelled) {
|
|
@@ -785,6 +822,7 @@ export function EntityTagsDialog({
|
|
|
785
822
|
}, [
|
|
786
823
|
activeCategoryKindValue,
|
|
787
824
|
activeCategoryPage,
|
|
825
|
+
activeCategoryReloadToken,
|
|
788
826
|
activeCategorySource,
|
|
789
827
|
entityId,
|
|
790
828
|
entityOrganizationId,
|
|
@@ -1250,15 +1288,23 @@ export function EntityTagsDialog({
|
|
|
1250
1288
|
{t('customers.personTags.loading', 'Loading...')}
|
|
1251
1289
|
</div>
|
|
1252
1290
|
) : null}
|
|
1253
|
-
{(activeCategory.source === 'tags' || activeCategory.source === 'labels') &&
|
|
1291
|
+
{(activeCategory.source === 'tags' || activeCategory.source === 'labels') && activeCategoryHasMore ? (
|
|
1254
1292
|
<Button
|
|
1255
1293
|
type="button"
|
|
1256
1294
|
variant="outline"
|
|
1257
1295
|
size="sm"
|
|
1258
1296
|
className="rounded-lg px-3 text-xs"
|
|
1259
|
-
onClick={() =>
|
|
1297
|
+
onClick={() => {
|
|
1298
|
+
if (activeCategoryLoadFailed) {
|
|
1299
|
+
setActiveCategoryReloadToken((current) => current + 1)
|
|
1300
|
+
return
|
|
1301
|
+
}
|
|
1302
|
+
setActiveCategoryPage((current) => current + 1)
|
|
1303
|
+
}}
|
|
1260
1304
|
>
|
|
1261
|
-
{
|
|
1305
|
+
{activeCategoryLoadFailed
|
|
1306
|
+
? t('customers.personTags.retry', 'Retry')
|
|
1307
|
+
: t('customers.activities.loadMore', 'Load more')}
|
|
1262
1308
|
</Button>
|
|
1263
1309
|
) : null}
|
|
1264
1310
|
</div>
|
|
@@ -10,6 +10,7 @@ import { Button } from '@open-mercato/ui/primitives/button'
|
|
|
10
10
|
import { Input } from '@open-mercato/ui/primitives/input'
|
|
11
11
|
import { useConfirmDialog } from '@open-mercato/ui/backend/confirm-dialog'
|
|
12
12
|
import { useAppEvent } from '@open-mercato/ui/backend/injection/useAppEvent'
|
|
13
|
+
import type { AppEventPayload } from '@open-mercato/shared/modules/widgets/injection'
|
|
13
14
|
import { CompanyCard, type EnrichedCompanyData } from './CompanyCard'
|
|
14
15
|
import { useCustomerDictionary } from './hooks/useCustomerDictionary'
|
|
15
16
|
import { LinkEntityDialog, type LinkEntityOption } from '../linking/LinkEntityDialog'
|
|
@@ -369,13 +370,19 @@ export function PersonCompaniesSection({
|
|
|
369
370
|
[_personName, confirm, loadData, onChanged, personId, runWriteMutation, t, unlinkingId],
|
|
370
371
|
)
|
|
371
372
|
|
|
372
|
-
|
|
373
|
+
const reloadOnPersonDetach = React.useCallback((event: AppEventPayload) => {
|
|
373
374
|
const payload = event.payload as { personEntityId?: string | null } | null | undefined
|
|
374
375
|
if (payload && payload.personEntityId === personId) {
|
|
375
376
|
void loadData({ showLoading: false })
|
|
376
377
|
}
|
|
377
378
|
}, [personId, loadData])
|
|
378
379
|
|
|
380
|
+
useAppEvent('customers.person_company_link.deleted', reloadOnPersonDetach, [reloadOnPersonDetach])
|
|
381
|
+
// Legacy profile-only assignments have no link row, so their detach broadcasts this sibling
|
|
382
|
+
// event instead of `customers.person_company_link.deleted` (#5114). Without it, other viewers
|
|
383
|
+
// of the same person keep listing a company that is already detached.
|
|
384
|
+
useAppEvent('customers.person.company_assignment.detached', reloadOnPersonDetach, [reloadOnPersonDetach])
|
|
385
|
+
|
|
379
386
|
return (
|
|
380
387
|
<>
|
|
381
388
|
<div className="space-y-4">
|
|
@@ -7,6 +7,7 @@ import { resolveTodoApiPath } from '../utils'
|
|
|
7
7
|
import type { TodoLinkSummary } from '../types'
|
|
8
8
|
import { generateTempId } from '@open-mercato/core/modules/customers/lib/detailHelpers'
|
|
9
9
|
import { parseBooleanToken } from '@open-mercato/shared/lib/boolean'
|
|
10
|
+
import { hasMoreFromPage } from '@open-mercato/shared/lib/pagination/load-more'
|
|
10
11
|
import { CUSTOMER_INTERACTION_TASK_SOURCE } from '../../../lib/interactionCompatibility'
|
|
11
12
|
|
|
12
13
|
const DEFAULT_TODO_SOURCE = CUSTOMER_INTERACTION_TASK_SOURCE
|
|
@@ -29,12 +30,15 @@ type CustomerTodoRow = {
|
|
|
29
30
|
createdAt: string
|
|
30
31
|
}
|
|
31
32
|
|
|
33
|
+
// `/api/customers/todos` also reports `totalPages`, deliberately left out of
|
|
34
|
+
// this type: the load-more affordance terminates on a short page instead — see
|
|
35
|
+
// `hasMoreFromPage`. `total` stays because it feeds the section's count badge,
|
|
36
|
+
// where an under-report is cosmetic rather than a way to strand rows.
|
|
32
37
|
type CustomerTodosResponse = {
|
|
33
38
|
items: CustomerTodoRow[]
|
|
34
39
|
total: number
|
|
35
40
|
page: number
|
|
36
41
|
pageSize: number
|
|
37
|
-
totalPages: number
|
|
38
42
|
}
|
|
39
43
|
|
|
40
44
|
export type TaskFormPayload = {
|
|
@@ -172,9 +176,9 @@ export function usePersonTasks({
|
|
|
172
176
|
pageSize = 20,
|
|
173
177
|
}: UsePersonTasksOptions): UsePersonTasksResult {
|
|
174
178
|
const [tasks, setTasks] = React.useState<TodoLinkSummary[]>(initialTasks)
|
|
175
|
-
const [pageInfo, setPageInfo] = React.useState<{ page: number;
|
|
179
|
+
const [pageInfo, setPageInfo] = React.useState<{ page: number; hasMore: boolean; total: number }>({
|
|
176
180
|
page: 1,
|
|
177
|
-
|
|
181
|
+
hasMore: false,
|
|
178
182
|
total: initialTasks.length,
|
|
179
183
|
})
|
|
180
184
|
const [isInitialLoading, setIsInitialLoading] = React.useState<boolean>(() => Boolean(entityId))
|
|
@@ -187,12 +191,18 @@ export function usePersonTasks({
|
|
|
187
191
|
const mapped = Array.isArray(payload.items) ? payload.items.map(mapRowToSummary) : []
|
|
188
192
|
setPageInfo({
|
|
189
193
|
page: payload.page ?? 1,
|
|
190
|
-
|
|
194
|
+
// Short-page termination instead of `page < totalPages` — see
|
|
195
|
+
// `hasMoreFromPage`. `mapRowToSummary` is a 1:1 map and the `mergeUnique`
|
|
196
|
+
// dedupe happens after this, so `mapped.length` is what the server served.
|
|
197
|
+
// Measured against the page size the server echoed rather than the one
|
|
198
|
+
// requested, so a page size the endpoint narrows server-side cannot make a
|
|
199
|
+
// full page read as short and silently end the sequence.
|
|
200
|
+
hasMore: hasMoreFromPage(mapped.length, payload.pageSize ?? pageSize),
|
|
191
201
|
total: payload.total ?? mapped.length,
|
|
192
202
|
})
|
|
193
203
|
setError(null)
|
|
194
204
|
return mapped
|
|
195
|
-
}, [])
|
|
205
|
+
}, [pageSize])
|
|
196
206
|
|
|
197
207
|
const fetchPage = React.useCallback(
|
|
198
208
|
async (page: number): Promise<CustomerTodosResponse> => {
|
|
@@ -202,7 +212,6 @@ export function usePersonTasks({
|
|
|
202
212
|
total: 0,
|
|
203
213
|
page: 1,
|
|
204
214
|
pageSize,
|
|
205
|
-
totalPages: 1,
|
|
206
215
|
}
|
|
207
216
|
}
|
|
208
217
|
const params = new URLSearchParams({
|
|
@@ -222,7 +231,7 @@ export function usePersonTasks({
|
|
|
222
231
|
const refresh = React.useCallback(async () => {
|
|
223
232
|
if (!entityId) {
|
|
224
233
|
setTasks([])
|
|
225
|
-
setPageInfo({ page: 1,
|
|
234
|
+
setPageInfo({ page: 1, hasMore: false, total: 0 })
|
|
226
235
|
return
|
|
227
236
|
}
|
|
228
237
|
setIsInitialLoading(true)
|
|
@@ -242,7 +251,7 @@ export function usePersonTasks({
|
|
|
242
251
|
const loadMore = React.useCallback(async () => {
|
|
243
252
|
if (!entityId) return
|
|
244
253
|
if (isLoadingMore) return
|
|
245
|
-
if (pageInfo.
|
|
254
|
+
if (!pageInfo.hasMore) return
|
|
246
255
|
setIsLoadingMore(true)
|
|
247
256
|
try {
|
|
248
257
|
const payload = await fetchPage(pageInfo.page + 1)
|
|
@@ -255,12 +264,12 @@ export function usePersonTasks({
|
|
|
255
264
|
} finally {
|
|
256
265
|
setIsLoadingMore(false)
|
|
257
266
|
}
|
|
258
|
-
}, [entityId, fetchPage, isLoadingMore, mapResponse, pageInfo.
|
|
267
|
+
}, [entityId, fetchPage, isLoadingMore, mapResponse, pageInfo.hasMore, pageInfo.page])
|
|
259
268
|
|
|
260
269
|
React.useEffect(() => {
|
|
261
270
|
if (!entityId) {
|
|
262
271
|
setTasks([])
|
|
263
|
-
setPageInfo({ page: 1,
|
|
272
|
+
setPageInfo({ page: 1, hasMore: false, total: 0 })
|
|
264
273
|
setError(null)
|
|
265
274
|
setIsInitialLoading(false)
|
|
266
275
|
return
|
|
@@ -268,7 +277,7 @@ export function usePersonTasks({
|
|
|
268
277
|
setTasks(initialTasks)
|
|
269
278
|
setPageInfo({
|
|
270
279
|
page: 1,
|
|
271
|
-
|
|
280
|
+
hasMore: false,
|
|
272
281
|
total: initialTasks.length,
|
|
273
282
|
})
|
|
274
283
|
setError(null)
|
|
@@ -342,7 +351,7 @@ export function usePersonTasks({
|
|
|
342
351
|
setTasks((prev) => [newTask, ...prev])
|
|
343
352
|
setPageInfo((prev) => ({
|
|
344
353
|
page: 1,
|
|
345
|
-
|
|
354
|
+
hasMore: prev.hasMore,
|
|
346
355
|
total: prev.total + 1,
|
|
347
356
|
}))
|
|
348
357
|
await refresh()
|
|
@@ -466,7 +475,7 @@ export function usePersonTasks({
|
|
|
466
475
|
setTasks((prev) => prev.filter((item) => item.id !== task.id))
|
|
467
476
|
setPageInfo((prev) => ({
|
|
468
477
|
page: prev.page,
|
|
469
|
-
|
|
478
|
+
hasMore: prev.hasMore,
|
|
470
479
|
total: Math.max(0, prev.total - 1),
|
|
471
480
|
}))
|
|
472
481
|
} finally {
|
|
@@ -476,7 +485,7 @@ export function usePersonTasks({
|
|
|
476
485
|
[],
|
|
477
486
|
)
|
|
478
487
|
|
|
479
|
-
const hasMore = entityId != null && pageInfo.
|
|
488
|
+
const hasMore = entityId != null && pageInfo.hasMore
|
|
480
489
|
|
|
481
490
|
return {
|
|
482
491
|
tasks,
|