@open-mercato/core 0.8.1-develop.7274.1.21a0083828 → 0.8.1-develop.7294.1.0ef99fc518
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/modules/auth/api/users/acl/route.js.map +2 -2
- package/dist/modules/auth/components/AclEditor.js +21 -3
- package/dist/modules/auth/components/AclEditor.js.map +2 -2
- package/dist/modules/customers/backend/customers/companies/page.js +6 -4
- package/dist/modules/customers/backend/customers/companies/page.js.map +2 -2
- package/dist/modules/customers/backend/customers/deals/map/components/DealsMapView.js +6 -4
- package/dist/modules/customers/backend/customers/deals/map/components/DealsMapView.js.map +2 -2
- package/dist/modules/customers/backend/customers/deals/page.js +6 -4
- package/dist/modules/customers/backend/customers/deals/page.js.map +2 -2
- package/dist/modules/customers/backend/customers/deals/pipeline/components/ChangeOwnerDialog.js +5 -3
- package/dist/modules/customers/backend/customers/deals/pipeline/components/ChangeOwnerDialog.js.map +2 -2
- package/dist/modules/customers/backend/customers/deals/pipeline/page.js +6 -4
- package/dist/modules/customers/backend/customers/deals/pipeline/page.js.map +2 -2
- package/dist/modules/customers/backend/customers/people/page.js +6 -4
- package/dist/modules/customers/backend/customers/people/page.js.map +2 -2
- package/dist/modules/customers/components/calendar/editor/PeopleField.js +9 -2
- package/dist/modules/customers/components/calendar/editor/PeopleField.js.map +2 -2
- package/dist/modules/customers/components/calendar/editor/hooks.js +4 -2
- package/dist/modules/customers/components/calendar/editor/hooks.js.map +2 -2
- package/dist/modules/customers/components/calendar/editor/lookups.js +7 -3
- package/dist/modules/customers/components/calendar/editor/lookups.js.map +2 -2
- package/dist/modules/customers/components/detail/AssignRoleDialog.js +5 -2
- package/dist/modules/customers/components/detail/AssignRoleDialog.js.map +2 -2
- package/dist/modules/customers/components/detail/RoleAssignmentRow.js +4 -2
- package/dist/modules/customers/components/detail/RoleAssignmentRow.js.map +2 -2
- package/dist/modules/customers/components/detail/ScheduleActivityDialog.js +8 -5
- package/dist/modules/customers/components/detail/ScheduleActivityDialog.js.map +2 -2
- package/dist/modules/customers/components/detail/schedule/DateTimeFields.js +10 -7
- package/dist/modules/customers/components/detail/schedule/DateTimeFields.js.map +2 -2
- package/dist/modules/customers/components/detail/schedule/ParticipantsField.js +4 -2
- package/dist/modules/customers/components/detail/schedule/ParticipantsField.js.map +2 -2
- package/dist/modules/customers/components/detail/schedule/fieldConfig.js +9 -0
- package/dist/modules/customers/components/detail/schedule/fieldConfig.js.map +2 -2
- package/dist/modules/customers/components/detail/schedule/index.js +3 -1
- package/dist/modules/customers/components/detail/schedule/index.js.map +2 -2
- package/dist/modules/customers/components/detail/schedule/useScheduleFormState.js +11 -4
- package/dist/modules/customers/components/detail/schedule/useScheduleFormState.js.map +2 -2
- package/dist/modules/customers/components/formConfig.js +17 -9
- package/dist/modules/customers/components/formConfig.js.map +2 -2
- package/dist/modules/customers/data/validators.js +12 -7
- package/dist/modules/customers/data/validators.js.map +2 -2
- package/dist/modules/customers/lib/assignableStaff.js +103 -22
- package/dist/modules/customers/lib/assignableStaff.js.map +2 -2
- package/dist/modules/customers/setup.js +10 -2
- package/dist/modules/customers/setup.js.map +2 -2
- package/dist/modules/data_sync/api/schedules/[id]/route.js +5 -0
- package/dist/modules/data_sync/api/schedules/[id]/route.js.map +2 -2
- package/dist/modules/data_sync/api/schedules/route.js +5 -0
- package/dist/modules/data_sync/api/schedules/route.js.map +2 -2
- package/dist/modules/data_sync/backend/data-sync/page.js +29 -5
- package/dist/modules/data_sync/backend/data-sync/page.js.map +2 -2
- package/dist/modules/data_sync/components/IntegrationScheduleTab.js +48 -11
- package/dist/modules/data_sync/components/IntegrationScheduleTab.js.map +2 -2
- package/dist/modules/data_sync/data/validators.js +13 -2
- package/dist/modules/data_sync/data/validators.js.map +2 -2
- package/dist/modules/data_sync/lib/schedule-value.js +30 -0
- package/dist/modules/data_sync/lib/schedule-value.js.map +7 -0
- package/dist/modules/eudr/data/validators.js.map +2 -2
- package/dist/modules/portal/frontend/[orgSlug]/portal/dashboard/page.js +3 -4
- package/dist/modules/portal/frontend/[orgSlug]/portal/dashboard/page.js.map +2 -2
- package/dist/modules/portal/frontend/[orgSlug]/portal/invite/page.js +3 -1
- package/dist/modules/portal/frontend/[orgSlug]/portal/invite/page.js.map +2 -2
- package/dist/modules/portal/frontend/[orgSlug]/portal/login/page.js +2 -1
- package/dist/modules/portal/frontend/[orgSlug]/portal/login/page.js.map +2 -2
- package/dist/modules/portal/frontend/[orgSlug]/portal/page.js +3 -4
- package/dist/modules/portal/frontend/[orgSlug]/portal/page.js.map +2 -2
- package/dist/modules/portal/frontend/[orgSlug]/portal/profile/page.js +3 -4
- package/dist/modules/portal/frontend/[orgSlug]/portal/profile/page.js.map +2 -2
- package/dist/modules/portal/lib/navigation.js +3 -4
- package/dist/modules/portal/lib/navigation.js.map +2 -2
- package/dist/modules/query_index/lib/engine.js +79 -14
- package/dist/modules/query_index/lib/engine.js.map +2 -2
- package/dist/modules/staff/backend/staff/time-tracking/page.js +122 -86
- package/dist/modules/staff/backend/staff/time-tracking/page.js.map +2 -2
- package/dist/modules/staff/backend/staff/time-tracking/projects/[id]/page.js +38 -17
- package/dist/modules/staff/backend/staff/time-tracking/projects/[id]/page.js.map +2 -2
- package/dist/modules/staff/backend/staff/time-tracking/reports/[id]/page.js +45 -18
- package/dist/modules/staff/backend/staff/time-tracking/reports/[id]/page.js.map +2 -2
- package/dist/modules/staff/extension-points.js +16 -0
- package/dist/modules/staff/extension-points.js.map +2 -2
- package/dist/modules/staff/frontend/[orgSlug]/portal/time-reports/[id]/page.js +3 -4
- package/dist/modules/staff/frontend/[orgSlug]/portal/time-reports/[id]/page.js.map +2 -2
- package/dist/modules/staff/frontend/[orgSlug]/portal/time-reports/page.js +3 -4
- package/dist/modules/staff/frontend/[orgSlug]/portal/time-reports/page.js.map +2 -2
- package/dist/modules/staff/lib/time-tracking-ui/ReportSheet.js +14 -13
- package/dist/modules/staff/lib/time-tracking-ui/ReportSheet.js.map +2 -2
- package/dist/modules/staff/lib/time-tracking-ui/TaskListView.js +60 -41
- package/dist/modules/staff/lib/time-tracking-ui/TaskListView.js.map +2 -2
- package/dist/modules/warranty_claims/api/ai/assess/route.js +2 -2
- package/dist/modules/warranty_claims/api/ai/assess/route.js.map +2 -2
- package/dist/modules/warranty_claims/api/ai/draft-reply/route.js +3 -4
- package/dist/modules/warranty_claims/api/ai/draft-reply/route.js.map +3 -3
- package/dist/modules/warranty_claims/api/ai/suggest/route.js +3 -3
- package/dist/modules/warranty_claims/api/ai/suggest/route.js.map +2 -2
- package/dist/modules/warranty_claims/api/assign/route.js +3 -3
- package/dist/modules/warranty_claims/api/assign/route.js.map +2 -2
- package/dist/modules/warranty_claims/api/credit-memo/route.js +2 -2
- package/dist/modules/warranty_claims/api/credit-memo/route.js.map +2 -2
- package/dist/modules/warranty_claims/api/entitlement/route.js +2 -2
- package/dist/modules/warranty_claims/api/entitlement/route.js.map +2 -2
- package/dist/modules/warranty_claims/api/events/route.js +4 -4
- package/dist/modules/warranty_claims/api/events/route.js.map +2 -2
- package/dist/modules/warranty_claims/api/external/claims/route.js +3 -3
- package/dist/modules/warranty_claims/api/external/claims/route.js.map +2 -2
- package/dist/modules/warranty_claims/api/portal/claims/[id]/submit/route.js +2 -2
- package/dist/modules/warranty_claims/api/portal/claims/[id]/submit/route.js.map +2 -2
- package/dist/modules/warranty_claims/api/portal/claims/[id]/withdraw/route.js +2 -2
- package/dist/modules/warranty_claims/api/portal/claims/[id]/withdraw/route.js.map +2 -2
- package/dist/modules/warranty_claims/api/portal/claims/route.js +2 -2
- package/dist/modules/warranty_claims/api/portal/claims/route.js.map +2 -2
- package/dist/modules/warranty_claims/api/portal/events/route.js +2 -2
- package/dist/modules/warranty_claims/api/portal/events/route.js.map +2 -2
- package/dist/modules/warranty_claims/api/receiving/route.js +2 -2
- package/dist/modules/warranty_claims/api/receiving/route.js.map +2 -2
- package/dist/modules/warranty_claims/api/replacement-order/route.js +2 -2
- package/dist/modules/warranty_claims/api/replacement-order/route.js.map +2 -2
- package/dist/modules/warranty_claims/api/return-label/route.js +2 -2
- package/dist/modules/warranty_claims/api/return-label/route.js.map +2 -2
- package/dist/modules/warranty_claims/api/risk/route.js +2 -2
- package/dist/modules/warranty_claims/api/risk/route.js.map +2 -2
- package/dist/modules/warranty_claims/api/sales-return/route.js +2 -2
- package/dist/modules/warranty_claims/api/sales-return/route.js.map +2 -2
- package/dist/modules/warranty_claims/api/settings-general/route.js +4 -4
- package/dist/modules/warranty_claims/api/settings-general/route.js.map +2 -2
- package/dist/modules/warranty_claims/api/stats/route.js +2 -2
- package/dist/modules/warranty_claims/api/stats/route.js.map +2 -2
- package/dist/modules/warranty_claims/api/submit/route.js +3 -3
- package/dist/modules/warranty_claims/api/submit/route.js.map +2 -2
- package/dist/modules/warranty_claims/api/transition/route.js +3 -3
- package/dist/modules/warranty_claims/api/transition/route.js.map +2 -2
- package/dist/modules/warranty_claims/api/vendor-recovery/route.js +3 -3
- package/dist/modules/warranty_claims/api/vendor-recovery/route.js.map +2 -2
- package/dist/modules/warranty_claims/api/vendor-recovery-suggestions/route.js +2 -2
- package/dist/modules/warranty_claims/api/vendor-recovery-suggestions/route.js.map +2 -2
- package/dist/modules/warranty_claims/backend/page.js +4 -2
- package/dist/modules/warranty_claims/backend/page.js.map +2 -2
- package/dist/modules/warranty_claims/backend/warranty_claims/[id]/page.js +9 -2
- package/dist/modules/warranty_claims/backend/warranty_claims/[id]/page.js.map +2 -2
- package/dist/modules/warranty_claims/backend/warranty_claims/settings/page.js +4 -2
- package/dist/modules/warranty_claims/backend/warranty_claims/settings/page.js.map +2 -2
- package/dist/modules/warranty_claims/frontend/[orgSlug]/portal/claims/[id]/page.js +3 -4
- package/dist/modules/warranty_claims/frontend/[orgSlug]/portal/claims/[id]/page.js.map +2 -2
- package/dist/modules/warranty_claims/frontend/[orgSlug]/portal/claims/new/page.js +3 -2
- package/dist/modules/warranty_claims/frontend/[orgSlug]/portal/claims/new/page.js.map +2 -2
- package/dist/modules/warranty_claims/frontend/[orgSlug]/portal/claims/page.js +3 -2
- package/dist/modules/warranty_claims/frontend/[orgSlug]/portal/claims/page.js.map +2 -2
- package/dist/modules/workflows/components/DefinitionTriggersEditor.js +1 -1
- package/dist/modules/workflows/components/DefinitionTriggersEditor.js.map +2 -2
- package/dist/modules/workflows/frontend/[orgSlug]/portal/tasks/[id]/page.js +2 -2
- package/dist/modules/workflows/frontend/[orgSlug]/portal/tasks/[id]/page.js.map +2 -2
- package/dist/modules/workflows/lib/event-trigger-service.js +56 -1
- package/dist/modules/workflows/lib/event-trigger-service.js.map +2 -2
- package/package.json +7 -7
- package/src/modules/auth/api/users/acl/route.ts +4 -3
- package/src/modules/auth/components/AclEditor.tsx +38 -2
- package/src/modules/auth/i18n/de.json +5 -1
- package/src/modules/auth/i18n/en.json +5 -1
- package/src/modules/auth/i18n/es.json +5 -1
- package/src/modules/auth/i18n/ko.json +5 -1
- package/src/modules/auth/i18n/pl.json +5 -1
- package/src/modules/customers/backend/customers/companies/page.tsx +6 -4
- package/src/modules/customers/backend/customers/deals/map/components/DealsMapView.tsx +6 -4
- package/src/modules/customers/backend/customers/deals/page.tsx +6 -4
- package/src/modules/customers/backend/customers/deals/pipeline/components/ChangeOwnerDialog.tsx +5 -3
- package/src/modules/customers/backend/customers/deals/pipeline/page.tsx +6 -4
- package/src/modules/customers/backend/customers/people/page.tsx +6 -4
- package/src/modules/customers/components/calendar/editor/PeopleField.tsx +9 -2
- package/src/modules/customers/components/calendar/editor/hooks.ts +4 -2
- package/src/modules/customers/components/calendar/editor/lookups.ts +12 -4
- package/src/modules/customers/components/detail/AssignRoleDialog.tsx +4 -1
- package/src/modules/customers/components/detail/RoleAssignmentRow.tsx +4 -2
- package/src/modules/customers/components/detail/ScheduleActivityDialog.tsx +15 -7
- package/src/modules/customers/components/detail/schedule/DateTimeFields.tsx +16 -7
- package/src/modules/customers/components/detail/schedule/ParticipantsField.tsx +4 -2
- package/src/modules/customers/components/detail/schedule/fieldConfig.ts +15 -0
- package/src/modules/customers/components/detail/schedule/index.ts +1 -1
- package/src/modules/customers/components/detail/schedule/useScheduleFormState.ts +16 -9
- package/src/modules/customers/components/formConfig.tsx +35 -12
- package/src/modules/customers/data/validators.ts +14 -8
- package/src/modules/customers/i18n/de.json +1 -0
- package/src/modules/customers/i18n/en.json +1 -0
- package/src/modules/customers/i18n/es.json +1 -0
- package/src/modules/customers/i18n/ko.json +1 -0
- package/src/modules/customers/i18n/pl.json +1 -0
- package/src/modules/customers/lib/assignableStaff.ts +172 -34
- package/src/modules/customers/setup.ts +8 -0
- package/src/modules/data_sync/api/schedules/[id]/route.ts +5 -0
- package/src/modules/data_sync/api/schedules/route.ts +5 -0
- package/src/modules/data_sync/backend/data-sync/page.tsx +48 -4
- package/src/modules/data_sync/components/IntegrationScheduleTab.tsx +61 -2
- package/src/modules/data_sync/data/validators.ts +26 -2
- package/src/modules/data_sync/i18n/de.json +2 -0
- package/src/modules/data_sync/i18n/en.json +2 -0
- package/src/modules/data_sync/i18n/es.json +2 -0
- package/src/modules/data_sync/i18n/ko.json +2 -0
- package/src/modules/data_sync/i18n/pl.json +2 -0
- package/src/modules/data_sync/lib/schedule-value.ts +45 -0
- package/src/modules/eudr/data/validators.ts +3 -4
- package/src/modules/portal/frontend/[orgSlug]/portal/dashboard/page.tsx +5 -4
- package/src/modules/portal/frontend/[orgSlug]/portal/invite/page.tsx +3 -1
- package/src/modules/portal/frontend/[orgSlug]/portal/login/page.tsx +2 -1
- package/src/modules/portal/frontend/[orgSlug]/portal/page.tsx +5 -5
- package/src/modules/portal/frontend/[orgSlug]/portal/profile/page.tsx +5 -4
- package/src/modules/portal/i18n/de.json +1 -0
- package/src/modules/portal/i18n/en.json +1 -0
- package/src/modules/portal/i18n/es.json +1 -0
- package/src/modules/portal/i18n/ko.json +1 -0
- package/src/modules/portal/i18n/pl.json +1 -0
- package/src/modules/portal/lib/navigation.ts +8 -3
- package/src/modules/query_index/lib/engine.ts +111 -16
- package/src/modules/staff/backend/staff/time-tracking/page.tsx +161 -130
- package/src/modules/staff/backend/staff/time-tracking/projects/[id]/page.tsx +55 -43
- package/src/modules/staff/backend/staff/time-tracking/reports/[id]/page.tsx +61 -38
- package/src/modules/staff/extension-points.ts +16 -0
- package/src/modules/staff/frontend/[orgSlug]/portal/time-reports/[id]/page.tsx +3 -4
- package/src/modules/staff/frontend/[orgSlug]/portal/time-reports/page.tsx +3 -4
- package/src/modules/staff/i18n/de.json +3 -0
- package/src/modules/staff/i18n/en.json +3 -0
- package/src/modules/staff/i18n/es.json +3 -0
- package/src/modules/staff/i18n/ko.json +3 -0
- package/src/modules/staff/i18n/pl.json +3 -0
- package/src/modules/staff/lib/time-tracking-ui/ReportSheet.tsx +32 -29
- package/src/modules/staff/lib/time-tracking-ui/TaskListView.tsx +89 -79
- package/src/modules/warranty_claims/api/ai/assess/route.ts +2 -2
- package/src/modules/warranty_claims/api/ai/draft-reply/route.ts +2 -3
- package/src/modules/warranty_claims/api/ai/suggest/route.ts +3 -3
- package/src/modules/warranty_claims/api/assign/route.ts +3 -3
- package/src/modules/warranty_claims/api/credit-memo/route.ts +2 -2
- package/src/modules/warranty_claims/api/entitlement/route.ts +2 -2
- package/src/modules/warranty_claims/api/events/route.ts +4 -4
- package/src/modules/warranty_claims/api/external/claims/route.ts +3 -3
- package/src/modules/warranty_claims/api/portal/claims/[id]/submit/route.ts +2 -2
- package/src/modules/warranty_claims/api/portal/claims/[id]/withdraw/route.ts +2 -2
- package/src/modules/warranty_claims/api/portal/claims/route.ts +2 -2
- package/src/modules/warranty_claims/api/portal/events/route.ts +2 -2
- package/src/modules/warranty_claims/api/receiving/route.ts +2 -2
- package/src/modules/warranty_claims/api/replacement-order/route.ts +2 -2
- package/src/modules/warranty_claims/api/return-label/route.ts +2 -2
- package/src/modules/warranty_claims/api/risk/route.ts +2 -2
- package/src/modules/warranty_claims/api/sales-return/route.ts +2 -2
- package/src/modules/warranty_claims/api/settings-general/route.ts +4 -4
- package/src/modules/warranty_claims/api/stats/route.ts +2 -2
- package/src/modules/warranty_claims/api/submit/route.ts +3 -3
- package/src/modules/warranty_claims/api/transition/route.ts +3 -3
- package/src/modules/warranty_claims/api/vendor-recovery/route.ts +3 -3
- package/src/modules/warranty_claims/api/vendor-recovery-suggestions/route.ts +2 -2
- package/src/modules/warranty_claims/backend/page.tsx +4 -2
- package/src/modules/warranty_claims/backend/warranty_claims/[id]/page.tsx +9 -2
- package/src/modules/warranty_claims/backend/warranty_claims/settings/page.tsx +4 -2
- package/src/modules/warranty_claims/frontend/[orgSlug]/portal/claims/[id]/page.tsx +5 -4
- package/src/modules/warranty_claims/frontend/[orgSlug]/portal/claims/new/page.tsx +5 -2
- package/src/modules/warranty_claims/frontend/[orgSlug]/portal/claims/page.tsx +5 -2
- package/src/modules/workflows/components/DefinitionTriggersEditor.tsx +1 -1
- package/src/modules/workflows/frontend/[orgSlug]/portal/tasks/[id]/page.tsx +2 -2
- package/src/modules/workflows/i18n/de.json +1 -1
- package/src/modules/workflows/i18n/en.json +1 -1
- package/src/modules/workflows/i18n/es.json +1 -1
- package/src/modules/workflows/i18n/ko.json +1 -1
- package/src/modules/workflows/i18n/pl.json +1 -1
- package/src/modules/workflows/lib/event-trigger-service.ts +139 -0
|
@@ -86,6 +86,13 @@ const FIELD_LABEL_OVERRIDES = {
|
|
|
86
86
|
function isVisible(type, fieldId) {
|
|
87
87
|
return FIELD_VISIBILITY[type].has(fieldId);
|
|
88
88
|
}
|
|
89
|
+
const OPTIONAL_DATE_TYPES = /* @__PURE__ */ new Set(["task"]);
|
|
90
|
+
function isDateRequired(type) {
|
|
91
|
+
return isVisible(type, "date") && !OPTIONAL_DATE_TYPES.has(type);
|
|
92
|
+
}
|
|
93
|
+
function isTimeRequired(type) {
|
|
94
|
+
return isVisible(type, "startTime") && isDateRequired(type);
|
|
95
|
+
}
|
|
89
96
|
function getFieldLabel(type, fieldId, t, defaultKey, defaultFallback) {
|
|
90
97
|
const override = FIELD_LABEL_OVERRIDES[type]?.[fieldId];
|
|
91
98
|
if (override) return t(override.key, override.fallback);
|
|
@@ -95,6 +102,8 @@ export {
|
|
|
95
102
|
FIELD_LABEL_OVERRIDES,
|
|
96
103
|
FIELD_VISIBILITY,
|
|
97
104
|
getFieldLabel,
|
|
105
|
+
isDateRequired,
|
|
106
|
+
isTimeRequired,
|
|
98
107
|
isVisible
|
|
99
108
|
};
|
|
100
109
|
//# sourceMappingURL=fieldConfig.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../../src/modules/customers/components/detail/schedule/fieldConfig.ts"],
|
|
4
|
-
"sourcesContent": ["export type ActivityType = 'meeting' | 'call' | 'task' | 'email' | 'note'\n\nexport type ScheduleFieldId =\n | 'title'\n | 'date'\n | 'startTime'\n | 'duration'\n | 'allDay'\n | 'timezone'\n | 'recurrence'\n | 'participants'\n | 'guestPermissions'\n | 'location'\n | 'linkedEntities'\n | 'description'\n | 'reminder'\n | 'visibility'\n\nexport const FIELD_VISIBILITY: Record<ActivityType, Set<ScheduleFieldId>> = {\n meeting: new Set([\n 'title', 'date', 'startTime', 'duration', 'allDay', 'timezone', 'recurrence',\n 'participants', 'guestPermissions', 'location', 'linkedEntities', 'description',\n 'reminder', 'visibility',\n ]),\n call: new Set([\n 'title', 'date', 'startTime', 'duration',\n 'participants', 'linkedEntities', 'description',\n 'reminder', 'visibility',\n ]),\n // Task: now also surfaces Due time (startTime) + Estimate (duration) per Figma 790:280.\n task: new Set([\n 'title', 'date', 'startTime', 'duration',\n 'linkedEntities', 'description',\n 'reminder', 'visibility',\n ]),\n // Email: surface participants as TO recipients per Figma 790:510.\n email: new Set([\n 'title', 'date', 'startTime',\n 'participants', 'linkedEntities', 'description',\n 'reminder', 'visibility',\n ]),\n note: new Set([\n 'title', 'linkedEntities', 'description', 'visibility',\n ]),\n}\n\ntype LabelOverride = { key: string; fallback: string }\n\n// Per-type section labels (Figma 784:1255 / 829:50 / 790:280 / 790:510).\n// `participants` / `linkedEntities` / `description` resolve via these overrides\n// when present; otherwise the field components fall back to their generic key.\nexport const FIELD_LABEL_OVERRIDES: Partial<\n Record<ActivityType, Partial<Record<ScheduleFieldId, LabelOverride>>>\n> = {\n meeting: {\n participants: { key: 'customers.schedule.attendees', fallback: 'Attendees' },\n linkedEntities: { key: 'customers.schedule.connections', fallback: 'Connections' },\n },\n call: {\n participants: { key: 'customers.schedule.contact', fallback: 'Contact' },\n linkedEntities: { key: 'customers.schedule.connections', fallback: 'Connections' },\n description: { key: 'customers.schedule.callNotes', fallback: 'Call notes' },\n },\n task: {\n date: { key: 'customers.schedule.dueDate', fallback: 'Due date' },\n startTime: { key: 'customers.schedule.dueTime', fallback: 'Due time' },\n duration: { key: 'customers.schedule.estimate', fallback: 'Estimate' },\n linkedEntities: { key: 'customers.schedule.connections', fallback: 'Connections' },\n description: { key: 'customers.schedule.details', fallback: 'Details' },\n },\n email: {\n title: { key: 'customers.schedule.subject', fallback: 'Subject' },\n participants: { key: 'customers.schedule.to', fallback: 'To' },\n linkedEntities: { key: 'customers.schedule.connections', fallback: 'Connections' },\n description: { key: 'customers.schedule.message', fallback: 'Message' },\n },\n note: {\n linkedEntities: { key: 'customers.schedule.connections', fallback: 'Connections' },\n description: { key: 'customers.schedule.note.content', fallback: 'Note' },\n },\n}\n\nexport function isVisible(type: ActivityType, fieldId: ScheduleFieldId): boolean {\n return FIELD_VISIBILITY[type].has(fieldId)\n}\n\nexport function getFieldLabel(\n type: ActivityType,\n fieldId: ScheduleFieldId,\n t: (key: string, fallback: string) => string,\n defaultKey: string,\n defaultFallback: string,\n): string {\n const override = FIELD_LABEL_OVERRIDES[type]?.[fieldId]\n if (override) return t(override.key, override.fallback)\n return t(defaultKey, defaultFallback)\n}\n"],
|
|
5
|
-
"mappings": "AAkBO,MAAM,mBAA+D;AAAA,EAC1E,SAAS,oBAAI,IAAI;AAAA,IACf;AAAA,IAAS;AAAA,IAAQ;AAAA,IAAa;AAAA,IAAY;AAAA,IAAU;AAAA,IAAY;AAAA,IAChE;AAAA,IAAgB;AAAA,IAAoB;AAAA,IAAY;AAAA,IAAkB;AAAA,IAClE;AAAA,IAAY;AAAA,EACd,CAAC;AAAA,EACD,MAAM,oBAAI,IAAI;AAAA,IACZ;AAAA,IAAS;AAAA,IAAQ;AAAA,IAAa;AAAA,IAC9B;AAAA,IAAgB;AAAA,IAAkB;AAAA,IAClC;AAAA,IAAY;AAAA,EACd,CAAC;AAAA;AAAA,EAED,MAAM,oBAAI,IAAI;AAAA,IACZ;AAAA,IAAS;AAAA,IAAQ;AAAA,IAAa;AAAA,IAC9B;AAAA,IAAkB;AAAA,IAClB;AAAA,IAAY;AAAA,EACd,CAAC;AAAA;AAAA,EAED,OAAO,oBAAI,IAAI;AAAA,IACb;AAAA,IAAS;AAAA,IAAQ;AAAA,IACjB;AAAA,IAAgB;AAAA,IAAkB;AAAA,IAClC;AAAA,IAAY;AAAA,EACd,CAAC;AAAA,EACD,MAAM,oBAAI,IAAI;AAAA,IACZ;AAAA,IAAS;AAAA,IAAkB;AAAA,IAAe;AAAA,EAC5C,CAAC;AACH;AAOO,MAAM,wBAET;AAAA,EACF,SAAS;AAAA,IACP,cAAc,EAAE,KAAK,gCAAgC,UAAU,YAAY;AAAA,IAC3E,gBAAgB,EAAE,KAAK,kCAAkC,UAAU,cAAc;AAAA,EACnF;AAAA,EACA,MAAM;AAAA,IACJ,cAAc,EAAE,KAAK,8BAA8B,UAAU,UAAU;AAAA,IACvE,gBAAgB,EAAE,KAAK,kCAAkC,UAAU,cAAc;AAAA,IACjF,aAAa,EAAE,KAAK,gCAAgC,UAAU,aAAa;AAAA,EAC7E;AAAA,EACA,MAAM;AAAA,IACJ,MAAM,EAAE,KAAK,8BAA8B,UAAU,WAAW;AAAA,IAChE,WAAW,EAAE,KAAK,8BAA8B,UAAU,WAAW;AAAA,IACrE,UAAU,EAAE,KAAK,+BAA+B,UAAU,WAAW;AAAA,IACrE,gBAAgB,EAAE,KAAK,kCAAkC,UAAU,cAAc;AAAA,IACjF,aAAa,EAAE,KAAK,8BAA8B,UAAU,UAAU;AAAA,EACxE;AAAA,EACA,OAAO;AAAA,IACL,OAAO,EAAE,KAAK,8BAA8B,UAAU,UAAU;AAAA,IAChE,cAAc,EAAE,KAAK,yBAAyB,UAAU,KAAK;AAAA,IAC7D,gBAAgB,EAAE,KAAK,kCAAkC,UAAU,cAAc;AAAA,IACjF,aAAa,EAAE,KAAK,8BAA8B,UAAU,UAAU;AAAA,EACxE;AAAA,EACA,MAAM;AAAA,IACJ,gBAAgB,EAAE,KAAK,kCAAkC,UAAU,cAAc;AAAA,IACjF,aAAa,EAAE,KAAK,mCAAmC,UAAU,OAAO;AAAA,EAC1E;AACF;AAEO,SAAS,UAAU,MAAoB,SAAmC;AAC/E,SAAO,iBAAiB,IAAI,EAAE,IAAI,OAAO;AAC3C;AAEO,SAAS,cACd,MACA,SACA,GACA,YACA,iBACQ;AACR,QAAM,WAAW,sBAAsB,IAAI,IAAI,OAAO;AACtD,MAAI,SAAU,QAAO,EAAE,SAAS,KAAK,SAAS,QAAQ;AACtD,SAAO,EAAE,YAAY,eAAe;AACtC;",
|
|
4
|
+
"sourcesContent": ["export type ActivityType = 'meeting' | 'call' | 'task' | 'email' | 'note'\n\nexport type ScheduleFieldId =\n | 'title'\n | 'date'\n | 'startTime'\n | 'duration'\n | 'allDay'\n | 'timezone'\n | 'recurrence'\n | 'participants'\n | 'guestPermissions'\n | 'location'\n | 'linkedEntities'\n | 'description'\n | 'reminder'\n | 'visibility'\n\nexport const FIELD_VISIBILITY: Record<ActivityType, Set<ScheduleFieldId>> = {\n meeting: new Set([\n 'title', 'date', 'startTime', 'duration', 'allDay', 'timezone', 'recurrence',\n 'participants', 'guestPermissions', 'location', 'linkedEntities', 'description',\n 'reminder', 'visibility',\n ]),\n call: new Set([\n 'title', 'date', 'startTime', 'duration',\n 'participants', 'linkedEntities', 'description',\n 'reminder', 'visibility',\n ]),\n // Task: now also surfaces Due time (startTime) + Estimate (duration) per Figma 790:280.\n task: new Set([\n 'title', 'date', 'startTime', 'duration',\n 'linkedEntities', 'description',\n 'reminder', 'visibility',\n ]),\n // Email: surface participants as TO recipients per Figma 790:510.\n email: new Set([\n 'title', 'date', 'startTime',\n 'participants', 'linkedEntities', 'description',\n 'reminder', 'visibility',\n ]),\n note: new Set([\n 'title', 'linkedEntities', 'description', 'visibility',\n ]),\n}\n\ntype LabelOverride = { key: string; fallback: string }\n\n// Per-type section labels (Figma 784:1255 / 829:50 / 790:280 / 790:510).\n// `participants` / `linkedEntities` / `description` resolve via these overrides\n// when present; otherwise the field components fall back to their generic key.\nexport const FIELD_LABEL_OVERRIDES: Partial<\n Record<ActivityType, Partial<Record<ScheduleFieldId, LabelOverride>>>\n> = {\n meeting: {\n participants: { key: 'customers.schedule.attendees', fallback: 'Attendees' },\n linkedEntities: { key: 'customers.schedule.connections', fallback: 'Connections' },\n },\n call: {\n participants: { key: 'customers.schedule.contact', fallback: 'Contact' },\n linkedEntities: { key: 'customers.schedule.connections', fallback: 'Connections' },\n description: { key: 'customers.schedule.callNotes', fallback: 'Call notes' },\n },\n task: {\n date: { key: 'customers.schedule.dueDate', fallback: 'Due date' },\n startTime: { key: 'customers.schedule.dueTime', fallback: 'Due time' },\n duration: { key: 'customers.schedule.estimate', fallback: 'Estimate' },\n linkedEntities: { key: 'customers.schedule.connections', fallback: 'Connections' },\n description: { key: 'customers.schedule.details', fallback: 'Details' },\n },\n email: {\n title: { key: 'customers.schedule.subject', fallback: 'Subject' },\n participants: { key: 'customers.schedule.to', fallback: 'To' },\n linkedEntities: { key: 'customers.schedule.connections', fallback: 'Connections' },\n description: { key: 'customers.schedule.message', fallback: 'Message' },\n },\n note: {\n linkedEntities: { key: 'customers.schedule.connections', fallback: 'Connections' },\n description: { key: 'customers.schedule.note.content', fallback: 'Note' },\n },\n}\n\nexport function isVisible(type: ActivityType, fieldId: ScheduleFieldId): boolean {\n return FIELD_VISIBILITY[type].has(fieldId)\n}\n\n// Calendar-bound types must land on a concrete moment, but a task is a backlog\n// item whose due date is optional by design (`interactions.scheduled_at` is\n// nullable and the task lists already render an undated row) \u2014 #5941.\nconst OPTIONAL_DATE_TYPES: Set<ActivityType> = new Set(['task'])\n\nexport function isDateRequired(type: ActivityType): boolean {\n return isVisible(type, 'date') && !OPTIONAL_DATE_TYPES.has(type)\n}\n\n// A time without a date is meaningless, so the time follows the date: it is\n// only demanded for the types that must be scheduled in the first place.\nexport function isTimeRequired(type: ActivityType): boolean {\n return isVisible(type, 'startTime') && isDateRequired(type)\n}\n\nexport function getFieldLabel(\n type: ActivityType,\n fieldId: ScheduleFieldId,\n t: (key: string, fallback: string) => string,\n defaultKey: string,\n defaultFallback: string,\n): string {\n const override = FIELD_LABEL_OVERRIDES[type]?.[fieldId]\n if (override) return t(override.key, override.fallback)\n return t(defaultKey, defaultFallback)\n}\n"],
|
|
5
|
+
"mappings": "AAkBO,MAAM,mBAA+D;AAAA,EAC1E,SAAS,oBAAI,IAAI;AAAA,IACf;AAAA,IAAS;AAAA,IAAQ;AAAA,IAAa;AAAA,IAAY;AAAA,IAAU;AAAA,IAAY;AAAA,IAChE;AAAA,IAAgB;AAAA,IAAoB;AAAA,IAAY;AAAA,IAAkB;AAAA,IAClE;AAAA,IAAY;AAAA,EACd,CAAC;AAAA,EACD,MAAM,oBAAI,IAAI;AAAA,IACZ;AAAA,IAAS;AAAA,IAAQ;AAAA,IAAa;AAAA,IAC9B;AAAA,IAAgB;AAAA,IAAkB;AAAA,IAClC;AAAA,IAAY;AAAA,EACd,CAAC;AAAA;AAAA,EAED,MAAM,oBAAI,IAAI;AAAA,IACZ;AAAA,IAAS;AAAA,IAAQ;AAAA,IAAa;AAAA,IAC9B;AAAA,IAAkB;AAAA,IAClB;AAAA,IAAY;AAAA,EACd,CAAC;AAAA;AAAA,EAED,OAAO,oBAAI,IAAI;AAAA,IACb;AAAA,IAAS;AAAA,IAAQ;AAAA,IACjB;AAAA,IAAgB;AAAA,IAAkB;AAAA,IAClC;AAAA,IAAY;AAAA,EACd,CAAC;AAAA,EACD,MAAM,oBAAI,IAAI;AAAA,IACZ;AAAA,IAAS;AAAA,IAAkB;AAAA,IAAe;AAAA,EAC5C,CAAC;AACH;AAOO,MAAM,wBAET;AAAA,EACF,SAAS;AAAA,IACP,cAAc,EAAE,KAAK,gCAAgC,UAAU,YAAY;AAAA,IAC3E,gBAAgB,EAAE,KAAK,kCAAkC,UAAU,cAAc;AAAA,EACnF;AAAA,EACA,MAAM;AAAA,IACJ,cAAc,EAAE,KAAK,8BAA8B,UAAU,UAAU;AAAA,IACvE,gBAAgB,EAAE,KAAK,kCAAkC,UAAU,cAAc;AAAA,IACjF,aAAa,EAAE,KAAK,gCAAgC,UAAU,aAAa;AAAA,EAC7E;AAAA,EACA,MAAM;AAAA,IACJ,MAAM,EAAE,KAAK,8BAA8B,UAAU,WAAW;AAAA,IAChE,WAAW,EAAE,KAAK,8BAA8B,UAAU,WAAW;AAAA,IACrE,UAAU,EAAE,KAAK,+BAA+B,UAAU,WAAW;AAAA,IACrE,gBAAgB,EAAE,KAAK,kCAAkC,UAAU,cAAc;AAAA,IACjF,aAAa,EAAE,KAAK,8BAA8B,UAAU,UAAU;AAAA,EACxE;AAAA,EACA,OAAO;AAAA,IACL,OAAO,EAAE,KAAK,8BAA8B,UAAU,UAAU;AAAA,IAChE,cAAc,EAAE,KAAK,yBAAyB,UAAU,KAAK;AAAA,IAC7D,gBAAgB,EAAE,KAAK,kCAAkC,UAAU,cAAc;AAAA,IACjF,aAAa,EAAE,KAAK,8BAA8B,UAAU,UAAU;AAAA,EACxE;AAAA,EACA,MAAM;AAAA,IACJ,gBAAgB,EAAE,KAAK,kCAAkC,UAAU,cAAc;AAAA,IACjF,aAAa,EAAE,KAAK,mCAAmC,UAAU,OAAO;AAAA,EAC1E;AACF;AAEO,SAAS,UAAU,MAAoB,SAAmC;AAC/E,SAAO,iBAAiB,IAAI,EAAE,IAAI,OAAO;AAC3C;AAKA,MAAM,sBAAyC,oBAAI,IAAI,CAAC,MAAM,CAAC;AAExD,SAAS,eAAe,MAA6B;AAC1D,SAAO,UAAU,MAAM,MAAM,KAAK,CAAC,oBAAoB,IAAI,IAAI;AACjE;AAIO,SAAS,eAAe,MAA6B;AAC1D,SAAO,UAAU,MAAM,WAAW,KAAK,eAAe,IAAI;AAC5D;AAEO,SAAS,cACd,MACA,SACA,GACA,YACA,iBACQ;AACR,QAAM,WAAW,sBAAsB,IAAI,IAAI,OAAO;AACtD,MAAI,SAAU,QAAO,EAAE,SAAS,KAAK,SAAS,QAAQ;AACtD,SAAO,EAAE,YAAY,eAAe;AACtC;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -3,7 +3,7 @@ import { ParticipantsField } from "./ParticipantsField.js";
|
|
|
3
3
|
import { LocationField } from "./LocationField.js";
|
|
4
4
|
import { FooterFields } from "./FooterFields.js";
|
|
5
5
|
import { LinkedEntitiesField } from "./LinkedEntitiesField.js";
|
|
6
|
-
import { isVisible, getFieldLabel, FIELD_VISIBILITY, FIELD_LABEL_OVERRIDES } from "./fieldConfig.js";
|
|
6
|
+
import { isVisible, isDateRequired, isTimeRequired, getFieldLabel, FIELD_VISIBILITY, FIELD_LABEL_OVERRIDES } from "./fieldConfig.js";
|
|
7
7
|
import { useScheduleFormState, PARTICIPANT_COLORS } from "./useScheduleFormState.js";
|
|
8
8
|
export {
|
|
9
9
|
DateTimeFields,
|
|
@@ -15,6 +15,8 @@ export {
|
|
|
15
15
|
PARTICIPANT_COLORS,
|
|
16
16
|
ParticipantsField,
|
|
17
17
|
getFieldLabel,
|
|
18
|
+
isDateRequired,
|
|
19
|
+
isTimeRequired,
|
|
18
20
|
isVisible,
|
|
19
21
|
useScheduleFormState
|
|
20
22
|
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../../src/modules/customers/components/detail/schedule/index.ts"],
|
|
4
|
-
"sourcesContent": ["export { DateTimeFields } from './DateTimeFields'\nexport { ParticipantsField } from './ParticipantsField'\nexport { LocationField } from './LocationField'\nexport { FooterFields } from './FooterFields'\nexport { LinkedEntitiesField } from './LinkedEntitiesField'\nexport { isVisible, getFieldLabel, FIELD_VISIBILITY, FIELD_LABEL_OVERRIDES } from './fieldConfig'\nexport type { ActivityType, ScheduleFieldId } from './fieldConfig'\nexport { useScheduleFormState, PARTICIPANT_COLORS } from './useScheduleFormState'\nexport type { Participant, LinkedEntity, RsvpStatus, ScheduleActivityEditData } from './useScheduleFormState'\n"],
|
|
5
|
-
"mappings": "AAAA,SAAS,sBAAsB;AAC/B,SAAS,yBAAyB;AAClC,SAAS,qBAAqB;AAC9B,SAAS,oBAAoB;AAC7B,SAAS,2BAA2B;AACpC,SAAS,WAAW,eAAe,kBAAkB,6BAA6B;
|
|
4
|
+
"sourcesContent": ["export { DateTimeFields } from './DateTimeFields'\nexport { ParticipantsField } from './ParticipantsField'\nexport { LocationField } from './LocationField'\nexport { FooterFields } from './FooterFields'\nexport { LinkedEntitiesField } from './LinkedEntitiesField'\nexport { isVisible, isDateRequired, isTimeRequired, getFieldLabel, FIELD_VISIBILITY, FIELD_LABEL_OVERRIDES } from './fieldConfig'\nexport type { ActivityType, ScheduleFieldId } from './fieldConfig'\nexport { useScheduleFormState, PARTICIPANT_COLORS } from './useScheduleFormState'\nexport type { Participant, LinkedEntity, RsvpStatus, ScheduleActivityEditData } from './useScheduleFormState'\n"],
|
|
5
|
+
"mappings": "AAAA,SAAS,sBAAsB;AAC/B,SAAS,yBAAyB;AAClC,SAAS,qBAAqB;AAC9B,SAAS,oBAAoB;AAC7B,SAAS,2BAA2B;AACpC,SAAS,WAAW,gBAAgB,gBAAgB,eAAe,kBAAkB,6BAA6B;AAElH,SAAS,sBAAsB,0BAA0B;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
|
+
import { isDateRequired } from "./fieldConfig.js";
|
|
2
3
|
const PARTICIPANT_COLORS = [
|
|
3
4
|
"bg-chart-emerald",
|
|
4
5
|
"bg-chart-blue",
|
|
@@ -78,9 +79,15 @@ function useScheduleFormState({ open, editData }) {
|
|
|
78
79
|
setTitle(editData.title ?? "");
|
|
79
80
|
const sourceTimestamp = editData.occurredAt ?? editData.scheduledAt ?? null;
|
|
80
81
|
const seedDate = sourceTimestamp ? new Date(sourceTimestamp) : null;
|
|
81
|
-
const
|
|
82
|
-
|
|
83
|
-
|
|
82
|
+
const seedDateValid = seedDate !== null && !Number.isNaN(seedDate.getTime());
|
|
83
|
+
if (isEditing && !seedDateValid && !isDateRequired(resolvedType)) {
|
|
84
|
+
setDate("");
|
|
85
|
+
setStartTime("");
|
|
86
|
+
} else {
|
|
87
|
+
const dateForForm = seedDateValid ? seedDate : resolveDefaultActivityStart(resolvedType, /* @__PURE__ */ new Date());
|
|
88
|
+
setDate(formatLocalDateInput(dateForForm));
|
|
89
|
+
setStartTime(formatLocalTimeInput(dateForForm));
|
|
90
|
+
}
|
|
84
91
|
setDuration(editData.durationMinutes ?? 30);
|
|
85
92
|
setAllDay(editData.allDay ?? false);
|
|
86
93
|
setDescription(editData.body ?? "");
|
|
@@ -152,7 +159,7 @@ function useScheduleFormState({ open, editData }) {
|
|
|
152
159
|
document.body.style.removeProperty("overflow");
|
|
153
160
|
document.body.style.removeProperty("pointer-events");
|
|
154
161
|
};
|
|
155
|
-
}, [open, editData]);
|
|
162
|
+
}, [open, editData, isEditing]);
|
|
156
163
|
const lastReminderTypeRef = React.useRef("meeting");
|
|
157
164
|
React.useEffect(() => {
|
|
158
165
|
if (!open || isEditing) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../../src/modules/customers/components/detail/schedule/useScheduleFormState.ts"],
|
|
4
|
-
"sourcesContent": ["import * as React from 'react'\nimport type { ActivityType } from './fieldConfig'\n\nexport type RsvpStatus = 'pending' | 'accepted' | 'declined' | 'tentative'\n\nexport type Participant = {\n userId?: string\n name: string\n email?: string\n color?: string\n status?: RsvpStatus\n}\n\nexport type LinkedEntity = {\n id: string\n type: 'company' | 'deal' | 'offer'\n label: string\n}\n\nexport type ScheduleActivityEditData = {\n id: string\n /** Record version for the OSS optimistic-lock header on edit (#2055). */\n updatedAt?: string | null\n interactionType?: string\n title?: string | null\n body?: string | null\n scheduledAt?: string | null\n /**\n * Historical timestamp for completed activities (status `done`). Required for\n * the edit prefill to restore the original date/time instead of falling back\n * to \"today\" (#1807).\n */\n occurredAt?: string | null\n durationMinutes?: number | null\n /** Interaction priority column (0-100, nullable) backing the task priority control (#5943). */\n priority?: number | null\n location?: string | null\n allDay?: boolean | null\n recurrenceRule?: string | null\n recurrenceEnd?: string | null\n participants?: Array<{ userId?: string; name?: string; email?: string; status?: string }> | null\n reminderMinutes?: number | null\n visibility?: string | null\n linkedEntities?: Array<{ id: string; type: string; label: string }> | null\n guestPermissions?: { canInviteOthers?: boolean; canModify?: boolean; canSeeList?: boolean } | null\n}\n\nexport const PARTICIPANT_COLORS = [\n 'bg-chart-emerald',\n 'bg-chart-blue',\n 'bg-chart-orange',\n 'bg-chart-violet',\n 'bg-chart-pink',\n 'bg-chart-teal',\n]\n\n// Per-Figma defaults for the Reminder dropdown when the user picks an activity\n// type. Meeting/email keep the standard 15 min; tasks default to 1 day (1440 min)\n// because they're plan-ahead artefacts; calls default to 5 min as a stand-in for\n// the Figma \"After call ends\" treatment (which would need a non-numeric sentinel\n// in the API contract \u2014 tracked as a follow-up).\nconst DEFAULT_REMINDER_MINUTES: Record<ActivityType, number> = {\n meeting: 15,\n call: 5,\n task: 1440,\n email: 15,\n note: 15,\n}\n\n// Create-mode date/time defaults. A fixed morning slot made every activity opened\n// later in the day start in the past, so the seed is always computed forward from\n// \"now\" (#5940): tasks are plan-ahead artefacts and default to the end of the\n// working day, everything else to the next half-hour slot.\nconst DEFAULT_SLOT_MINUTES = 30\nconst TASK_DEFAULT_HOUR = 17\nconst NEXT_DAY_START_HOUR = 9\n\nfunction padDatePart(value: number): string {\n return String(value).padStart(2, '0')\n}\n\nfunction isSameLocalDay(left: Date, right: Date): boolean {\n return (\n left.getFullYear() === right.getFullYear() &&\n left.getMonth() === right.getMonth() &&\n left.getDate() === right.getDate()\n )\n}\n\nfunction nextSlotAfter(now: Date): Date {\n const next = new Date(now)\n next.setSeconds(0, 0)\n next.setMinutes(next.getMinutes() + (DEFAULT_SLOT_MINUTES - (next.getMinutes() % DEFAULT_SLOT_MINUTES)))\n if (!isSameLocalDay(next, now)) {\n next.setHours(NEXT_DAY_START_HOUR, 0, 0, 0)\n }\n return next\n}\n\n/**\n * Default start moment for a newly created activity of `type`, always strictly\n * after `now` so a brand-new record is never born overdue (#5940).\n */\nexport function resolveDefaultActivityStart(type: ActivityType, now: Date): Date {\n if (type === 'task') {\n const endOfWorkingDay = new Date(now)\n endOfWorkingDay.setHours(TASK_DEFAULT_HOUR, 0, 0, 0)\n if (endOfWorkingDay.getTime() > now.getTime()) return endOfWorkingDay\n }\n return nextSlotAfter(now)\n}\n\nfunction formatLocalDateInput(date: Date): string {\n return `${date.getFullYear()}-${padDatePart(date.getMonth() + 1)}-${padDatePart(date.getDate())}`\n}\n\nfunction formatLocalTimeInput(date: Date): string {\n return `${padDatePart(date.getHours())}:${padDatePart(date.getMinutes())}`\n}\n\ninterface UseScheduleFormStateParams {\n open: boolean\n editData: ScheduleActivityEditData | null | undefined\n}\n\nexport function useScheduleFormState({ open, editData }: UseScheduleFormStateParams) {\n // An empty `id` is the menu-driven \"New X\" convention \u2014 a create with a preset\n // type, not an edit. The save path already reads it this way (`isSaveEdit`), so\n // the seeding below must agree or new records inherit edit-mode fallbacks (#5940).\n const isEditing = Boolean(editData?.id)\n const [initialStart] = React.useState(() => resolveDefaultActivityStart('meeting', new Date()))\n const [activityType, setActivityType] = React.useState<ActivityType>('meeting')\n const [title, setTitle] = React.useState('')\n const [date, setDate] = React.useState(() => formatLocalDateInput(initialStart))\n const [startTime, setStartTime] = React.useState(() => formatLocalTimeInput(initialStart))\n const [duration, setDuration] = React.useState(30)\n const [allDay, setAllDay] = React.useState(false)\n const [description, setDescription] = React.useState('')\n const [markdownEnabled, setMarkdownEnabled] = React.useState(true)\n const [location, setLocation] = React.useState('')\n const [reminderMinutes, setReminderMinutes] = React.useState(15)\n const [visibility, setVisibility] = React.useState('team')\n const [participants, setParticipants] = React.useState<Participant[]>([])\n const [linkedEntities, setLinkedEntities] = React.useState<LinkedEntity[]>([])\n const [recurrenceEnabled, setRecurrenceEnabled] = React.useState(false)\n const [recurrenceDays, setRecurrenceDays] = React.useState<boolean[]>([true, false, true, false, false, false, false])\n const [recurrenceEndType, setRecurrenceEndType] = React.useState<'never' | 'count' | 'date'>('never')\n const [recurrenceCount, setRecurrenceCount] = React.useState(8)\n const [recurrenceEndDate, setRecurrenceEndDate] = React.useState('')\n const [conflict, setConflict] = React.useState<string | null>(null)\n const [saving, setSaving] = React.useState(false)\n const [guestPermissions, setGuestPermissions] = React.useState({ canInviteOthers: true, canModify: false, canSeeList: true })\n\n React.useEffect(() => {\n if (open) {\n if (editData) {\n // Edit mode: populate from existing interaction\n const resolvedType = (editData.interactionType as ActivityType) ?? 'meeting'\n setActivityType(resolvedType)\n setTitle(editData.title ?? '')\n // For historical activities the canonical timestamp is `occurredAt`; for\n // planned/future ones it's `scheduledAt`. Without this fallback editing a\n // past activity prefilled to \"today\" instead of its actual moment (#1807).\n // Keep seed values in the user's local timezone, matching the cluster-E\n // local-day convention.\n const sourceTimestamp = editData.occurredAt ?? editData.scheduledAt ?? null\n const seedDate = sourceTimestamp ? new Date(sourceTimestamp) : null\n // No usable timestamp means this is a preset create (or a corrupt row), so\n // fall forward to the create-mode default instead of \"now\" (#5940).\n const dateForForm =\n seedDate && !Number.isNaN(seedDate.getTime())\n ? seedDate\n : resolveDefaultActivityStart(resolvedType, new Date())\n setDate(formatLocalDateInput(dateForForm))\n setStartTime(formatLocalTimeInput(dateForForm))\n setDuration(editData.durationMinutes ?? 30)\n setAllDay(editData.allDay ?? false)\n setDescription(editData.body ?? '')\n setLocation(editData.location ?? '')\n // Use per-type default when the editData omits an explicit reminder\n // (the menu-driven \"New X\" flow opens the dialog with `reminderMinutes: null`).\n setReminderMinutes(editData.reminderMinutes ?? DEFAULT_REMINDER_MINUTES[resolvedType])\n setVisibility(editData.visibility ?? 'team')\n setParticipants(\n Array.isArray(editData.participants)\n ? editData.participants.map((p, i) => ({\n userId: p.userId,\n name: p.name ?? p.email ?? p.userId ?? '',\n email: p.email,\n color: PARTICIPANT_COLORS[i % PARTICIPANT_COLORS.length],\n status: (p.status ?? 'pending') as RsvpStatus,\n }))\n : [],\n )\n setLinkedEntities(\n Array.isArray(editData.linkedEntities)\n ? editData.linkedEntities.map((e) => ({ id: e.id, type: e.type as LinkedEntity['type'], label: e.label }))\n : [],\n )\n if (editData.recurrenceRule) {\n setRecurrenceEnabled(true)\n // Parse RRULE to set days and end type\n const rule = editData.recurrenceRule\n const byDayMatch = rule.match(/BYDAY=([A-Z,]+)/)\n if (byDayMatch) {\n const dayNames = ['MO', 'TU', 'WE', 'TH', 'FR', 'SA', 'SU']\n const activeDays = byDayMatch[1].split(',')\n setRecurrenceDays(dayNames.map((d) => activeDays.includes(d)))\n }\n const countMatch = rule.match(/COUNT=(\\d+)/)\n const untilMatch = rule.match(/UNTIL=(\\d{8})/)\n if (countMatch) {\n setRecurrenceEndType('count')\n setRecurrenceCount(Number(countMatch[1]))\n } else if (untilMatch) {\n setRecurrenceEndType('date')\n const raw = untilMatch[1]\n setRecurrenceEndDate(`${raw.slice(0, 4)}-${raw.slice(4, 6)}-${raw.slice(6, 8)}`)\n } else {\n setRecurrenceEndType('never')\n }\n } else {\n setRecurrenceEnabled(false)\n }\n if (editData.guestPermissions) {\n setGuestPermissions({\n canInviteOthers: editData.guestPermissions.canInviteOthers ?? true,\n canModify: editData.guestPermissions.canModify ?? false,\n canSeeList: editData.guestPermissions.canSeeList ?? true,\n })\n }\n } else {\n // Create mode: reset all fields\n const defaultStart = resolveDefaultActivityStart('meeting', new Date())\n setActivityType('meeting')\n setTitle('')\n setDate(formatLocalDateInput(defaultStart))\n setStartTime(formatLocalTimeInput(defaultStart))\n setDuration(30)\n setAllDay(false)\n setDescription('')\n setLocation('')\n setReminderMinutes(DEFAULT_REMINDER_MINUTES.meeting)\n setVisibility('team')\n setParticipants([])\n setLinkedEntities([])\n setRecurrenceEnabled(false)\n }\n setConflict(null)\n }\n return () => {\n // Safety net: restore body scroll if Radix Dialog fails to clean up\n document.body.style.removeProperty('overflow')\n document.body.style.removeProperty('pointer-events')\n }\n }, [open, editData])\n\n // Update the Reminder default when the activity type changes in create mode.\n // Skipped in edit mode (the persisted value wins), and gated by `open` to\n // avoid flipping the default in a closed-but-mounted dialog.\n const lastReminderTypeRef = React.useRef<ActivityType>('meeting')\n React.useEffect(() => {\n if (!open || isEditing) {\n lastReminderTypeRef.current = activityType\n return\n }\n if (lastReminderTypeRef.current === activityType) return\n lastReminderTypeRef.current = activityType\n setReminderMinutes(DEFAULT_REMINDER_MINUTES[activityType])\n }, [activityType, isEditing, open])\n\n const removeParticipant = React.useCallback((index: number) => {\n setParticipants((prev) => prev.filter((_, i) => i !== index))\n }, [])\n\n const toggleRecurrenceDay = React.useCallback((index: number) => {\n setRecurrenceDays((prev) => {\n const next = [...prev]\n next[index] = !next[index]\n return next\n })\n }, [])\n\n return {\n activityType,\n setActivityType,\n title,\n setTitle,\n date,\n setDate,\n startTime,\n setStartTime,\n duration,\n setDuration,\n allDay,\n setAllDay,\n description,\n setDescription,\n markdownEnabled,\n setMarkdownEnabled,\n location,\n setLocation,\n reminderMinutes,\n setReminderMinutes,\n visibility,\n setVisibility,\n participants,\n setParticipants,\n linkedEntities,\n setLinkedEntities,\n recurrenceEnabled,\n setRecurrenceEnabled,\n recurrenceDays,\n setRecurrenceDays,\n recurrenceEndType,\n setRecurrenceEndType,\n recurrenceCount,\n setRecurrenceCount,\n recurrenceEndDate,\n setRecurrenceEndDate,\n conflict,\n setConflict,\n saving,\n setSaving,\n guestPermissions,\n setGuestPermissions,\n removeParticipant,\n toggleRecurrenceDay,\n }\n}\n"],
|
|
5
|
-
"mappings": "AAAA,YAAY,WAAW;
|
|
4
|
+
"sourcesContent": ["import * as React from 'react'\nimport type { ActivityType } from './fieldConfig'\nimport { isDateRequired } from './fieldConfig'\n\nexport type RsvpStatus = 'pending' | 'accepted' | 'declined' | 'tentative'\n\nexport type Participant = {\n userId?: string\n name: string\n email?: string\n color?: string\n status?: RsvpStatus\n}\n\nexport type LinkedEntity = {\n id: string\n type: 'company' | 'deal' | 'offer'\n label: string\n}\n\nexport type ScheduleActivityEditData = {\n id: string\n /** Record version for the OSS optimistic-lock header on edit (#2055). */\n updatedAt?: string | null\n interactionType?: string\n title?: string | null\n body?: string | null\n scheduledAt?: string | null\n /**\n * Historical timestamp for completed activities (status `done`). Required for\n * the edit prefill to restore the original date/time instead of falling back\n * to \"today\" (#1807).\n */\n occurredAt?: string | null\n durationMinutes?: number | null\n /** Interaction priority column (0-100, nullable) backing the task priority control (#5943). */\n priority?: number | null\n location?: string | null\n allDay?: boolean | null\n recurrenceRule?: string | null\n recurrenceEnd?: string | null\n participants?: Array<{ userId?: string; name?: string; email?: string; status?: string }> | null\n reminderMinutes?: number | null\n visibility?: string | null\n linkedEntities?: Array<{ id: string; type: string; label: string }> | null\n guestPermissions?: { canInviteOthers?: boolean; canModify?: boolean; canSeeList?: boolean } | null\n}\n\nexport const PARTICIPANT_COLORS = [\n 'bg-chart-emerald',\n 'bg-chart-blue',\n 'bg-chart-orange',\n 'bg-chart-violet',\n 'bg-chart-pink',\n 'bg-chart-teal',\n]\n\n// Per-Figma defaults for the Reminder dropdown when the user picks an activity\n// type. Meeting/email keep the standard 15 min; tasks default to 1 day (1440 min)\n// because they're plan-ahead artefacts; calls default to 5 min as a stand-in for\n// the Figma \"After call ends\" treatment (which would need a non-numeric sentinel\n// in the API contract \u2014 tracked as a follow-up).\nconst DEFAULT_REMINDER_MINUTES: Record<ActivityType, number> = {\n meeting: 15,\n call: 5,\n task: 1440,\n email: 15,\n note: 15,\n}\n\n// Create-mode date/time defaults. A fixed morning slot made every activity opened\n// later in the day start in the past, so the seed is always computed forward from\n// \"now\" (#5940): tasks are plan-ahead artefacts and default to the end of the\n// working day, everything else to the next half-hour slot.\nconst DEFAULT_SLOT_MINUTES = 30\nconst TASK_DEFAULT_HOUR = 17\nconst NEXT_DAY_START_HOUR = 9\n\nfunction padDatePart(value: number): string {\n return String(value).padStart(2, '0')\n}\n\nfunction isSameLocalDay(left: Date, right: Date): boolean {\n return (\n left.getFullYear() === right.getFullYear() &&\n left.getMonth() === right.getMonth() &&\n left.getDate() === right.getDate()\n )\n}\n\nfunction nextSlotAfter(now: Date): Date {\n const next = new Date(now)\n next.setSeconds(0, 0)\n next.setMinutes(next.getMinutes() + (DEFAULT_SLOT_MINUTES - (next.getMinutes() % DEFAULT_SLOT_MINUTES)))\n if (!isSameLocalDay(next, now)) {\n next.setHours(NEXT_DAY_START_HOUR, 0, 0, 0)\n }\n return next\n}\n\n/**\n * Default start moment for a newly created activity of `type`, always strictly\n * after `now` so a brand-new record is never born overdue (#5940).\n */\nexport function resolveDefaultActivityStart(type: ActivityType, now: Date): Date {\n if (type === 'task') {\n const endOfWorkingDay = new Date(now)\n endOfWorkingDay.setHours(TASK_DEFAULT_HOUR, 0, 0, 0)\n if (endOfWorkingDay.getTime() > now.getTime()) return endOfWorkingDay\n }\n return nextSlotAfter(now)\n}\n\nfunction formatLocalDateInput(date: Date): string {\n return `${date.getFullYear()}-${padDatePart(date.getMonth() + 1)}-${padDatePart(date.getDate())}`\n}\n\nfunction formatLocalTimeInput(date: Date): string {\n return `${padDatePart(date.getHours())}:${padDatePart(date.getMinutes())}`\n}\n\ninterface UseScheduleFormStateParams {\n open: boolean\n editData: ScheduleActivityEditData | null | undefined\n}\n\nexport function useScheduleFormState({ open, editData }: UseScheduleFormStateParams) {\n // An empty `id` is the menu-driven \"New X\" convention \u2014 a create with a preset\n // type, not an edit. The save path already reads it this way (`isSaveEdit`), so\n // the seeding below must agree or new records inherit edit-mode fallbacks (#5940).\n const isEditing = Boolean(editData?.id)\n const [initialStart] = React.useState(() => resolveDefaultActivityStart('meeting', new Date()))\n const [activityType, setActivityType] = React.useState<ActivityType>('meeting')\n const [title, setTitle] = React.useState('')\n const [date, setDate] = React.useState(() => formatLocalDateInput(initialStart))\n const [startTime, setStartTime] = React.useState(() => formatLocalTimeInput(initialStart))\n const [duration, setDuration] = React.useState(30)\n const [allDay, setAllDay] = React.useState(false)\n const [description, setDescription] = React.useState('')\n const [markdownEnabled, setMarkdownEnabled] = React.useState(true)\n const [location, setLocation] = React.useState('')\n const [reminderMinutes, setReminderMinutes] = React.useState(15)\n const [visibility, setVisibility] = React.useState('team')\n const [participants, setParticipants] = React.useState<Participant[]>([])\n const [linkedEntities, setLinkedEntities] = React.useState<LinkedEntity[]>([])\n const [recurrenceEnabled, setRecurrenceEnabled] = React.useState(false)\n const [recurrenceDays, setRecurrenceDays] = React.useState<boolean[]>([true, false, true, false, false, false, false])\n const [recurrenceEndType, setRecurrenceEndType] = React.useState<'never' | 'count' | 'date'>('never')\n const [recurrenceCount, setRecurrenceCount] = React.useState(8)\n const [recurrenceEndDate, setRecurrenceEndDate] = React.useState('')\n const [conflict, setConflict] = React.useState<string | null>(null)\n const [saving, setSaving] = React.useState(false)\n const [guestPermissions, setGuestPermissions] = React.useState({ canInviteOthers: true, canModify: false, canSeeList: true })\n\n React.useEffect(() => {\n if (open) {\n if (editData) {\n // Edit mode: populate from existing interaction\n const resolvedType = (editData.interactionType as ActivityType) ?? 'meeting'\n setActivityType(resolvedType)\n setTitle(editData.title ?? '')\n // For historical activities the canonical timestamp is `occurredAt`; for\n // planned/future ones it's `scheduledAt`. Without this fallback editing a\n // past activity prefilled to \"today\" instead of its actual moment (#1807).\n // Keep seed values in the user's local timezone, matching the cluster-E\n // local-day convention.\n const sourceTimestamp = editData.occurredAt ?? editData.scheduledAt ?? null\n const seedDate = sourceTimestamp ? new Date(sourceTimestamp) : null\n const seedDateValid = seedDate !== null && !Number.isNaN(seedDate.getTime())\n // A real edit of an undated task must stay undated: falling back to a\n // computed default here would silently give a backlog item a due date on\n // the next save (#5941). Menu-driven \"New Task\" (no id yet, so `isEditing`\n // is false) still gets the create-mode default so #5940's forward-seeded\n // default keeps working.\n if (isEditing && !seedDateValid && !isDateRequired(resolvedType)) {\n setDate('')\n setStartTime('')\n } else {\n const dateForForm = seedDateValid ? (seedDate as Date) : resolveDefaultActivityStart(resolvedType, new Date())\n setDate(formatLocalDateInput(dateForForm))\n setStartTime(formatLocalTimeInput(dateForForm))\n }\n setDuration(editData.durationMinutes ?? 30)\n setAllDay(editData.allDay ?? false)\n setDescription(editData.body ?? '')\n setLocation(editData.location ?? '')\n // Use per-type default when the editData omits an explicit reminder\n // (the menu-driven \"New X\" flow opens the dialog with `reminderMinutes: null`).\n setReminderMinutes(editData.reminderMinutes ?? DEFAULT_REMINDER_MINUTES[resolvedType])\n setVisibility(editData.visibility ?? 'team')\n setParticipants(\n Array.isArray(editData.participants)\n ? editData.participants.map((p, i) => ({\n userId: p.userId,\n name: p.name ?? p.email ?? p.userId ?? '',\n email: p.email,\n color: PARTICIPANT_COLORS[i % PARTICIPANT_COLORS.length],\n status: (p.status ?? 'pending') as RsvpStatus,\n }))\n : [],\n )\n setLinkedEntities(\n Array.isArray(editData.linkedEntities)\n ? editData.linkedEntities.map((e) => ({ id: e.id, type: e.type as LinkedEntity['type'], label: e.label }))\n : [],\n )\n if (editData.recurrenceRule) {\n setRecurrenceEnabled(true)\n // Parse RRULE to set days and end type\n const rule = editData.recurrenceRule\n const byDayMatch = rule.match(/BYDAY=([A-Z,]+)/)\n if (byDayMatch) {\n const dayNames = ['MO', 'TU', 'WE', 'TH', 'FR', 'SA', 'SU']\n const activeDays = byDayMatch[1].split(',')\n setRecurrenceDays(dayNames.map((d) => activeDays.includes(d)))\n }\n const countMatch = rule.match(/COUNT=(\\d+)/)\n const untilMatch = rule.match(/UNTIL=(\\d{8})/)\n if (countMatch) {\n setRecurrenceEndType('count')\n setRecurrenceCount(Number(countMatch[1]))\n } else if (untilMatch) {\n setRecurrenceEndType('date')\n const raw = untilMatch[1]\n setRecurrenceEndDate(`${raw.slice(0, 4)}-${raw.slice(4, 6)}-${raw.slice(6, 8)}`)\n } else {\n setRecurrenceEndType('never')\n }\n } else {\n setRecurrenceEnabled(false)\n }\n if (editData.guestPermissions) {\n setGuestPermissions({\n canInviteOthers: editData.guestPermissions.canInviteOthers ?? true,\n canModify: editData.guestPermissions.canModify ?? false,\n canSeeList: editData.guestPermissions.canSeeList ?? true,\n })\n }\n } else {\n // Create mode: reset all fields\n const defaultStart = resolveDefaultActivityStart('meeting', new Date())\n setActivityType('meeting')\n setTitle('')\n setDate(formatLocalDateInput(defaultStart))\n setStartTime(formatLocalTimeInput(defaultStart))\n setDuration(30)\n setAllDay(false)\n setDescription('')\n setLocation('')\n setReminderMinutes(DEFAULT_REMINDER_MINUTES.meeting)\n setVisibility('team')\n setParticipants([])\n setLinkedEntities([])\n setRecurrenceEnabled(false)\n }\n setConflict(null)\n }\n return () => {\n // Safety net: restore body scroll if Radix Dialog fails to clean up\n document.body.style.removeProperty('overflow')\n document.body.style.removeProperty('pointer-events')\n }\n }, [open, editData, isEditing])\n\n // Update the Reminder default when the activity type changes in create mode.\n // Skipped in edit mode (the persisted value wins), and gated by `open` to\n // avoid flipping the default in a closed-but-mounted dialog.\n const lastReminderTypeRef = React.useRef<ActivityType>('meeting')\n React.useEffect(() => {\n if (!open || isEditing) {\n lastReminderTypeRef.current = activityType\n return\n }\n if (lastReminderTypeRef.current === activityType) return\n lastReminderTypeRef.current = activityType\n setReminderMinutes(DEFAULT_REMINDER_MINUTES[activityType])\n }, [activityType, isEditing, open])\n\n const removeParticipant = React.useCallback((index: number) => {\n setParticipants((prev) => prev.filter((_, i) => i !== index))\n }, [])\n\n const toggleRecurrenceDay = React.useCallback((index: number) => {\n setRecurrenceDays((prev) => {\n const next = [...prev]\n next[index] = !next[index]\n return next\n })\n }, [])\n\n return {\n activityType,\n setActivityType,\n title,\n setTitle,\n date,\n setDate,\n startTime,\n setStartTime,\n duration,\n setDuration,\n allDay,\n setAllDay,\n description,\n setDescription,\n markdownEnabled,\n setMarkdownEnabled,\n location,\n setLocation,\n reminderMinutes,\n setReminderMinutes,\n visibility,\n setVisibility,\n participants,\n setParticipants,\n linkedEntities,\n setLinkedEntities,\n recurrenceEnabled,\n setRecurrenceEnabled,\n recurrenceDays,\n setRecurrenceDays,\n recurrenceEndType,\n setRecurrenceEndType,\n recurrenceCount,\n setRecurrenceCount,\n recurrenceEndDate,\n setRecurrenceEndDate,\n conflict,\n setConflict,\n saving,\n setSaving,\n guestPermissions,\n setGuestPermissions,\n removeParticipant,\n toggleRecurrenceDay,\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -51,14 +51,18 @@ import {
|
|
|
51
51
|
getCustomerDictionaryManageHref
|
|
52
52
|
} from "../lib/dictionaries.js";
|
|
53
53
|
import { normalizeCustomFieldSubmitValue } from "./detail/customFieldUtils.js";
|
|
54
|
-
import {
|
|
54
|
+
import {
|
|
55
|
+
CUSTOMER_EMAIL_INVALID_MESSAGE_KEY,
|
|
56
|
+
CUSTOMER_PHONE_INVALID_MESSAGE_KEY,
|
|
57
|
+
CUSTOMER_URL_INVALID_MESSAGE_KEY
|
|
58
|
+
} from "../data/validators.js";
|
|
55
59
|
const metadata = {
|
|
56
60
|
navHidden: true
|
|
57
61
|
};
|
|
58
62
|
function cn(...values) {
|
|
59
63
|
return values.filter(Boolean).join(" ");
|
|
60
64
|
}
|
|
61
|
-
const emailValidationSchema = z.string().email();
|
|
65
|
+
const emailValidationSchema = z.string().email(CUSTOMER_EMAIL_INVALID_MESSAGE_KEY);
|
|
62
66
|
const EMAIL_CHECK_DEBOUNCE_MS = 350;
|
|
63
67
|
const createSectionHeadingField = (id, title) => ({
|
|
64
68
|
id,
|
|
@@ -311,7 +315,7 @@ const companyDictionaryFieldDefinitions = [
|
|
|
311
315
|
layout: "third"
|
|
312
316
|
}
|
|
313
317
|
];
|
|
314
|
-
const createPrimaryPhoneField = (t, defaultCountryIso2) => ({
|
|
318
|
+
const createPrimaryPhoneField = (t, defaultCountryIso2, phoneCountries) => ({
|
|
315
319
|
id: "primaryPhone",
|
|
316
320
|
label: t("customers.people.form.primaryPhone"),
|
|
317
321
|
type: "custom",
|
|
@@ -340,7 +344,8 @@ const createPrimaryPhoneField = (t, defaultCountryIso2) => ({
|
|
|
340
344
|
invalidLabel: t("customers.people.form.primaryPhone.invalid", "Enter a valid phone number with country code (e.g. +1 212 555 1234)"),
|
|
341
345
|
minDigits: 7,
|
|
342
346
|
onDuplicateLookup: !disabled && !error ? duplicateLookup : void 0,
|
|
343
|
-
defaultCountryIso2
|
|
347
|
+
defaultCountryIso2,
|
|
348
|
+
countries: phoneCountries
|
|
344
349
|
}
|
|
345
350
|
);
|
|
346
351
|
}
|
|
@@ -548,7 +553,7 @@ const createPersonFormSchema = () => z.object({
|
|
|
548
553
|
firstName: z.string().trim().min(1),
|
|
549
554
|
lastName: z.string().trim().min(1),
|
|
550
555
|
jobTitle: z.string().trim().optional().or(z.literal("")).transform((val) => val === "" ? void 0 : val).optional(),
|
|
551
|
-
primaryEmail: z.string().trim().email().optional().or(z.literal("")).transform((val) => val === "" ? void 0 : val),
|
|
556
|
+
primaryEmail: z.string().trim().email(CUSTOMER_EMAIL_INVALID_MESSAGE_KEY).optional().or(z.literal("")).transform((val) => val === "" ? void 0 : val),
|
|
552
557
|
primaryPhone: z.string().trim().max(50).refine((value) => isValidPhoneNumber(value), { message: CUSTOMER_PHONE_INVALID_MESSAGE_KEY }).optional().or(z.literal("")).transform((val) => val === "" ? void 0 : val).optional(),
|
|
553
558
|
status: z.string().trim().optional().or(z.literal("")).transform((val) => val === "" ? void 0 : val).optional(),
|
|
554
559
|
lifecycleStage: z.string().trim().optional().or(z.literal("")).transform((val) => val === "" ? void 0 : val).optional(),
|
|
@@ -625,6 +630,7 @@ const createDisplayNameSection = (t) => function DisplayNameSection({ values, se
|
|
|
625
630
|
};
|
|
626
631
|
const createPersonFormFields = (t, options) => {
|
|
627
632
|
const defaultCountryIso2 = options?.defaultCountryIso2;
|
|
633
|
+
const phoneCountries = options?.phoneCountries;
|
|
628
634
|
const contactSection = createSectionHeadingField("__contactInformationSection", t("customers.people.form.sections.contactInformation"));
|
|
629
635
|
const companySection = createSectionHeadingField("__companyInformationSection", t("customers.people.form.sections.companyInformation"));
|
|
630
636
|
const dictionaryFields = dictionaryFieldDefinitions.map((definition) => ({
|
|
@@ -686,7 +692,7 @@ const createPersonFormFields = (t, options) => {
|
|
|
686
692
|
},
|
|
687
693
|
contactSection,
|
|
688
694
|
createPrimaryEmailField(t),
|
|
689
|
-
createPrimaryPhoneField(t, defaultCountryIso2),
|
|
695
|
+
createPrimaryPhoneField(t, defaultCountryIso2, phoneCountries),
|
|
690
696
|
companySection,
|
|
691
697
|
{
|
|
692
698
|
id: "companyEntityId",
|
|
@@ -869,7 +875,7 @@ function buildPersonPayload(values, organizationId) {
|
|
|
869
875
|
}
|
|
870
876
|
const createCompanyFormSchema = () => z.object({
|
|
871
877
|
displayName: z.string().trim().min(1),
|
|
872
|
-
primaryEmail: z.string().trim().email().optional().or(z.literal("")).transform((val) => val === "" ? void 0 : val),
|
|
878
|
+
primaryEmail: z.string().trim().email(CUSTOMER_EMAIL_INVALID_MESSAGE_KEY).optional().or(z.literal("")).transform((val) => val === "" ? void 0 : val),
|
|
873
879
|
primaryPhone: z.string().trim().max(50).refine((value) => isValidPhoneNumber(value), { message: CUSTOMER_PHONE_INVALID_MESSAGE_KEY }).optional().or(z.literal("")).transform((val) => val === "" ? void 0 : val).optional(),
|
|
874
880
|
status: z.string().trim().optional().or(z.literal("")).transform((val) => val === "" ? void 0 : val).optional(),
|
|
875
881
|
lifecycleStage: z.string().trim().optional().or(z.literal("")).transform((val) => val === "" ? void 0 : val).optional(),
|
|
@@ -884,6 +890,7 @@ const createCompanyFormSchema = () => z.object({
|
|
|
884
890
|
}).passthrough();
|
|
885
891
|
const createCompanyFormFields = (t, options) => {
|
|
886
892
|
const defaultCountryIso2 = options?.defaultCountryIso2;
|
|
893
|
+
const phoneCountries = options?.phoneCountries;
|
|
887
894
|
const dictionaryFields = companyDictionaryFieldDefinitions.map((definition) => ({
|
|
888
895
|
id: definition.id,
|
|
889
896
|
label: t(definition.labelKey),
|
|
@@ -930,7 +937,8 @@ const createCompanyFormFields = (t, options) => {
|
|
|
930
937
|
placeholder: t("customers.companies.form.primaryPhonePlaceholder", "+1 555 123 4567"),
|
|
931
938
|
invalidLabel: t("customers.people.form.primaryPhone.invalid", "Enter a valid phone number with country code (e.g. +1 212 555 1234)"),
|
|
932
939
|
minDigits: 7,
|
|
933
|
-
defaultCountryIso2
|
|
940
|
+
defaultCountryIso2,
|
|
941
|
+
countries: phoneCountries
|
|
934
942
|
}
|
|
935
943
|
)
|
|
936
944
|
},
|
|
@@ -1137,7 +1145,7 @@ function buildCompanyPayload(values, organizationId) {
|
|
|
1137
1145
|
}
|
|
1138
1146
|
const optionalString = () => z.string().trim().optional().or(z.literal("")).transform((val) => val === "" ? void 0 : val).optional();
|
|
1139
1147
|
const clearableUrlField = () => z.string().trim().url(CUSTOMER_URL_INVALID_MESSAGE_KEY).optional().or(z.literal("")).transform((val) => val === "" ? null : val).optional();
|
|
1140
|
-
const clearableEmailField = () => z.string().trim().email().optional().or(z.literal("")).transform((val) => val === "" ? null : val).optional();
|
|
1148
|
+
const clearableEmailField = () => z.string().trim().email(CUSTOMER_EMAIL_INVALID_MESSAGE_KEY).optional().or(z.literal("")).transform((val) => val === "" ? null : val).optional();
|
|
1141
1149
|
const clearableDomainField = () => z.string().trim().max(200).optional().or(z.literal("")).transform((val) => val === "" ? null : val).optional();
|
|
1142
1150
|
const clearableTextField = () => z.string().trim().optional().or(z.literal("")).transform((val) => val === "" ? null : val).optional();
|
|
1143
1151
|
const clearablePhoneField = () => z.string().trim().max(50).refine((value) => value === "" || isValidPhoneNumber(value), { message: CUSTOMER_PHONE_INVALID_MESSAGE_KEY }).optional().or(z.literal("")).transform((val) => val === "" ? null : val).optional();
|