@open-mercato/core 0.5.1-develop.2953.6647bb2c43 → 0.5.1-develop.2964.d5ac4a6ebb
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/dist/helpers/integration/salesUi.js +25 -23
- package/dist/helpers/integration/salesUi.js.map +2 -2
- package/dist/modules/api_docs/frontend/docs/api/Explorer.js +24 -24
- package/dist/modules/api_docs/frontend/docs/api/Explorer.js.map +2 -2
- package/dist/modules/attachments/components/AttachmentPartitionSettings.js +15 -7
- package/dist/modules/attachments/components/AttachmentPartitionSettings.js.map +2 -2
- package/dist/modules/attachments/fields/attachment.js +4 -6
- package/dist/modules/attachments/fields/attachment.js.map +2 -2
- package/dist/modules/auth/backend/users/create/page.js +26 -26
- package/dist/modules/auth/backend/users/create/page.js.map +2 -2
- package/dist/modules/business_rules/components/ActionRow.js +36 -25
- package/dist/modules/business_rules/components/ActionRow.js.map +2 -2
- package/dist/modules/business_rules/components/ConditionGroup.js +14 -5
- package/dist/modules/business_rules/components/ConditionGroup.js.map +2 -2
- package/dist/modules/business_rules/components/ConditionRow.js +19 -10
- package/dist/modules/business_rules/components/ConditionRow.js.map +2 -2
- package/dist/modules/business_rules/components/RuleSetMembers.js +16 -10
- package/dist/modules/business_rules/components/RuleSetMembers.js.map +2 -2
- package/dist/modules/catalog/backend/catalog/products/[id]/page.js +30 -34
- package/dist/modules/catalog/backend/catalog/products/[id]/page.js.map +2 -2
- package/dist/modules/catalog/backend/catalog/products/create/page.js +220 -223
- package/dist/modules/catalog/backend/catalog/products/create/page.js.map +2 -2
- package/dist/modules/catalog/components/PriceKindSettings.js +20 -19
- package/dist/modules/catalog/components/PriceKindSettings.js.map +2 -2
- package/dist/modules/catalog/components/products/ProductUomSection.js +42 -37
- package/dist/modules/catalog/components/products/ProductUomSection.js.map +2 -2
- package/dist/modules/catalog/components/products/VariantBuilder.js +22 -18
- package/dist/modules/catalog/components/products/VariantBuilder.js.map +2 -2
- package/dist/modules/customer_accounts/backend/customer_accounts/users/[id]/page.js +18 -26
- package/dist/modules/customer_accounts/backend/customer_accounts/users/[id]/page.js.map +2 -2
- package/dist/modules/customer_accounts/backend/customer_accounts/users/page.js +4 -6
- package/dist/modules/customer_accounts/backend/customer_accounts/users/page.js.map +2 -2
- package/dist/modules/customer_accounts/widgets/injection/account-status/widget.client.js +5 -4
- package/dist/modules/customer_accounts/widgets/injection/account-status/widget.client.js.map +2 -2
- package/dist/modules/customers/backend/config/customers/pipeline-stages/page.js +19 -7
- package/dist/modules/customers/backend/config/customers/pipeline-stages/page.js.map +2 -2
- package/dist/modules/customers/backend/customers/deals/pipeline/page.js +24 -21
- package/dist/modules/customers/backend/customers/deals/pipeline/page.js.map +2 -2
- package/dist/modules/customers/components/AddressEditor.js +24 -7
- package/dist/modules/customers/components/AddressEditor.js.map +2 -2
- package/dist/modules/customers/components/AddressFormatSettings.js +35 -25
- package/dist/modules/customers/components/AddressFormatSettings.js.map +2 -2
- package/dist/modules/customers/components/detail/ActivityForm.js +20 -12
- package/dist/modules/customers/components/detail/ActivityForm.js.map +2 -2
- package/dist/modules/customers/components/detail/AnnualRevenueField.js +2 -2
- package/dist/modules/customers/components/detail/AnnualRevenueField.js.map +2 -2
- package/dist/modules/customers/components/detail/DealForm.js +19 -14
- package/dist/modules/customers/components/detail/DealForm.js.map +2 -2
- package/dist/modules/customers/components/formConfig.js +16 -12
- package/dist/modules/customers/components/formConfig.js.map +2 -2
- package/dist/modules/customers/widgets/dashboard/customer-todos/widget.client.js +3 -2
- package/dist/modules/customers/widgets/dashboard/customer-todos/widget.client.js.map +2 -2
- package/dist/modules/customers/widgets/dashboard/new-customers/widget.client.js +18 -10
- package/dist/modules/customers/widgets/dashboard/new-customers/widget.client.js.map +2 -2
- package/dist/modules/customers/widgets/dashboard/new-deals/widget.client.js +3 -2
- package/dist/modules/customers/widgets/dashboard/new-deals/widget.client.js.map +2 -2
- package/dist/modules/customers/widgets/dashboard/next-interactions/widget.client.js +3 -2
- package/dist/modules/customers/widgets/dashboard/next-interactions/widget.client.js.map +2 -2
- package/dist/modules/dashboards/components/WidgetVisibilityEditor.js +27 -28
- package/dist/modules/dashboards/components/WidgetVisibilityEditor.js.map +2 -2
- package/dist/modules/dashboards/widgets/dashboard/orders-by-status/widget.client.js +14 -6
- package/dist/modules/dashboards/widgets/dashboard/orders-by-status/widget.client.js.map +2 -2
- package/dist/modules/dashboards/widgets/dashboard/revenue-trend/widget.client.js +14 -6
- package/dist/modules/dashboards/widgets/dashboard/revenue-trend/widget.client.js.map +2 -2
- package/dist/modules/dashboards/widgets/dashboard/sales-by-region/widget.client.js +3 -2
- package/dist/modules/dashboards/widgets/dashboard/sales-by-region/widget.client.js.map +2 -2
- package/dist/modules/dashboards/widgets/dashboard/top-customers/widget.client.js +3 -2
- package/dist/modules/dashboards/widgets/dashboard/top-customers/widget.client.js.map +2 -2
- package/dist/modules/dashboards/widgets/dashboard/top-products/widget.client.js +17 -8
- package/dist/modules/dashboards/widgets/dashboard/top-products/widget.client.js.map +2 -2
- package/dist/modules/data_sync/backend/data-sync/page.js +40 -23
- package/dist/modules/data_sync/backend/data-sync/page.js.map +2 -2
- package/dist/modules/data_sync/components/IntegrationScheduleTab.js +15 -6
- package/dist/modules/data_sync/components/IntegrationScheduleTab.js.map +2 -2
- package/dist/modules/dictionaries/components/AppearanceSelector.js +4 -4
- package/dist/modules/dictionaries/components/AppearanceSelector.js.map +2 -2
- package/dist/modules/dictionaries/components/DictionaryEntriesEditor.js +4 -5
- package/dist/modules/dictionaries/components/DictionaryEntriesEditor.js.map +2 -2
- package/dist/modules/dictionaries/components/DictionaryEntrySelect.js +22 -14
- package/dist/modules/dictionaries/components/DictionaryEntrySelect.js.map +2 -2
- package/dist/modules/dictionaries/fields/dictionary.js +18 -13
- package/dist/modules/dictionaries/fields/dictionary.js.map +2 -2
- package/dist/modules/entities/components/EncryptionManager.js +23 -19
- package/dist/modules/entities/components/EncryptionManager.js.map +2 -2
- package/dist/modules/feature_toggles/components/formConfig.js +17 -9
- package/dist/modules/feature_toggles/components/formConfig.js.map +2 -2
- package/dist/modules/feature_toggles/components/overrideFormConfig.js +17 -9
- package/dist/modules/feature_toggles/components/overrideFormConfig.js.map +2 -2
- package/dist/modules/inbox_ops/backend/inbox-ops/settings/page.js +15 -8
- package/dist/modules/inbox_ops/backend/inbox-ops/settings/page.js.map +2 -2
- package/dist/modules/inbox_ops/components/proposals/EditActionDialog.js +37 -22
- package/dist/modules/inbox_ops/components/proposals/EditActionDialog.js.map +2 -2
- package/dist/modules/integrations/backend/integrations/[id]/page.js +22 -17
- package/dist/modules/integrations/backend/integrations/[id]/page.js.map +2 -2
- package/dist/modules/integrations/backend/integrations/bundle/[id]/page.js +12 -6
- package/dist/modules/integrations/backend/integrations/bundle/[id]/page.js.map +2 -2
- package/dist/modules/planner/components/AvailabilityRulesEditor.js +19 -12
- package/dist/modules/planner/components/AvailabilityRulesEditor.js.map +2 -2
- package/dist/modules/resources/components/ResourceCrudForm.js +15 -10
- package/dist/modules/resources/components/ResourceCrudForm.js.map +3 -3
- package/dist/modules/sales/backend/sales/documents/[id]/page.js +15 -18
- package/dist/modules/sales/backend/sales/documents/[id]/page.js.map +2 -2
- package/dist/modules/sales/components/ProviderFieldInput.js +23 -20
- package/dist/modules/sales/components/ProviderFieldInput.js.map +2 -2
- package/dist/modules/sales/components/ShippingMethodsSettings.js +25 -17
- package/dist/modules/sales/components/ShippingMethodsSettings.js.map +3 -3
- package/dist/modules/sales/components/channels/ChannelOfferForm.js +35 -42
- package/dist/modules/sales/components/channels/ChannelOfferForm.js.map +2 -2
- package/dist/modules/sales/components/documents/AddressesSection.js +87 -90
- package/dist/modules/sales/components/documents/AddressesSection.js.map +2 -2
- package/dist/modules/sales/components/documents/AdjustmentDialog.js +17 -6
- package/dist/modules/sales/components/documents/AdjustmentDialog.js.map +3 -3
- package/dist/modules/sales/components/documents/LineItemDialog.js +42 -25
- package/dist/modules/sales/components/documents/LineItemDialog.js.map +2 -2
- package/dist/modules/sales/components/documents/SalesDocumentForm.js +96 -87
- package/dist/modules/sales/components/documents/SalesDocumentForm.js.map +2 -2
- package/dist/modules/sales/widgets/dashboard/new-orders/widget.client.js +20 -11
- package/dist/modules/sales/widgets/dashboard/new-orders/widget.client.js.map +2 -2
- package/dist/modules/sales/widgets/dashboard/new-quotes/widget.client.js +20 -11
- package/dist/modules/sales/widgets/dashboard/new-quotes/widget.client.js.map +2 -2
- package/dist/modules/shipping_carriers/lib/shipment-wizard/components/ConfigureStep.js +36 -22
- package/dist/modules/shipping_carriers/lib/shipment-wizard/components/ConfigureStep.js.map +2 -2
- package/dist/modules/staff/components/TeamMemberForm.js +14 -9
- package/dist/modules/staff/components/TeamMemberForm.js.map +3 -3
- package/dist/modules/workflows/backend/tasks/[id]/page.js +42 -21
- package/dist/modules/workflows/backend/tasks/[id]/page.js.map +2 -2
- package/dist/modules/workflows/components/ActivitiesEditor.js +14 -6
- package/dist/modules/workflows/components/ActivitiesEditor.js.map +3 -3
- package/dist/modules/workflows/components/DefinitionTriggersEditor.js +25 -17
- package/dist/modules/workflows/components/DefinitionTriggersEditor.js.map +3 -3
- package/dist/modules/workflows/components/EdgeEditDialog.js +48 -45
- package/dist/modules/workflows/components/EdgeEditDialog.js.map +2 -2
- package/dist/modules/workflows/components/NodeEditDialog.js +90 -90
- package/dist/modules/workflows/components/NodeEditDialog.js.map +2 -2
- package/dist/modules/workflows/components/StepsEditor.js +14 -6
- package/dist/modules/workflows/components/StepsEditor.js.map +3 -3
- package/dist/modules/workflows/components/TransitionsEditor.js +31 -26
- package/dist/modules/workflows/components/TransitionsEditor.js.map +3 -3
- package/dist/modules/workflows/components/fields/ActivityArrayEditor.js +19 -11
- package/dist/modules/workflows/components/fields/ActivityArrayEditor.js.map +3 -3
- package/dist/modules/workflows/components/fields/BusinessRuleConditionsEditor.js +12 -14
- package/dist/modules/workflows/components/fields/BusinessRuleConditionsEditor.js.map +2 -2
- package/dist/modules/workflows/components/fields/FormFieldArrayEditor.js +24 -16
- package/dist/modules/workflows/components/fields/FormFieldArrayEditor.js.map +3 -3
- package/dist/modules/workflows/components/fields/StartPreConditionsEditor.js +12 -13
- package/dist/modules/workflows/components/fields/StartPreConditionsEditor.js.map +2 -2
- package/dist/modules/workflows/components/mobile/MobileTaskForm.js +12 -8
- package/dist/modules/workflows/components/mobile/MobileTaskForm.js.map +2 -2
- package/dist/modules/workflows/frontend/checkout-demo/page.js +43 -46
- package/dist/modules/workflows/frontend/checkout-demo/page.js.map +2 -2
- package/package.json +3 -3
- package/src/helpers/integration/salesUi.ts +40 -30
- package/src/modules/api_docs/frontend/docs/api/Explorer.tsx +25 -19
- package/src/modules/attachments/components/AttachmentPartitionSettings.tsx +21 -11
- package/src/modules/attachments/fields/attachment.tsx +4 -6
- package/src/modules/auth/backend/users/create/page.tsx +16 -20
- package/src/modules/business_rules/components/ActionRow.tsx +51 -32
- package/src/modules/business_rules/components/ConditionGroup.tsx +20 -9
- package/src/modules/business_rules/components/ConditionRow.tsx +24 -15
- package/src/modules/business_rules/components/RuleSetMembers.tsx +23 -13
- package/src/modules/catalog/backend/catalog/products/[id]/page.tsx +47 -53
- package/src/modules/catalog/backend/catalog/products/create/page.tsx +84 -87
- package/src/modules/catalog/components/PriceKindSettings.tsx +9 -9
- package/src/modules/catalog/components/products/ProductUomSection.tsx +85 -83
- package/src/modules/catalog/components/products/VariantBuilder.tsx +49 -33
- package/src/modules/customer_accounts/backend/customer_accounts/users/[id]/page.tsx +12 -27
- package/src/modules/customer_accounts/backend/customer_accounts/users/page.tsx +4 -6
- package/src/modules/customer_accounts/widgets/injection/account-status/widget.client.tsx +5 -4
- package/src/modules/customers/backend/config/customers/pipeline-stages/page.tsx +28 -15
- package/src/modules/customers/backend/customers/deals/pipeline/page.tsx +37 -26
- package/src/modules/customers/components/AddressEditor.tsx +30 -16
- package/src/modules/customers/components/AddressFormatSettings.tsx +25 -19
- package/src/modules/customers/components/detail/ActivityForm.tsx +35 -23
- package/src/modules/customers/components/detail/AnnualRevenueField.tsx +2 -2
- package/src/modules/customers/components/detail/DealForm.tsx +33 -20
- package/src/modules/customers/components/formConfig.tsx +25 -17
- package/src/modules/customers/widgets/dashboard/customer-todos/widget.client.tsx +3 -2
- package/src/modules/customers/widgets/dashboard/new-customers/widget.client.tsx +21 -11
- package/src/modules/customers/widgets/dashboard/new-deals/widget.client.tsx +3 -2
- package/src/modules/customers/widgets/dashboard/next-interactions/widget.client.tsx +3 -2
- package/src/modules/dashboards/components/WidgetVisibilityEditor.tsx +17 -22
- package/src/modules/dashboards/widgets/dashboard/orders-by-status/widget.client.tsx +17 -7
- package/src/modules/dashboards/widgets/dashboard/revenue-trend/widget.client.tsx +20 -10
- package/src/modules/dashboards/widgets/dashboard/sales-by-region/widget.client.tsx +3 -2
- package/src/modules/dashboards/widgets/dashboard/top-customers/widget.client.tsx +3 -2
- package/src/modules/dashboards/widgets/dashboard/top-products/widget.client.tsx +20 -9
- package/src/modules/data_sync/backend/data-sync/page.tsx +64 -38
- package/src/modules/data_sync/components/IntegrationScheduleTab.tsx +18 -7
- package/src/modules/dictionaries/components/AppearanceSelector.tsx +4 -4
- package/src/modules/dictionaries/components/DictionaryEntriesEditor.tsx +3 -4
- package/src/modules/dictionaries/components/DictionaryEntrySelect.tsx +27 -21
- package/src/modules/dictionaries/fields/dictionary.tsx +36 -23
- package/src/modules/entities/components/EncryptionManager.tsx +49 -33
- package/src/modules/feature_toggles/components/formConfig.tsx +20 -10
- package/src/modules/feature_toggles/components/overrideFormConfig.tsx +20 -10
- package/src/modules/inbox_ops/backend/inbox-ops/settings/page.tsx +19 -10
- package/src/modules/inbox_ops/components/proposals/EditActionDialog.tsx +49 -26
- package/src/modules/integrations/backend/integrations/[id]/page.tsx +20 -11
- package/src/modules/integrations/backend/integrations/bundle/[id]/page.tsx +19 -9
- package/src/modules/planner/components/AvailabilityRulesEditor.tsx +34 -21
- package/src/modules/resources/components/ResourceCrudForm.tsx +24 -15
- package/src/modules/sales/backend/sales/documents/[id]/page.tsx +12 -15
- package/src/modules/sales/components/ProviderFieldInput.tsx +26 -17
- package/src/modules/sales/components/ShippingMethodsSettings.tsx +28 -20
- package/src/modules/sales/components/channels/ChannelOfferForm.tsx +51 -46
- package/src/modules/sales/components/documents/AddressesSection.tsx +78 -76
- package/src/modules/sales/components/documents/AdjustmentDialog.tsx +27 -15
- package/src/modules/sales/components/documents/LineItemDialog.tsx +69 -51
- package/src/modules/sales/components/documents/SalesDocumentForm.tsx +98 -87
- package/src/modules/sales/widgets/dashboard/new-orders/widget.client.tsx +23 -12
- package/src/modules/sales/widgets/dashboard/new-quotes/widget.client.tsx +23 -12
- package/src/modules/shipping_carriers/lib/shipment-wizard/components/ConfigureStep.tsx +35 -19
- package/src/modules/staff/components/TeamMemberForm.tsx +23 -14
- package/src/modules/workflows/backend/tasks/[id]/page.tsx +51 -23
- package/src/modules/workflows/components/ActivitiesEditor.tsx +20 -10
- package/src/modules/workflows/components/DefinitionTriggersEditor.tsx +28 -18
- package/src/modules/workflows/components/EdgeEditDialog.tsx +51 -40
- package/src/modules/workflows/components/NodeEditDialog.tsx +81 -77
- package/src/modules/workflows/components/StepsEditor.tsx +20 -10
- package/src/modules/workflows/components/TransitionsEditor.tsx +61 -44
- package/src/modules/workflows/components/fields/ActivityArrayEditor.tsx +22 -12
- package/src/modules/workflows/components/fields/BusinessRuleConditionsEditor.tsx +9 -13
- package/src/modules/workflows/components/fields/FormFieldArrayEditor.tsx +27 -17
- package/src/modules/workflows/components/fields/StartPreConditionsEditor.tsx +9 -12
- package/src/modules/workflows/components/mobile/MobileTaskForm.tsx +19 -11
- package/src/modules/workflows/frontend/checkout-demo/page.tsx +71 -60
|
@@ -5,6 +5,13 @@ import { z } from "zod";
|
|
|
5
5
|
import { useT } from "@open-mercato/shared/lib/i18n/context";
|
|
6
6
|
import { CrudForm } from "@open-mercato/ui/backend/CrudForm";
|
|
7
7
|
import { Button } from "@open-mercato/ui/primitives/button";
|
|
8
|
+
import {
|
|
9
|
+
Select,
|
|
10
|
+
SelectContent,
|
|
11
|
+
SelectItem,
|
|
12
|
+
SelectTrigger,
|
|
13
|
+
SelectValue
|
|
14
|
+
} from "@open-mercato/ui/primitives/select";
|
|
8
15
|
import { collectCustomFieldValues } from "@open-mercato/ui/backend/utils/customFieldValues";
|
|
9
16
|
import { createCrudFormError } from "@open-mercato/ui/backend/utils/serverErrors";
|
|
10
17
|
import { DictionaryEntrySelect } from "@open-mercato/core/modules/dictionaries/components/DictionaryEntrySelect";
|
|
@@ -89,13 +96,15 @@ function ActivityForm({
|
|
|
89
96
|
layout: "half",
|
|
90
97
|
component: ({ value, setValue }) => {
|
|
91
98
|
const currentValue = typeof value === "string" && value.length ? value : normalizedEntityOptions[0]?.id ?? "";
|
|
92
|
-
return /* @__PURE__ */
|
|
93
|
-
|
|
99
|
+
return /* @__PURE__ */ jsxs(
|
|
100
|
+
Select,
|
|
94
101
|
{
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
102
|
+
value: currentValue || void 0,
|
|
103
|
+
onValueChange: (next) => setValue(next ?? ""),
|
|
104
|
+
children: [
|
|
105
|
+
/* @__PURE__ */ jsx(SelectTrigger, { children: /* @__PURE__ */ jsx(SelectValue, {}) }),
|
|
106
|
+
/* @__PURE__ */ jsx(SelectContent, { children: normalizedEntityOptions.map((option) => /* @__PURE__ */ jsx(SelectItem, { value: option.id, children: option.label }, option.id)) })
|
|
107
|
+
]
|
|
99
108
|
}
|
|
100
109
|
);
|
|
101
110
|
}
|
|
@@ -110,14 +119,13 @@ function ActivityForm({
|
|
|
110
119
|
component: ({ value, setValue }) => {
|
|
111
120
|
const currentValue = typeof value === "string" ? value : "";
|
|
112
121
|
return /* @__PURE__ */ jsxs(
|
|
113
|
-
|
|
122
|
+
Select,
|
|
114
123
|
{
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
onChange: (event) => setValue(event.target.value),
|
|
124
|
+
value: currentValue || void 0,
|
|
125
|
+
onValueChange: (next) => setValue(next ?? ""),
|
|
118
126
|
children: [
|
|
119
|
-
/* @__PURE__ */ jsx(
|
|
120
|
-
normalizedDealOptions.map((option) => /* @__PURE__ */ jsx(
|
|
127
|
+
/* @__PURE__ */ jsx(SelectTrigger, { children: /* @__PURE__ */ jsx(SelectValue, { placeholder: t("customers.people.detail.activities.fields.dealPlaceholder", "No linked deal") }) }),
|
|
128
|
+
/* @__PURE__ */ jsx(SelectContent, { children: normalizedDealOptions.map((option) => /* @__PURE__ */ jsx(SelectItem, { value: option.id, children: option.label }, option.id)) })
|
|
121
129
|
]
|
|
122
130
|
}
|
|
123
131
|
);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../src/modules/customers/components/detail/ActivityForm.tsx"],
|
|
4
|
-
"sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { z } from 'zod'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { CrudForm, type CrudField, type CrudFormGroup } from '@open-mercato/ui/backend/CrudForm'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { collectCustomFieldValues } from '@open-mercato/ui/backend/utils/customFieldValues'\nimport { createCrudFormError } from '@open-mercato/ui/backend/utils/serverErrors'\nimport { DictionaryEntrySelect, type DictionarySelectLabels } from '@open-mercato/core/modules/dictionaries/components/DictionaryEntrySelect'\nimport { E } from '#generated/entities.ids.generated'\nimport { toLocalDateTimeInput } from './utils'\nimport { normalizeCustomFieldSubmitValue } from './customFieldUtils'\n\ntype DictionaryOption = {\n value: string\n label: string\n color: string | null\n icon: string | null\n}\n\nexport type ActivityFormBaseValues = {\n activityType: string\n subject?: string | null\n body?: string | null\n occurredAt?: string | null\n dealId?: string | null\n}\n\nexport type ActivityFormSubmitPayload = {\n base: ActivityFormBaseValues\n custom: Record<string, unknown>\n entityId?: string | null\n}\n\nexport type ActivityFormProps = {\n mode: 'create' | 'edit'\n initialValues?: Partial<ActivityFormBaseValues & Record<string, unknown>>\n onSubmit: (payload: ActivityFormSubmitPayload) => Promise<void>\n onCancel: () => void\n submitLabel?: string\n cancelLabel?: string\n isSubmitting?: boolean\n activityTypeLabels: DictionarySelectLabels\n loadActivityOptions: () => Promise<DictionaryOption[]>\n createActivityOption?: (input: { value: string; label?: string; color?: string | null; icon?: string | null }) => Promise<DictionaryOption>\n dealOptions?: Array<{ id: string; label: string }>\n entityOptions?: Array<{ id: string; label: string }>\n defaultEntityId?: string | null\n}\n\nconst schema = z.object({\n activityType: z.string().min(1),\n subject: z.string().transform((value) => value.trim()).optional(),\n body: z.string().transform((value) => value.trim()).optional(),\n occurredAt: z\n .string()\n .transform((value) => value.trim())\n .refine((value) => {\n if (!value) return true\n const parsed = new Date(value)\n return !Number.isNaN(parsed.getTime())\n }, { message: 'customers.people.detail.activities.invalidDate' })\n .optional(),\n}).passthrough()\n\nconst ACTIVITY_ENTITY_IDS = [E.customers.customer_activity]\n\nexport function ActivityForm({\n mode,\n initialValues,\n onSubmit,\n onCancel,\n submitLabel,\n cancelLabel,\n isSubmitting = false,\n activityTypeLabels,\n loadActivityOptions,\n createActivityOption,\n dealOptions,\n entityOptions,\n defaultEntityId,\n}: ActivityFormProps) {\n const t = useT()\n const [pending, setPending] = React.useState(false)\n\n const dictionaryAppearanceLabels = React.useMemo(\n () => ({\n colorLabel: t('customers.config.dictionaries.dialog.colorLabel', 'Color'),\n colorHelp: t('customers.config.dictionaries.dialog.colorHelp', 'Pick a highlight color for this entry.'),\n colorClearLabel: t('customers.config.dictionaries.dialog.colorClear', 'Remove color'),\n iconLabel: t('customers.config.dictionaries.dialog.iconLabel', 'Icon or emoji'),\n iconPlaceholder: t('customers.config.dictionaries.dialog.iconPlaceholder', 'Type an emoji or pick one of the suggestions.'),\n iconPickerTriggerLabel: t('customers.config.dictionaries.dialog.iconBrowse', 'Browse icons and emojis'),\n iconSearchPlaceholder: t('customers.config.dictionaries.dialog.iconSearchPlaceholder', 'Search icons or emojis\u2026'),\n iconSearchEmptyLabel: t('customers.config.dictionaries.dialog.iconSearchEmpty', 'No icons match your search.'),\n iconSuggestionsLabel: t('customers.config.dictionaries.dialog.iconSuggestions', 'Suggestions'),\n iconClearLabel: t('customers.config.dictionaries.dialog.iconClear', 'Remove icon'),\n previewEmptyLabel: t('customers.config.dictionaries.dialog.previewEmpty', 'No appearance selected'),\n }),\n [t],\n )\n\n const normalizedDealOptions = React.useMemo(() => {\n if (!Array.isArray(dealOptions)) return []\n const seen = new Set<string>()\n return dealOptions\n .map((option) => {\n if (!option || typeof option !== 'object') return null\n const id = typeof option.id === 'string' ? option.id.trim() : ''\n if (!id || seen.has(id)) return null\n const label =\n typeof option.label === 'string' && option.label.trim().length\n ? option.label.trim()\n : id\n seen.add(id)\n return { id, label }\n })\n .filter((option): option is { id: string; label: string } => !!option)\n }, [dealOptions])\n\n const normalizedEntityOptions = React.useMemo(() => {\n if (!Array.isArray(entityOptions)) return []\n const seen = new Set<string>()\n return entityOptions\n .map((option) => {\n if (!option || typeof option !== 'object') return null\n const id = typeof option.id === 'string' ? option.id.trim() : ''\n if (!id || seen.has(id)) return null\n const label =\n typeof option.label === 'string' && option.label.trim().length\n ? option.label.trim()\n : id\n seen.add(id)\n return { id, label }\n })\n .filter((option): option is { id: string; label: string } => !!option)\n }, [entityOptions])\n\n const baseFields = React.useMemo<CrudField[]>(() => {\n const fields: CrudField[] = []\n\n if (normalizedEntityOptions.length) {\n fields.push({\n id: 'entityId',\n label: t('customers.people.detail.activities.fields.entity', 'Assign to customer'),\n type: 'custom',\n layout: 'half',\n component: ({ value, setValue }) => {\n const currentValue =\n typeof value === 'string' && value.length ? value : normalizedEntityOptions[0]?.id ?? ''\n return (\n <select\n className=\"h-9 w-full rounded border border-muted-foreground/40 bg-background px-2 text-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\"\n value={currentValue}\n onChange={(event) => setValue(event.target.value)}\n >\n {normalizedEntityOptions.map((option) => (\n <option key={option.id} value={option.id}>\n {option.label}\n </option>\n ))}\n </select>\n )\n },\n } as CrudField)\n }\n\n if (normalizedDealOptions.length) {\n fields.push({\n id: 'dealId',\n label: t('customers.people.detail.activities.fields.deal', 'Link to deal (optional)'),\n type: 'custom',\n layout: 'half',\n component: ({ value, setValue }) => {\n const currentValue = typeof value === 'string' ? value : ''\n return (\n <select\n className=\"h-9 w-full rounded border border-muted-foreground/40 bg-background px-2 text-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\"\n value={currentValue}\n onChange={(event) => setValue(event.target.value)}\n >\n <option value=\"\">\n {t('customers.people.detail.activities.fields.dealPlaceholder', 'No linked deal')}\n </option>\n {normalizedDealOptions.map((option) => (\n <option key={option.id} value={option.id}>\n {option.label}\n </option>\n ))}\n </select>\n )\n },\n } as CrudField)\n }\n\n fields.push({\n id: 'activityType',\n label: t('customers.people.detail.activities.fields.type'),\n type: 'custom',\n required: true,\n layout: 'half',\n component: ({ value, setValue }) => (\n <DictionaryEntrySelect\n value={typeof value === 'string' ? value : undefined}\n onChange={(next) => setValue(next ?? '')}\n fetchOptions={loadActivityOptions}\n createOption={createActivityOption}\n labels={activityTypeLabels}\n allowAppearance\n allowInlineCreate\n appearanceLabels={dictionaryAppearanceLabels}\n selectClassName=\"w-full\"\n manageHref=\"/backend/config/customers\"\n />\n ),\n } as CrudField)\n\n fields.push({\n id: 'subject',\n label: t('customers.people.detail.activities.fields.subject'),\n type: 'text',\n layout: 'half',\n placeholder: t('customers.people.detail.activities.subjectPlaceholder', 'Add a subject (optional)'),\n } as CrudField)\n\n fields.push({\n id: 'body',\n label: t('customers.people.detail.activities.fields.body'),\n type: 'textarea',\n placeholder: t('customers.people.detail.activities.bodyPlaceholder', 'Describe the interaction'),\n } as CrudField)\n\n fields.push({\n id: 'occurredAt',\n label: t('customers.people.detail.activities.fields.occurredAt'),\n type: 'custom',\n component: ({ value, setValue }) => (\n <input\n type=\"datetime-local\"\n className=\"w-full rounded-md border px-3 py-2 text-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\"\n value={typeof value === 'string' ? value : ''}\n onChange={(event) => setValue(event.target.value || '')}\n onFocus={(event) => {\n const target = event.currentTarget as HTMLInputElement & { showPicker?: () => void }\n if (typeof target.showPicker === 'function') {\n try { target.showPicker() } catch { /* ignore unsupported */ }\n }\n }}\n onClick={(event) => {\n const target = event.currentTarget as HTMLInputElement & { showPicker?: () => void }\n if (typeof target.showPicker === 'function') {\n try { target.showPicker() } catch { /* ignore unsupported */ }\n }\n }}\n />\n ),\n layout: 'half',\n } as CrudField)\n\n return fields\n }, [\n activityTypeLabels,\n createActivityOption,\n dictionaryAppearanceLabels,\n loadActivityOptions,\n normalizedDealOptions,\n normalizedEntityOptions,\n t,\n ])\n\n const baseFieldIds = React.useMemo(() => new Set(baseFields.map((field) => field.id)), [baseFields])\n\n const groups = React.useMemo<CrudFormGroup[]>(() => {\n const detailFields: string[] = []\n if (normalizedEntityOptions.length) detailFields.push('entityId')\n if (normalizedDealOptions.length) detailFields.push('dealId')\n detailFields.push('activityType', 'subject', 'occurredAt', 'body')\n return [\n {\n id: 'details',\n title: t('customers.people.detail.activities.form.details', 'Activity details'),\n column: 1,\n fields: detailFields,\n },\n {\n id: 'custom',\n title: t('customers.people.detail.activities.form.customFields', 'Custom fields'),\n column: 2,\n kind: 'customFields',\n },\n ]\n }, [normalizedDealOptions.length, normalizedEntityOptions.length, t])\n\n const handleSubmit = React.useCallback(\n async (values: Record<string, unknown>) => {\n if (pending || isSubmitting) return\n setPending(true)\n try {\n const parsed = schema.safeParse(values)\n if (!parsed.success) {\n throw buildActivityValidationError(parsed.error.issues, t)\n }\n const rawEntityId = typeof values.entityId === 'string' ? values.entityId.trim() : ''\n const resolvedEntityId = rawEntityId || (typeof defaultEntityId === 'string' ? defaultEntityId : '')\n const rawDealId = typeof values.dealId === 'string' ? values.dealId.trim() : ''\n const base: ActivityFormBaseValues = {\n activityType: parsed.data.activityType,\n subject: parsed.data.subject || undefined,\n body: parsed.data.body || undefined,\n occurredAt: parsed.data.occurredAt && parsed.data.occurredAt.length\n ? new Date(parsed.data.occurredAt).toISOString()\n : undefined,\n dealId: rawDealId.length ? rawDealId : undefined,\n }\n const reservedCustomKeys = new Set(['entityId', 'dealId'])\n const customEntries = collectCustomFieldValues(values, {\n transform: (value) => normalizeCustomFieldSubmitValue(value),\n accept: (fieldId) => !reservedCustomKeys.has(fieldId),\n })\n Object.entries(values).forEach(([key, value]) => {\n if (key.startsWith('cf_')) return\n if (!baseFieldIds.has(key) && key !== 'id') {\n if (reservedCustomKeys.has(key)) return\n customEntries[key] = normalizeCustomFieldSubmitValue(value)\n }\n })\n await onSubmit({ base, custom: customEntries, entityId: resolvedEntityId.length ? resolvedEntityId : undefined })\n } finally {\n setPending(false)\n }\n },\n [baseFieldIds, defaultEntityId, isSubmitting, onSubmit, pending, t],\n )\n\n const embeddedInitialValues = React.useMemo(() => {\n const occurredAt = toLocalDateTimeInput(initialValues?.occurredAt ?? null)\n const resolvedEntity = (() => {\n const raw = typeof (initialValues as Record<string, unknown> | undefined)?.entityId === 'string'\n ? (initialValues as Record<string, unknown>).entityId as string\n : typeof defaultEntityId === 'string'\n ? defaultEntityId\n : normalizedEntityOptions[0]?.id ?? ''\n return raw ?? ''\n })()\n const resolvedDeal = typeof (initialValues as Record<string, unknown> | undefined)?.dealId === 'string'\n ? (initialValues as Record<string, unknown>).dealId as string\n : ''\n\n return {\n entityId: resolvedEntity,\n dealId: resolvedDeal,\n activityType: initialValues?.activityType ?? '',\n subject: initialValues?.subject ?? '',\n body: initialValues?.body ?? '',\n occurredAt,\n ...Object.fromEntries(\n Object.entries(initialValues ?? {})\n .filter(([key]) => {\n if (!key.startsWith('cf_')) return false\n const trimmed = key.slice(3)\n return trimmed !== 'entityId' && trimmed !== 'dealId'\n })\n .map(([key, value]) => [key, value]),\n ),\n }\n }, [defaultEntityId, initialValues, normalizedEntityOptions])\n\n return (\n <CrudForm<Record<string, unknown>>\n embedded\n fields={baseFields}\n groups={groups}\n initialValues={embeddedInitialValues}\n onSubmit={handleSubmit}\n submitLabel={submitLabel ?? (mode === 'edit'\n ? t('customers.people.detail.activities.update', 'Update activity (\u2318/Ctrl + Enter)')\n : t('customers.people.detail.activities.save', 'Save activity (\u2318/Ctrl + Enter)'))}\n extraActions={(\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={onCancel}\n disabled={pending || isSubmitting}\n >\n {cancelLabel ?? t('customers.people.detail.activities.cancel', 'Cancel')}\n </Button>\n )}\n entityIds={ACTIVITY_ENTITY_IDS}\n />\n )\n}\n\nexport function buildActivityValidationError(issues: z.ZodIssue[], t: (key: string, fallback?: string) => string) {\n const issue = issues[0]\n const message = issue?.message ?? t('customers.people.detail.activities.error')\n const firstPath = Array.isArray(issue?.path) ? issue?.path?.[0] : undefined\n const field = typeof firstPath === 'string' ? firstPath : undefined\n throw createCrudFormError(message, field ? { [field]: message } : undefined)\n}\n"],
|
|
5
|
-
"mappings": ";
|
|
4
|
+
"sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { z } from 'zod'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { CrudForm, type CrudField, type CrudFormGroup } from '@open-mercato/ui/backend/CrudForm'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from '@open-mercato/ui/primitives/select'\nimport { collectCustomFieldValues } from '@open-mercato/ui/backend/utils/customFieldValues'\nimport { createCrudFormError } from '@open-mercato/ui/backend/utils/serverErrors'\nimport { DictionaryEntrySelect, type DictionarySelectLabels } from '@open-mercato/core/modules/dictionaries/components/DictionaryEntrySelect'\nimport { E } from '#generated/entities.ids.generated'\nimport { toLocalDateTimeInput } from './utils'\nimport { normalizeCustomFieldSubmitValue } from './customFieldUtils'\n\ntype DictionaryOption = {\n value: string\n label: string\n color: string | null\n icon: string | null\n}\n\nexport type ActivityFormBaseValues = {\n activityType: string\n subject?: string | null\n body?: string | null\n occurredAt?: string | null\n dealId?: string | null\n}\n\nexport type ActivityFormSubmitPayload = {\n base: ActivityFormBaseValues\n custom: Record<string, unknown>\n entityId?: string | null\n}\n\nexport type ActivityFormProps = {\n mode: 'create' | 'edit'\n initialValues?: Partial<ActivityFormBaseValues & Record<string, unknown>>\n onSubmit: (payload: ActivityFormSubmitPayload) => Promise<void>\n onCancel: () => void\n submitLabel?: string\n cancelLabel?: string\n isSubmitting?: boolean\n activityTypeLabels: DictionarySelectLabels\n loadActivityOptions: () => Promise<DictionaryOption[]>\n createActivityOption?: (input: { value: string; label?: string; color?: string | null; icon?: string | null }) => Promise<DictionaryOption>\n dealOptions?: Array<{ id: string; label: string }>\n entityOptions?: Array<{ id: string; label: string }>\n defaultEntityId?: string | null\n}\n\nconst schema = z.object({\n activityType: z.string().min(1),\n subject: z.string().transform((value) => value.trim()).optional(),\n body: z.string().transform((value) => value.trim()).optional(),\n occurredAt: z\n .string()\n .transform((value) => value.trim())\n .refine((value) => {\n if (!value) return true\n const parsed = new Date(value)\n return !Number.isNaN(parsed.getTime())\n }, { message: 'customers.people.detail.activities.invalidDate' })\n .optional(),\n}).passthrough()\n\nconst ACTIVITY_ENTITY_IDS = [E.customers.customer_activity]\n\nexport function ActivityForm({\n mode,\n initialValues,\n onSubmit,\n onCancel,\n submitLabel,\n cancelLabel,\n isSubmitting = false,\n activityTypeLabels,\n loadActivityOptions,\n createActivityOption,\n dealOptions,\n entityOptions,\n defaultEntityId,\n}: ActivityFormProps) {\n const t = useT()\n const [pending, setPending] = React.useState(false)\n\n const dictionaryAppearanceLabels = React.useMemo(\n () => ({\n colorLabel: t('customers.config.dictionaries.dialog.colorLabel', 'Color'),\n colorHelp: t('customers.config.dictionaries.dialog.colorHelp', 'Pick a highlight color for this entry.'),\n colorClearLabel: t('customers.config.dictionaries.dialog.colorClear', 'Remove color'),\n iconLabel: t('customers.config.dictionaries.dialog.iconLabel', 'Icon or emoji'),\n iconPlaceholder: t('customers.config.dictionaries.dialog.iconPlaceholder', 'Type an emoji or pick one of the suggestions.'),\n iconPickerTriggerLabel: t('customers.config.dictionaries.dialog.iconBrowse', 'Browse icons and emojis'),\n iconSearchPlaceholder: t('customers.config.dictionaries.dialog.iconSearchPlaceholder', 'Search icons or emojis\u2026'),\n iconSearchEmptyLabel: t('customers.config.dictionaries.dialog.iconSearchEmpty', 'No icons match your search.'),\n iconSuggestionsLabel: t('customers.config.dictionaries.dialog.iconSuggestions', 'Suggestions'),\n iconClearLabel: t('customers.config.dictionaries.dialog.iconClear', 'Remove icon'),\n previewEmptyLabel: t('customers.config.dictionaries.dialog.previewEmpty', 'No appearance selected'),\n }),\n [t],\n )\n\n const normalizedDealOptions = React.useMemo(() => {\n if (!Array.isArray(dealOptions)) return []\n const seen = new Set<string>()\n return dealOptions\n .map((option) => {\n if (!option || typeof option !== 'object') return null\n const id = typeof option.id === 'string' ? option.id.trim() : ''\n if (!id || seen.has(id)) return null\n const label =\n typeof option.label === 'string' && option.label.trim().length\n ? option.label.trim()\n : id\n seen.add(id)\n return { id, label }\n })\n .filter((option): option is { id: string; label: string } => !!option)\n }, [dealOptions])\n\n const normalizedEntityOptions = React.useMemo(() => {\n if (!Array.isArray(entityOptions)) return []\n const seen = new Set<string>()\n return entityOptions\n .map((option) => {\n if (!option || typeof option !== 'object') return null\n const id = typeof option.id === 'string' ? option.id.trim() : ''\n if (!id || seen.has(id)) return null\n const label =\n typeof option.label === 'string' && option.label.trim().length\n ? option.label.trim()\n : id\n seen.add(id)\n return { id, label }\n })\n .filter((option): option is { id: string; label: string } => !!option)\n }, [entityOptions])\n\n const baseFields = React.useMemo<CrudField[]>(() => {\n const fields: CrudField[] = []\n\n if (normalizedEntityOptions.length) {\n fields.push({\n id: 'entityId',\n label: t('customers.people.detail.activities.fields.entity', 'Assign to customer'),\n type: 'custom',\n layout: 'half',\n component: ({ value, setValue }) => {\n const currentValue =\n typeof value === 'string' && value.length ? value : normalizedEntityOptions[0]?.id ?? ''\n return (\n <Select\n value={currentValue || undefined}\n onValueChange={(next) => setValue(next ?? '')}\n >\n <SelectTrigger>\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {normalizedEntityOptions.map((option) => (\n <SelectItem key={option.id} value={option.id}>\n {option.label}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n )\n },\n } as CrudField)\n }\n\n if (normalizedDealOptions.length) {\n fields.push({\n id: 'dealId',\n label: t('customers.people.detail.activities.fields.deal', 'Link to deal (optional)'),\n type: 'custom',\n layout: 'half',\n component: ({ value, setValue }) => {\n const currentValue = typeof value === 'string' ? value : ''\n return (\n <Select\n value={currentValue || undefined}\n onValueChange={(next) => setValue(next ?? '')}\n >\n <SelectTrigger>\n <SelectValue placeholder={t('customers.people.detail.activities.fields.dealPlaceholder', 'No linked deal')} />\n </SelectTrigger>\n <SelectContent>\n {normalizedDealOptions.map((option) => (\n <SelectItem key={option.id} value={option.id}>\n {option.label}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n )\n },\n } as CrudField)\n }\n\n fields.push({\n id: 'activityType',\n label: t('customers.people.detail.activities.fields.type'),\n type: 'custom',\n required: true,\n layout: 'half',\n component: ({ value, setValue }) => (\n <DictionaryEntrySelect\n value={typeof value === 'string' ? value : undefined}\n onChange={(next) => setValue(next ?? '')}\n fetchOptions={loadActivityOptions}\n createOption={createActivityOption}\n labels={activityTypeLabels}\n allowAppearance\n allowInlineCreate\n appearanceLabels={dictionaryAppearanceLabels}\n selectClassName=\"w-full\"\n manageHref=\"/backend/config/customers\"\n />\n ),\n } as CrudField)\n\n fields.push({\n id: 'subject',\n label: t('customers.people.detail.activities.fields.subject'),\n type: 'text',\n layout: 'half',\n placeholder: t('customers.people.detail.activities.subjectPlaceholder', 'Add a subject (optional)'),\n } as CrudField)\n\n fields.push({\n id: 'body',\n label: t('customers.people.detail.activities.fields.body'),\n type: 'textarea',\n placeholder: t('customers.people.detail.activities.bodyPlaceholder', 'Describe the interaction'),\n } as CrudField)\n\n fields.push({\n id: 'occurredAt',\n label: t('customers.people.detail.activities.fields.occurredAt'),\n type: 'custom',\n component: ({ value, setValue }) => (\n <input\n type=\"datetime-local\"\n className=\"w-full rounded-md border px-3 py-2 text-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\"\n value={typeof value === 'string' ? value : ''}\n onChange={(event) => setValue(event.target.value || '')}\n onFocus={(event) => {\n const target = event.currentTarget as HTMLInputElement & { showPicker?: () => void }\n if (typeof target.showPicker === 'function') {\n try { target.showPicker() } catch { /* ignore unsupported */ }\n }\n }}\n onClick={(event) => {\n const target = event.currentTarget as HTMLInputElement & { showPicker?: () => void }\n if (typeof target.showPicker === 'function') {\n try { target.showPicker() } catch { /* ignore unsupported */ }\n }\n }}\n />\n ),\n layout: 'half',\n } as CrudField)\n\n return fields\n }, [\n activityTypeLabels,\n createActivityOption,\n dictionaryAppearanceLabels,\n loadActivityOptions,\n normalizedDealOptions,\n normalizedEntityOptions,\n t,\n ])\n\n const baseFieldIds = React.useMemo(() => new Set(baseFields.map((field) => field.id)), [baseFields])\n\n const groups = React.useMemo<CrudFormGroup[]>(() => {\n const detailFields: string[] = []\n if (normalizedEntityOptions.length) detailFields.push('entityId')\n if (normalizedDealOptions.length) detailFields.push('dealId')\n detailFields.push('activityType', 'subject', 'occurredAt', 'body')\n return [\n {\n id: 'details',\n title: t('customers.people.detail.activities.form.details', 'Activity details'),\n column: 1,\n fields: detailFields,\n },\n {\n id: 'custom',\n title: t('customers.people.detail.activities.form.customFields', 'Custom fields'),\n column: 2,\n kind: 'customFields',\n },\n ]\n }, [normalizedDealOptions.length, normalizedEntityOptions.length, t])\n\n const handleSubmit = React.useCallback(\n async (values: Record<string, unknown>) => {\n if (pending || isSubmitting) return\n setPending(true)\n try {\n const parsed = schema.safeParse(values)\n if (!parsed.success) {\n throw buildActivityValidationError(parsed.error.issues, t)\n }\n const rawEntityId = typeof values.entityId === 'string' ? values.entityId.trim() : ''\n const resolvedEntityId = rawEntityId || (typeof defaultEntityId === 'string' ? defaultEntityId : '')\n const rawDealId = typeof values.dealId === 'string' ? values.dealId.trim() : ''\n const base: ActivityFormBaseValues = {\n activityType: parsed.data.activityType,\n subject: parsed.data.subject || undefined,\n body: parsed.data.body || undefined,\n occurredAt: parsed.data.occurredAt && parsed.data.occurredAt.length\n ? new Date(parsed.data.occurredAt).toISOString()\n : undefined,\n dealId: rawDealId.length ? rawDealId : undefined,\n }\n const reservedCustomKeys = new Set(['entityId', 'dealId'])\n const customEntries = collectCustomFieldValues(values, {\n transform: (value) => normalizeCustomFieldSubmitValue(value),\n accept: (fieldId) => !reservedCustomKeys.has(fieldId),\n })\n Object.entries(values).forEach(([key, value]) => {\n if (key.startsWith('cf_')) return\n if (!baseFieldIds.has(key) && key !== 'id') {\n if (reservedCustomKeys.has(key)) return\n customEntries[key] = normalizeCustomFieldSubmitValue(value)\n }\n })\n await onSubmit({ base, custom: customEntries, entityId: resolvedEntityId.length ? resolvedEntityId : undefined })\n } finally {\n setPending(false)\n }\n },\n [baseFieldIds, defaultEntityId, isSubmitting, onSubmit, pending, t],\n )\n\n const embeddedInitialValues = React.useMemo(() => {\n const occurredAt = toLocalDateTimeInput(initialValues?.occurredAt ?? null)\n const resolvedEntity = (() => {\n const raw = typeof (initialValues as Record<string, unknown> | undefined)?.entityId === 'string'\n ? (initialValues as Record<string, unknown>).entityId as string\n : typeof defaultEntityId === 'string'\n ? defaultEntityId\n : normalizedEntityOptions[0]?.id ?? ''\n return raw ?? ''\n })()\n const resolvedDeal = typeof (initialValues as Record<string, unknown> | undefined)?.dealId === 'string'\n ? (initialValues as Record<string, unknown>).dealId as string\n : ''\n\n return {\n entityId: resolvedEntity,\n dealId: resolvedDeal,\n activityType: initialValues?.activityType ?? '',\n subject: initialValues?.subject ?? '',\n body: initialValues?.body ?? '',\n occurredAt,\n ...Object.fromEntries(\n Object.entries(initialValues ?? {})\n .filter(([key]) => {\n if (!key.startsWith('cf_')) return false\n const trimmed = key.slice(3)\n return trimmed !== 'entityId' && trimmed !== 'dealId'\n })\n .map(([key, value]) => [key, value]),\n ),\n }\n }, [defaultEntityId, initialValues, normalizedEntityOptions])\n\n return (\n <CrudForm<Record<string, unknown>>\n embedded\n fields={baseFields}\n groups={groups}\n initialValues={embeddedInitialValues}\n onSubmit={handleSubmit}\n submitLabel={submitLabel ?? (mode === 'edit'\n ? t('customers.people.detail.activities.update', 'Update activity (\u2318/Ctrl + Enter)')\n : t('customers.people.detail.activities.save', 'Save activity (\u2318/Ctrl + Enter)'))}\n extraActions={(\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={onCancel}\n disabled={pending || isSubmitting}\n >\n {cancelLabel ?? t('customers.people.detail.activities.cancel', 'Cancel')}\n </Button>\n )}\n entityIds={ACTIVITY_ENTITY_IDS}\n />\n )\n}\n\nexport function buildActivityValidationError(issues: z.ZodIssue[], t: (key: string, fallback?: string) => string) {\n const issue = issues[0]\n const message = issue?.message ?? t('customers.people.detail.activities.error')\n const firstPath = Array.isArray(issue?.path) ? issue?.path?.[0] : undefined\n const field = typeof firstPath === 'string' ? firstPath : undefined\n throw createCrudFormError(message, field ? { [field]: message } : undefined)\n}\n"],
|
|
5
|
+
"mappings": ";AA+JY,SAKI,KALJ;AA7JZ,YAAY,WAAW;AACvB,SAAS,SAAS;AAClB,SAAS,YAAY;AACrB,SAAS,gBAAoD;AAC7D,SAAS,cAAc;AACvB;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,gCAAgC;AACzC,SAAS,2BAA2B;AACpC,SAAS,6BAA0D;AACnE,SAAS,SAAS;AAClB,SAAS,4BAA4B;AACrC,SAAS,uCAAuC;AAuChD,MAAM,SAAS,EAAE,OAAO;AAAA,EACtB,cAAc,EAAE,OAAO,EAAE,IAAI,CAAC;AAAA,EAC9B,SAAS,EAAE,OAAO,EAAE,UAAU,CAAC,UAAU,MAAM,KAAK,CAAC,EAAE,SAAS;AAAA,EAChE,MAAM,EAAE,OAAO,EAAE,UAAU,CAAC,UAAU,MAAM,KAAK,CAAC,EAAE,SAAS;AAAA,EAC7D,YAAY,EACT,OAAO,EACP,UAAU,CAAC,UAAU,MAAM,KAAK,CAAC,EACjC,OAAO,CAAC,UAAU;AACjB,QAAI,CAAC,MAAO,QAAO;AACnB,UAAM,SAAS,IAAI,KAAK,KAAK;AAC7B,WAAO,CAAC,OAAO,MAAM,OAAO,QAAQ,CAAC;AAAA,EACvC,GAAG,EAAE,SAAS,iDAAiD,CAAC,EAC/D,SAAS;AACd,CAAC,EAAE,YAAY;AAEf,MAAM,sBAAsB,CAAC,EAAE,UAAU,iBAAiB;AAEnD,SAAS,aAAa;AAAA,EAC3B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,eAAe;AAAA,EACf;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAsB;AACpB,QAAM,IAAI,KAAK;AACf,QAAM,CAAC,SAAS,UAAU,IAAI,MAAM,SAAS,KAAK;AAElD,QAAM,6BAA6B,MAAM;AAAA,IACvC,OAAO;AAAA,MACL,YAAY,EAAE,mDAAmD,OAAO;AAAA,MACxE,WAAW,EAAE,kDAAkD,wCAAwC;AAAA,MACvG,iBAAiB,EAAE,mDAAmD,cAAc;AAAA,MACpF,WAAW,EAAE,kDAAkD,eAAe;AAAA,MAC9E,iBAAiB,EAAE,wDAAwD,+CAA+C;AAAA,MAC1H,wBAAwB,EAAE,mDAAmD,yBAAyB;AAAA,MACtG,uBAAuB,EAAE,8DAA8D,8BAAyB;AAAA,MAChH,sBAAsB,EAAE,wDAAwD,6BAA6B;AAAA,MAC7G,sBAAsB,EAAE,wDAAwD,aAAa;AAAA,MAC7F,gBAAgB,EAAE,kDAAkD,aAAa;AAAA,MACjF,mBAAmB,EAAE,qDAAqD,wBAAwB;AAAA,IACpG;AAAA,IACA,CAAC,CAAC;AAAA,EACJ;AAEA,QAAM,wBAAwB,MAAM,QAAQ,MAAM;AAChD,QAAI,CAAC,MAAM,QAAQ,WAAW,EAAG,QAAO,CAAC;AACzC,UAAM,OAAO,oBAAI,IAAY;AAC7B,WAAO,YACJ,IAAI,CAAC,WAAW;AACf,UAAI,CAAC,UAAU,OAAO,WAAW,SAAU,QAAO;AAClD,YAAM,KAAK,OAAO,OAAO,OAAO,WAAW,OAAO,GAAG,KAAK,IAAI;AAC9D,UAAI,CAAC,MAAM,KAAK,IAAI,EAAE,EAAG,QAAO;AAChC,YAAM,QACJ,OAAO,OAAO,UAAU,YAAY,OAAO,MAAM,KAAK,EAAE,SACpD,OAAO,MAAM,KAAK,IAClB;AACN,WAAK,IAAI,EAAE;AACX,aAAO,EAAE,IAAI,MAAM;AAAA,IACrB,CAAC,EACA,OAAO,CAAC,WAAoD,CAAC,CAAC,MAAM;AAAA,EACzE,GAAG,CAAC,WAAW,CAAC;AAEhB,QAAM,0BAA0B,MAAM,QAAQ,MAAM;AAClD,QAAI,CAAC,MAAM,QAAQ,aAAa,EAAG,QAAO,CAAC;AAC3C,UAAM,OAAO,oBAAI,IAAY;AAC7B,WAAO,cACJ,IAAI,CAAC,WAAW;AACf,UAAI,CAAC,UAAU,OAAO,WAAW,SAAU,QAAO;AAClD,YAAM,KAAK,OAAO,OAAO,OAAO,WAAW,OAAO,GAAG,KAAK,IAAI;AAC9D,UAAI,CAAC,MAAM,KAAK,IAAI,EAAE,EAAG,QAAO;AAChC,YAAM,QACJ,OAAO,OAAO,UAAU,YAAY,OAAO,MAAM,KAAK,EAAE,SACpD,OAAO,MAAM,KAAK,IAClB;AACN,WAAK,IAAI,EAAE;AACX,aAAO,EAAE,IAAI,MAAM;AAAA,IACrB,CAAC,EACA,OAAO,CAAC,WAAoD,CAAC,CAAC,MAAM;AAAA,EACzE,GAAG,CAAC,aAAa,CAAC;AAElB,QAAM,aAAa,MAAM,QAAqB,MAAM;AAClD,UAAM,SAAsB,CAAC;AAE7B,QAAI,wBAAwB,QAAQ;AAClC,aAAO,KAAK;AAAA,QACV,IAAI;AAAA,QACJ,OAAO,EAAE,oDAAoD,oBAAoB;AAAA,QACjF,MAAM;AAAA,QACN,QAAQ;AAAA,QACR,WAAW,CAAC,EAAE,OAAO,SAAS,MAAM;AAClC,gBAAM,eACJ,OAAO,UAAU,YAAY,MAAM,SAAS,QAAQ,wBAAwB,CAAC,GAAG,MAAM;AACxF,iBACE;AAAA,YAAC;AAAA;AAAA,cACC,OAAO,gBAAgB;AAAA,cACvB,eAAe,CAAC,SAAS,SAAS,QAAQ,EAAE;AAAA,cAE5C;AAAA,oCAAC,iBACC,8BAAC,eAAY,GACf;AAAA,gBACA,oBAAC,iBACE,kCAAwB,IAAI,CAAC,WAC5B,oBAAC,cAA2B,OAAO,OAAO,IACvC,iBAAO,SADO,OAAO,EAExB,CACD,GACH;AAAA;AAAA;AAAA,UACF;AAAA,QAEJ;AAAA,MACF,CAAc;AAAA,IAChB;AAEA,QAAI,sBAAsB,QAAQ;AAChC,aAAO,KAAK;AAAA,QACV,IAAI;AAAA,QACJ,OAAO,EAAE,kDAAkD,yBAAyB;AAAA,QACpF,MAAM;AAAA,QACN,QAAQ;AAAA,QACR,WAAW,CAAC,EAAE,OAAO,SAAS,MAAM;AAClC,gBAAM,eAAe,OAAO,UAAU,WAAW,QAAQ;AACzD,iBACE;AAAA,YAAC;AAAA;AAAA,cACC,OAAO,gBAAgB;AAAA,cACvB,eAAe,CAAC,SAAS,SAAS,QAAQ,EAAE;AAAA,cAE5C;AAAA,oCAAC,iBACC,8BAAC,eAAY,aAAa,EAAE,6DAA6D,gBAAgB,GAAG,GAC9G;AAAA,gBACA,oBAAC,iBACE,gCAAsB,IAAI,CAAC,WAC1B,oBAAC,cAA2B,OAAO,OAAO,IACvC,iBAAO,SADO,OAAO,EAExB,CACD,GACH;AAAA;AAAA;AAAA,UACF;AAAA,QAEJ;AAAA,MACF,CAAc;AAAA,IAChB;AAEA,WAAO,KAAK;AAAA,MACV,IAAI;AAAA,MACJ,OAAO,EAAE,gDAAgD;AAAA,MACzD,MAAM;AAAA,MACN,UAAU;AAAA,MACV,QAAQ;AAAA,MACR,WAAW,CAAC,EAAE,OAAO,SAAS,MAC5B;AAAA,QAAC;AAAA;AAAA,UACC,OAAO,OAAO,UAAU,WAAW,QAAQ;AAAA,UAC3C,UAAU,CAAC,SAAS,SAAS,QAAQ,EAAE;AAAA,UACvC,cAAc;AAAA,UACd,cAAc;AAAA,UACd,QAAQ;AAAA,UACR,iBAAe;AAAA,UACf,mBAAiB;AAAA,UACjB,kBAAkB;AAAA,UAClB,iBAAgB;AAAA,UAChB,YAAW;AAAA;AAAA,MACb;AAAA,IAEJ,CAAc;AAEd,WAAO,KAAK;AAAA,MACV,IAAI;AAAA,MACJ,OAAO,EAAE,mDAAmD;AAAA,MAC5D,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,aAAa,EAAE,yDAAyD,0BAA0B;AAAA,IACpG,CAAc;AAEd,WAAO,KAAK;AAAA,MACV,IAAI;AAAA,MACJ,OAAO,EAAE,gDAAgD;AAAA,MACzD,MAAM;AAAA,MACN,aAAa,EAAE,sDAAsD,0BAA0B;AAAA,IACjG,CAAc;AAEd,WAAO,KAAK;AAAA,MACV,IAAI;AAAA,MACJ,OAAO,EAAE,sDAAsD;AAAA,MAC/D,MAAM;AAAA,MACN,WAAW,CAAC,EAAE,OAAO,SAAS,MAC5B;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL,WAAU;AAAA,UACV,OAAO,OAAO,UAAU,WAAW,QAAQ;AAAA,UAC3C,UAAU,CAAC,UAAU,SAAS,MAAM,OAAO,SAAS,EAAE;AAAA,UACtD,SAAS,CAAC,UAAU;AAClB,kBAAM,SAAS,MAAM;AACrB,gBAAI,OAAO,OAAO,eAAe,YAAY;AAC3C,kBAAI;AAAE,uBAAO,WAAW;AAAA,cAAE,QAAQ;AAAA,cAA2B;AAAA,YAC/D;AAAA,UACF;AAAA,UACA,SAAS,CAAC,UAAU;AAClB,kBAAM,SAAS,MAAM;AACrB,gBAAI,OAAO,OAAO,eAAe,YAAY;AAC3C,kBAAI;AAAE,uBAAO,WAAW;AAAA,cAAE,QAAQ;AAAA,cAA2B;AAAA,YAC/D;AAAA,UACF;AAAA;AAAA,MACF;AAAA,MAEF,QAAQ;AAAA,IACV,CAAc;AAEd,WAAO;AAAA,EACT,GAAG;AAAA,IACD;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AAED,QAAM,eAAe,MAAM,QAAQ,MAAM,IAAI,IAAI,WAAW,IAAI,CAAC,UAAU,MAAM,EAAE,CAAC,GAAG,CAAC,UAAU,CAAC;AAEnG,QAAM,SAAS,MAAM,QAAyB,MAAM;AAClD,UAAM,eAAyB,CAAC;AAChC,QAAI,wBAAwB,OAAQ,cAAa,KAAK,UAAU;AAChE,QAAI,sBAAsB,OAAQ,cAAa,KAAK,QAAQ;AAC5D,iBAAa,KAAK,gBAAgB,WAAW,cAAc,MAAM;AACjE,WAAO;AAAA,MACL;AAAA,QACE,IAAI;AAAA,QACJ,OAAO,EAAE,mDAAmD,kBAAkB;AAAA,QAC9E,QAAQ;AAAA,QACR,QAAQ;AAAA,MACV;AAAA,MACA;AAAA,QACE,IAAI;AAAA,QACJ,OAAO,EAAE,wDAAwD,eAAe;AAAA,QAChF,QAAQ;AAAA,QACR,MAAM;AAAA,MACR;AAAA,IACF;AAAA,EACF,GAAG,CAAC,sBAAsB,QAAQ,wBAAwB,QAAQ,CAAC,CAAC;AAEpE,QAAM,eAAe,MAAM;AAAA,IACzB,OAAO,WAAoC;AACzC,UAAI,WAAW,aAAc;AAC7B,iBAAW,IAAI;AACf,UAAI;AACF,cAAM,SAAS,OAAO,UAAU,MAAM;AACtC,YAAI,CAAC,OAAO,SAAS;AACnB,gBAAM,6BAA6B,OAAO,MAAM,QAAQ,CAAC;AAAA,QAC3D;AACA,cAAM,cAAc,OAAO,OAAO,aAAa,WAAW,OAAO,SAAS,KAAK,IAAI;AACnF,cAAM,mBAAmB,gBAAgB,OAAO,oBAAoB,WAAW,kBAAkB;AACjG,cAAM,YAAY,OAAO,OAAO,WAAW,WAAW,OAAO,OAAO,KAAK,IAAI;AAC7E,cAAM,OAA+B;AAAA,UACnC,cAAc,OAAO,KAAK;AAAA,UAC1B,SAAS,OAAO,KAAK,WAAW;AAAA,UAChC,MAAM,OAAO,KAAK,QAAQ;AAAA,UAC1B,YAAY,OAAO,KAAK,cAAc,OAAO,KAAK,WAAW,SACzD,IAAI,KAAK,OAAO,KAAK,UAAU,EAAE,YAAY,IAC7C;AAAA,UACJ,QAAQ,UAAU,SAAS,YAAY;AAAA,QACzC;AACA,cAAM,qBAAqB,oBAAI,IAAI,CAAC,YAAY,QAAQ,CAAC;AACzD,cAAM,gBAAgB,yBAAyB,QAAQ;AAAA,UACrD,WAAW,CAAC,UAAU,gCAAgC,KAAK;AAAA,UAC3D,QAAQ,CAAC,YAAY,CAAC,mBAAmB,IAAI,OAAO;AAAA,QACtD,CAAC;AACD,eAAO,QAAQ,MAAM,EAAE,QAAQ,CAAC,CAAC,KAAK,KAAK,MAAM;AAC/C,cAAI,IAAI,WAAW,KAAK,EAAG;AAC3B,cAAI,CAAC,aAAa,IAAI,GAAG,KAAK,QAAQ,MAAM;AAC1C,gBAAI,mBAAmB,IAAI,GAAG,EAAG;AACjC,0BAAc,GAAG,IAAI,gCAAgC,KAAK;AAAA,UAC5D;AAAA,QACF,CAAC;AACD,cAAM,SAAS,EAAE,MAAM,QAAQ,eAAe,UAAU,iBAAiB,SAAS,mBAAmB,OAAU,CAAC;AAAA,MAClH,UAAE;AACA,mBAAW,KAAK;AAAA,MAClB;AAAA,IACF;AAAA,IACA,CAAC,cAAc,iBAAiB,cAAc,UAAU,SAAS,CAAC;AAAA,EACpE;AAEA,QAAM,wBAAwB,MAAM,QAAQ,MAAM;AAChD,UAAM,aAAa,qBAAqB,eAAe,cAAc,IAAI;AACzE,UAAM,kBAAkB,MAAM;AAC5B,YAAM,MAAM,OAAQ,eAAuD,aAAa,WACnF,cAA0C,WAC3C,OAAO,oBAAoB,WACzB,kBACA,wBAAwB,CAAC,GAAG,MAAM;AACxC,aAAO,OAAO;AAAA,IAChB,GAAG;AACH,UAAM,eAAe,OAAQ,eAAuD,WAAW,WAC1F,cAA0C,SAC3C;AAEJ,WAAO;AAAA,MACL,UAAU;AAAA,MACV,QAAQ;AAAA,MACR,cAAc,eAAe,gBAAgB;AAAA,MAC7C,SAAS,eAAe,WAAW;AAAA,MACnC,MAAM,eAAe,QAAQ;AAAA,MAC7B;AAAA,MACA,GAAG,OAAO;AAAA,QACR,OAAO,QAAQ,iBAAiB,CAAC,CAAC,EAC/B,OAAO,CAAC,CAAC,GAAG,MAAM;AACjB,cAAI,CAAC,IAAI,WAAW,KAAK,EAAG,QAAO;AACnC,gBAAM,UAAU,IAAI,MAAM,CAAC;AAC3B,iBAAO,YAAY,cAAc,YAAY;AAAA,QAC/C,CAAC,EACA,IAAI,CAAC,CAAC,KAAK,KAAK,MAAM,CAAC,KAAK,KAAK,CAAC;AAAA,MACvC;AAAA,IACF;AAAA,EACF,GAAG,CAAC,iBAAiB,eAAe,uBAAuB,CAAC;AAE5D,SACE;AAAA,IAAC;AAAA;AAAA,MACC,UAAQ;AAAA,MACR,QAAQ;AAAA,MACR;AAAA,MACA,eAAe;AAAA,MACf,UAAU;AAAA,MACV,aAAa,gBAAgB,SAAS,SAClC,EAAE,6CAA6C,uCAAkC,IACjF,EAAE,2CAA2C,qCAAgC;AAAA,MACjF,cACE;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL,SAAQ;AAAA,UACR,SAAS;AAAA,UACT,UAAU,WAAW;AAAA,UAEpB,yBAAe,EAAE,6CAA6C,QAAQ;AAAA;AAAA,MACzE;AAAA,MAEF,WAAW;AAAA;AAAA,EACb;AAEJ;AAEO,SAAS,6BAA6B,QAAsB,GAA+C;AAChH,QAAM,QAAQ,OAAO,CAAC;AACtB,QAAM,UAAU,OAAO,WAAW,EAAE,0CAA0C;AAC9E,QAAM,YAAY,MAAM,QAAQ,OAAO,IAAI,IAAI,OAAO,OAAO,CAAC,IAAI;AAClE,QAAM,QAAQ,OAAO,cAAc,WAAW,YAAY;AAC1D,QAAM,oBAAoB,SAAS,QAAQ,EAAE,CAAC,KAAK,GAAG,QAAQ,IAAI,MAAS;AAC7E;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -3,6 +3,7 @@ import { jsx, jsxs } from "react/jsx-runtime";
|
|
|
3
3
|
import * as React from "react";
|
|
4
4
|
import { Loader2, Pencil, X } from "lucide-react";
|
|
5
5
|
import { Button } from "@open-mercato/ui/primitives/button";
|
|
6
|
+
import { Input } from "@open-mercato/ui/primitives/input";
|
|
6
7
|
import { DictionaryEntrySelect } from "@open-mercato/core/modules/dictionaries/components/DictionaryEntrySelect";
|
|
7
8
|
import { useT } from "@open-mercato/shared/lib/i18n/context";
|
|
8
9
|
import { cn } from "@open-mercato/shared/lib/utils";
|
|
@@ -188,9 +189,8 @@ function AnnualRevenueField({
|
|
|
188
189
|
/* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
|
|
189
190
|
/* @__PURE__ */ jsx("label", { className: "text-xs font-medium uppercase tracking-wide text-muted-foreground", children: t("customers.companies.detail.fields.annualRevenuePlaceholder", "Enter amount") }),
|
|
190
191
|
/* @__PURE__ */ jsx(
|
|
191
|
-
|
|
192
|
+
Input,
|
|
192
193
|
{
|
|
193
|
-
className: "w-full rounded-md border px-3 py-2 text-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
|
194
194
|
value: draftAmount,
|
|
195
195
|
onChange: (event) => {
|
|
196
196
|
setDraftAmount(event.target.value);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../src/modules/customers/components/detail/AnnualRevenueField.tsx"],
|
|
4
|
-
"sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { Loader2, Pencil, X } from 'lucide-react'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { DictionaryEntrySelect } from '@open-mercato/core/modules/dictionaries/components/DictionaryEntrySelect'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { cn } from '@open-mercato/shared/lib/utils'\nimport { useCurrencyDictionary } from './hooks/useCurrencyDictionary'\nimport type { InlineFieldProps } from './InlineEditors'\n\nexport type AnnualRevenueFieldProps = {\n label: string\n amount: string | null\n currency: string | null\n emptyLabel: string\n validator?: NonNullable<InlineFieldProps['validator']>\n onSave: (payload: { amount: number | null; currency: string | null }) => Promise<void>\n}\n\nexport function AnnualRevenueField({\n label,\n amount,\n currency,\n emptyLabel,\n validator,\n onSave,\n}: AnnualRevenueFieldProps) {\n const t = useT()\n const {\n data: currencyDictionary,\n error: currencyDictionaryErrorRaw,\n isLoading: currencyDictionaryLoading,\n refetch: refetchCurrencyDictionary,\n } = useCurrencyDictionary()\n\n const currencyDictionaryError =\n currencyDictionaryErrorRaw instanceof Error\n ? currencyDictionaryErrorRaw.message\n : currencyDictionaryErrorRaw\n ? String(currencyDictionaryErrorRaw)\n : null\n\n const [editing, setEditing] = React.useState(false)\n const [draftAmount, setDraftAmount] = React.useState(() => (typeof amount === 'string' ? amount : ''))\n const [draftCurrency, setDraftCurrency] = React.useState(() => (typeof currency === 'string' ? currency : ''))\n const [error, setError] = React.useState<string | null>(null)\n const [saving, setSaving] = React.useState(false)\n\n React.useEffect(() => {\n if (!editing) {\n setDraftAmount(typeof amount === 'string' ? amount : '')\n setDraftCurrency(typeof currency === 'string' ? currency : '')\n setError(null)\n }\n }, [amount, currency, editing])\n\n const currencyLabel = React.useMemo(() => {\n if (!currency) return null\n const entries = currencyDictionary?.entries ?? []\n const match = entries.find((entry) => entry.value === currency)\n if (!match) return currency\n return match.label || match.value\n }, [currency, currencyDictionary?.entries])\n\n const fetchCurrencyOptions = React.useCallback(async () => {\n if (currencyDictionary && currencyDictionary.entries.length) {\n return currencyDictionary.entries.map((entry) => ({\n value: entry.value,\n label: entry.label,\n color: entry.color ?? null,\n icon: entry.icon ?? null,\n }))\n }\n const payload = await refetchCurrencyDictionary()\n return payload.entries.map((entry) => ({\n value: entry.value,\n label: entry.label,\n color: entry.color ?? null,\n icon: entry.icon ?? null,\n }))\n }, [currencyDictionary, refetchCurrencyDictionary])\n\n const display = React.useMemo(() => {\n const value = typeof amount === 'string' ? amount.trim() : ''\n if (!value.length) {\n return <p className=\"text-sm text-muted-foreground\">{emptyLabel}</p>\n }\n const numeric = Number(value.replace(/,/g, ''))\n let formatted = value\n if (!Number.isNaN(numeric)) {\n try {\n formatted = new Intl.NumberFormat(undefined, {\n style: currency ? 'currency' : 'decimal',\n currency: currency ?? undefined,\n maximumFractionDigits: 2,\n }).format(numeric)\n } catch {\n formatted = currency ? `${currency} ${numeric}` : `${numeric}`\n }\n }\n return (\n <div className=\"flex flex-col gap-1\">\n <span className=\"text-sm font-medium text-foreground\">{formatted}</span>\n {currencyLabel ? (\n <span className=\"text-xs uppercase tracking-wide text-muted-foreground\">{currencyLabel}</span>\n ) : null}\n </div>\n )\n }, [amount, currency, currencyLabel, emptyLabel])\n\n const currencyLabels = React.useMemo(\n () => ({\n placeholder: t('customers.companies.detail.currency.placeholder', 'Select currency\u2026'),\n addLabel: t('customers.companies.detail.currency.add', 'Add currency'),\n addPrompt: t('customers.companies.detail.currency.addPrompt', 'Enter a 3-letter ISO currency code.'),\n dialogTitle: t('customers.companies.detail.currency.dialogTitle', 'Add currency'),\n valueLabel: t('customers.companies.detail.currency.valueLabel', 'Currency code'),\n valuePlaceholder: t('customers.companies.detail.currency.valuePlaceholder', 'e.g. USD'),\n labelLabel: t('customers.companies.detail.currency.labelLabel', 'Display label (optional)'),\n labelPlaceholder: t('customers.companies.detail.currency.labelPlaceholder', 'e.g. US Dollar'),\n emptyError: t('customers.companies.detail.currency.emptyError', 'Please provide a currency code.'),\n cancelLabel: t('customers.companies.detail.currency.cancel', 'Cancel'),\n saveLabel: t('customers.companies.detail.currency.save', 'Save'),\n saveShortcutHint: t('customers.companies.detail.currency.saveShortcutHint', 'Press Enter to save'),\n successCreateLabel: t('customers.companies.detail.currency.success', 'Currency added.'),\n errorLoad: t('customers.companies.detail.currency.fetchError', 'Unable to load currencies.'),\n errorSave: t('customers.companies.detail.currency.createError', 'Unable to add currency.'),\n loadingLabel: t('customers.companies.detail.currency.loading', 'Loading currencies\u2026'),\n manageTitle: t('customers.companies.detail.currency.manageTitle', 'Manage currencies'),\n }),\n [t],\n )\n\n const handleSave = React.useCallback(async () => {\n if (saving) return\n const trimmedAmount = draftAmount.trim()\n if (validator) {\n const validationError = validator(trimmedAmount)\n if (validationError) {\n setError(validationError)\n return\n }\n }\n let numeric: number | null = null\n if (trimmedAmount.length) {\n numeric = Number(trimmedAmount)\n if (Number.isNaN(numeric)) {\n setError(t('customers.companies.detail.currency.invalidAmount', 'Enter a valid amount.'))\n return\n }\n }\n setSaving(true)\n try {\n await onSave({ amount: numeric, currency: draftCurrency.trim() ? draftCurrency.trim() : null })\n setEditing(false)\n } catch (err) {\n const message =\n err instanceof Error\n ? err.message\n : t('customers.companies.detail.inline.error', 'Unable to update company.')\n setError(message)\n } finally {\n setSaving(false)\n }\n }, [draftAmount, draftCurrency, onSave, saving, t, validator])\n\n const containerClasses = React.useMemo(\n () =>\n cn('group rounded border bg-muted/30 p-3', {\n 'cursor-pointer focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring': !editing,\n }),\n [editing],\n )\n\n const handleActivate = React.useCallback(() => {\n if (!editing) setEditing(true)\n }, [editing])\n\n const handleKeyDown = React.useCallback(\n (event: React.KeyboardEvent<HTMLDivElement>) => {\n if (editing) return\n if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault()\n handleActivate()\n }\n },\n [editing, handleActivate],\n )\n\n return (\n <div\n className={containerClasses}\n role={editing ? undefined : 'button'}\n tabIndex={editing ? -1 : 0}\n onClick={() => {\n if (!editing) handleActivate()\n }}\n onKeyDown={handleKeyDown}\n >\n <div className=\"flex items-start justify-between gap-3\">\n <div>\n <p className=\"text-xs font-medium uppercase tracking-wide text-muted-foreground\">{label}</p>\n <div className=\"mt-1 text-sm text-foreground\">{display}</div>\n {currencyDictionaryError ? (\n <p className=\"mt-1 text-xs text-muted-foreground\">{currencyDictionaryError}</p>\n ) : null}\n </div>\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon\"\n onClick={() => setEditing((prev) => !prev)}\n className=\"h-8 w-8 opacity-0 transition-opacity duration-150 group-hover:opacity-100 group-focus-within:opacity-100 focus-visible:opacity-100\"\n >\n {editing ? <X className=\"h-4 w-4\" /> : <Pencil className=\"h-4 w-4\" />}\n <span className=\"sr-only\">{editing ? t('ui.forms.actions.cancel') : t('ui.forms.actions.edit')}</span>\n </Button>\n </div>\n {editing ? (\n <div className=\"mt-3 space-y-3\">\n <div className=\"space-y-1\">\n <label className=\"text-xs font-medium uppercase tracking-wide text-muted-foreground\">\n {t('customers.companies.detail.fields.annualRevenuePlaceholder', 'Enter amount')}\n </label>\n <input\n className=\"w-full rounded-md border px-3 py-2 text-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\"\n value={draftAmount}\n onChange={(event) => {\n setDraftAmount(event.target.value)\n if (error) setError(null)\n }}\n placeholder={t('customers.companies.detail.fields.annualRevenuePlaceholder', 'Enter amount')}\n type=\"number\"\n min=\"0\"\n step=\"0.01\"\n />\n </div>\n <div className=\"space-y-1\">\n <label className=\"text-xs font-medium uppercase tracking-wide text-muted-foreground\">\n {t('customers.companies.detail.highlights.annualRevenueCurrency', 'Currency')}\n </label>\n <DictionaryEntrySelect\n value={draftCurrency || undefined}\n onChange={(next) => setDraftCurrency(next ?? '')}\n fetchOptions={fetchCurrencyOptions}\n labels={currencyLabels}\n manageHref=\"/backend/config/dictionaries?key=currency\"\n allowInlineCreate={false}\n allowAppearance={false}\n selectClassName=\"w-full\"\n disabled={currencyDictionaryLoading}\n showLabelInput={false}\n />\n </div>\n {error ? <p className=\"text-xs text-status-error-text\">{error}</p> : null}\n <div className=\"flex items-center gap-2\">\n <Button type=\"button\" size=\"sm\" onClick={handleSave} disabled={saving}>\n {saving ? <Loader2 className=\"mr-2 h-3.5 w-3.5 animate-spin\" /> : null}\n {t('ui.forms.actions.save')}\n </Button>\n <Button type=\"button\" size=\"sm\" variant=\"ghost\" disabled={saving} onClick={() => setEditing(false)}>\n {t('ui.forms.actions.cancel')}\n </Button>\n <Button\n type=\"button\"\n size=\"sm\"\n variant=\"secondary\"\n disabled={saving}\n onClick={() => {\n setDraftAmount('')\n setDraftCurrency('')\n if (error) setError(null)\n }}\n >\n {t('customers.companies.detail.currency.clear', 'Clear')}\n </Button>\n </div>\n </div>\n ) : null}\n </div>\n )\n}\n"],
|
|
5
|
-
"mappings": ";
|
|
4
|
+
"sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { Loader2, Pencil, X } from 'lucide-react'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { Input } from '@open-mercato/ui/primitives/input'\nimport { DictionaryEntrySelect } from '@open-mercato/core/modules/dictionaries/components/DictionaryEntrySelect'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { cn } from '@open-mercato/shared/lib/utils'\nimport { useCurrencyDictionary } from './hooks/useCurrencyDictionary'\nimport type { InlineFieldProps } from './InlineEditors'\n\nexport type AnnualRevenueFieldProps = {\n label: string\n amount: string | null\n currency: string | null\n emptyLabel: string\n validator?: NonNullable<InlineFieldProps['validator']>\n onSave: (payload: { amount: number | null; currency: string | null }) => Promise<void>\n}\n\nexport function AnnualRevenueField({\n label,\n amount,\n currency,\n emptyLabel,\n validator,\n onSave,\n}: AnnualRevenueFieldProps) {\n const t = useT()\n const {\n data: currencyDictionary,\n error: currencyDictionaryErrorRaw,\n isLoading: currencyDictionaryLoading,\n refetch: refetchCurrencyDictionary,\n } = useCurrencyDictionary()\n\n const currencyDictionaryError =\n currencyDictionaryErrorRaw instanceof Error\n ? currencyDictionaryErrorRaw.message\n : currencyDictionaryErrorRaw\n ? String(currencyDictionaryErrorRaw)\n : null\n\n const [editing, setEditing] = React.useState(false)\n const [draftAmount, setDraftAmount] = React.useState(() => (typeof amount === 'string' ? amount : ''))\n const [draftCurrency, setDraftCurrency] = React.useState(() => (typeof currency === 'string' ? currency : ''))\n const [error, setError] = React.useState<string | null>(null)\n const [saving, setSaving] = React.useState(false)\n\n React.useEffect(() => {\n if (!editing) {\n setDraftAmount(typeof amount === 'string' ? amount : '')\n setDraftCurrency(typeof currency === 'string' ? currency : '')\n setError(null)\n }\n }, [amount, currency, editing])\n\n const currencyLabel = React.useMemo(() => {\n if (!currency) return null\n const entries = currencyDictionary?.entries ?? []\n const match = entries.find((entry) => entry.value === currency)\n if (!match) return currency\n return match.label || match.value\n }, [currency, currencyDictionary?.entries])\n\n const fetchCurrencyOptions = React.useCallback(async () => {\n if (currencyDictionary && currencyDictionary.entries.length) {\n return currencyDictionary.entries.map((entry) => ({\n value: entry.value,\n label: entry.label,\n color: entry.color ?? null,\n icon: entry.icon ?? null,\n }))\n }\n const payload = await refetchCurrencyDictionary()\n return payload.entries.map((entry) => ({\n value: entry.value,\n label: entry.label,\n color: entry.color ?? null,\n icon: entry.icon ?? null,\n }))\n }, [currencyDictionary, refetchCurrencyDictionary])\n\n const display = React.useMemo(() => {\n const value = typeof amount === 'string' ? amount.trim() : ''\n if (!value.length) {\n return <p className=\"text-sm text-muted-foreground\">{emptyLabel}</p>\n }\n const numeric = Number(value.replace(/,/g, ''))\n let formatted = value\n if (!Number.isNaN(numeric)) {\n try {\n formatted = new Intl.NumberFormat(undefined, {\n style: currency ? 'currency' : 'decimal',\n currency: currency ?? undefined,\n maximumFractionDigits: 2,\n }).format(numeric)\n } catch {\n formatted = currency ? `${currency} ${numeric}` : `${numeric}`\n }\n }\n return (\n <div className=\"flex flex-col gap-1\">\n <span className=\"text-sm font-medium text-foreground\">{formatted}</span>\n {currencyLabel ? (\n <span className=\"text-xs uppercase tracking-wide text-muted-foreground\">{currencyLabel}</span>\n ) : null}\n </div>\n )\n }, [amount, currency, currencyLabel, emptyLabel])\n\n const currencyLabels = React.useMemo(\n () => ({\n placeholder: t('customers.companies.detail.currency.placeholder', 'Select currency\u2026'),\n addLabel: t('customers.companies.detail.currency.add', 'Add currency'),\n addPrompt: t('customers.companies.detail.currency.addPrompt', 'Enter a 3-letter ISO currency code.'),\n dialogTitle: t('customers.companies.detail.currency.dialogTitle', 'Add currency'),\n valueLabel: t('customers.companies.detail.currency.valueLabel', 'Currency code'),\n valuePlaceholder: t('customers.companies.detail.currency.valuePlaceholder', 'e.g. USD'),\n labelLabel: t('customers.companies.detail.currency.labelLabel', 'Display label (optional)'),\n labelPlaceholder: t('customers.companies.detail.currency.labelPlaceholder', 'e.g. US Dollar'),\n emptyError: t('customers.companies.detail.currency.emptyError', 'Please provide a currency code.'),\n cancelLabel: t('customers.companies.detail.currency.cancel', 'Cancel'),\n saveLabel: t('customers.companies.detail.currency.save', 'Save'),\n saveShortcutHint: t('customers.companies.detail.currency.saveShortcutHint', 'Press Enter to save'),\n successCreateLabel: t('customers.companies.detail.currency.success', 'Currency added.'),\n errorLoad: t('customers.companies.detail.currency.fetchError', 'Unable to load currencies.'),\n errorSave: t('customers.companies.detail.currency.createError', 'Unable to add currency.'),\n loadingLabel: t('customers.companies.detail.currency.loading', 'Loading currencies\u2026'),\n manageTitle: t('customers.companies.detail.currency.manageTitle', 'Manage currencies'),\n }),\n [t],\n )\n\n const handleSave = React.useCallback(async () => {\n if (saving) return\n const trimmedAmount = draftAmount.trim()\n if (validator) {\n const validationError = validator(trimmedAmount)\n if (validationError) {\n setError(validationError)\n return\n }\n }\n let numeric: number | null = null\n if (trimmedAmount.length) {\n numeric = Number(trimmedAmount)\n if (Number.isNaN(numeric)) {\n setError(t('customers.companies.detail.currency.invalidAmount', 'Enter a valid amount.'))\n return\n }\n }\n setSaving(true)\n try {\n await onSave({ amount: numeric, currency: draftCurrency.trim() ? draftCurrency.trim() : null })\n setEditing(false)\n } catch (err) {\n const message =\n err instanceof Error\n ? err.message\n : t('customers.companies.detail.inline.error', 'Unable to update company.')\n setError(message)\n } finally {\n setSaving(false)\n }\n }, [draftAmount, draftCurrency, onSave, saving, t, validator])\n\n const containerClasses = React.useMemo(\n () =>\n cn('group rounded border bg-muted/30 p-3', {\n 'cursor-pointer focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring': !editing,\n }),\n [editing],\n )\n\n const handleActivate = React.useCallback(() => {\n if (!editing) setEditing(true)\n }, [editing])\n\n const handleKeyDown = React.useCallback(\n (event: React.KeyboardEvent<HTMLDivElement>) => {\n if (editing) return\n if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault()\n handleActivate()\n }\n },\n [editing, handleActivate],\n )\n\n return (\n <div\n className={containerClasses}\n role={editing ? undefined : 'button'}\n tabIndex={editing ? -1 : 0}\n onClick={() => {\n if (!editing) handleActivate()\n }}\n onKeyDown={handleKeyDown}\n >\n <div className=\"flex items-start justify-between gap-3\">\n <div>\n <p className=\"text-xs font-medium uppercase tracking-wide text-muted-foreground\">{label}</p>\n <div className=\"mt-1 text-sm text-foreground\">{display}</div>\n {currencyDictionaryError ? (\n <p className=\"mt-1 text-xs text-muted-foreground\">{currencyDictionaryError}</p>\n ) : null}\n </div>\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon\"\n onClick={() => setEditing((prev) => !prev)}\n className=\"h-8 w-8 opacity-0 transition-opacity duration-150 group-hover:opacity-100 group-focus-within:opacity-100 focus-visible:opacity-100\"\n >\n {editing ? <X className=\"h-4 w-4\" /> : <Pencil className=\"h-4 w-4\" />}\n <span className=\"sr-only\">{editing ? t('ui.forms.actions.cancel') : t('ui.forms.actions.edit')}</span>\n </Button>\n </div>\n {editing ? (\n <div className=\"mt-3 space-y-3\">\n <div className=\"space-y-1\">\n <label className=\"text-xs font-medium uppercase tracking-wide text-muted-foreground\">\n {t('customers.companies.detail.fields.annualRevenuePlaceholder', 'Enter amount')}\n </label>\n <Input\n value={draftAmount}\n onChange={(event) => {\n setDraftAmount(event.target.value)\n if (error) setError(null)\n }}\n placeholder={t('customers.companies.detail.fields.annualRevenuePlaceholder', 'Enter amount')}\n type=\"number\"\n min=\"0\"\n step=\"0.01\"\n />\n </div>\n <div className=\"space-y-1\">\n <label className=\"text-xs font-medium uppercase tracking-wide text-muted-foreground\">\n {t('customers.companies.detail.highlights.annualRevenueCurrency', 'Currency')}\n </label>\n <DictionaryEntrySelect\n value={draftCurrency || undefined}\n onChange={(next) => setDraftCurrency(next ?? '')}\n fetchOptions={fetchCurrencyOptions}\n labels={currencyLabels}\n manageHref=\"/backend/config/dictionaries?key=currency\"\n allowInlineCreate={false}\n allowAppearance={false}\n selectClassName=\"w-full\"\n disabled={currencyDictionaryLoading}\n showLabelInput={false}\n />\n </div>\n {error ? <p className=\"text-xs text-status-error-text\">{error}</p> : null}\n <div className=\"flex items-center gap-2\">\n <Button type=\"button\" size=\"sm\" onClick={handleSave} disabled={saving}>\n {saving ? <Loader2 className=\"mr-2 h-3.5 w-3.5 animate-spin\" /> : null}\n {t('ui.forms.actions.save')}\n </Button>\n <Button type=\"button\" size=\"sm\" variant=\"ghost\" disabled={saving} onClick={() => setEditing(false)}>\n {t('ui.forms.actions.cancel')}\n </Button>\n <Button\n type=\"button\"\n size=\"sm\"\n variant=\"secondary\"\n disabled={saving}\n onClick={() => {\n setDraftAmount('')\n setDraftCurrency('')\n if (error) setError(null)\n }}\n >\n {t('customers.companies.detail.currency.clear', 'Clear')}\n </Button>\n </div>\n </div>\n ) : null}\n </div>\n )\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -6,6 +6,13 @@ import { useT } from "@open-mercato/shared/lib/i18n/context";
|
|
|
6
6
|
import { CrudForm } from "@open-mercato/ui/backend/CrudForm";
|
|
7
7
|
import { Button } from "@open-mercato/ui/primitives/button";
|
|
8
8
|
import { IconButton } from "@open-mercato/ui/primitives/icon-button";
|
|
9
|
+
import {
|
|
10
|
+
Select,
|
|
11
|
+
SelectContent,
|
|
12
|
+
SelectItem,
|
|
13
|
+
SelectTrigger,
|
|
14
|
+
SelectValue
|
|
15
|
+
} from "@open-mercato/ui/primitives/select";
|
|
9
16
|
import { apiCall } from "@open-mercato/ui/backend/utils/apiCall";
|
|
10
17
|
import { createCrudFormError } from "@open-mercato/ui/backend/utils/serverErrors";
|
|
11
18
|
import { DictionarySelectField } from "../formConfig.js";
|
|
@@ -613,19 +620,18 @@ function DealForm({
|
|
|
613
620
|
type: "custom",
|
|
614
621
|
layout: "half",
|
|
615
622
|
component: ({ value, setValue }) => /* @__PURE__ */ jsxs(
|
|
616
|
-
|
|
623
|
+
Select,
|
|
617
624
|
{
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
loadStagesForPipeline(e.target.value).catch(() => {
|
|
625
|
+
value: typeof value === "string" && value ? value : void 0,
|
|
626
|
+
onValueChange: (next) => {
|
|
627
|
+
setValue(next ?? "");
|
|
628
|
+
loadStagesForPipeline(next ?? "").catch(() => {
|
|
623
629
|
});
|
|
624
630
|
},
|
|
625
631
|
disabled,
|
|
626
632
|
children: [
|
|
627
|
-
/* @__PURE__ */ jsx(
|
|
628
|
-
pipelines.map((p) => /* @__PURE__ */ jsx(
|
|
633
|
+
/* @__PURE__ */ jsx(SelectTrigger, { children: /* @__PURE__ */ jsx(SelectValue, { placeholder: t("customers.deals.form.pipeline.placeholder", "Select pipeline\u2026") }) }),
|
|
634
|
+
/* @__PURE__ */ jsx(SelectContent, { children: pipelines.map((p) => /* @__PURE__ */ jsx(SelectItem, { value: p.id, children: p.name }, p.id)) })
|
|
629
635
|
]
|
|
630
636
|
}
|
|
631
637
|
)
|
|
@@ -636,15 +642,14 @@ function DealForm({
|
|
|
636
642
|
type: "custom",
|
|
637
643
|
layout: "half",
|
|
638
644
|
component: ({ value, setValue }) => /* @__PURE__ */ jsxs(
|
|
639
|
-
|
|
645
|
+
Select,
|
|
640
646
|
{
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
onChange: (e) => setValue(e.target.value),
|
|
647
|
+
value: typeof value === "string" && value ? value : void 0,
|
|
648
|
+
onValueChange: (next) => setValue(next ?? ""),
|
|
644
649
|
disabled: disabled || !pipelineStages.length,
|
|
645
650
|
children: [
|
|
646
|
-
/* @__PURE__ */ jsx(
|
|
647
|
-
pipelineStages.map((s) => /* @__PURE__ */ jsx(
|
|
651
|
+
/* @__PURE__ */ jsx(SelectTrigger, { children: /* @__PURE__ */ jsx(SelectValue, { placeholder: t("customers.deals.form.pipelineStage.placeholder", "Select stage\u2026") }) }),
|
|
652
|
+
/* @__PURE__ */ jsx(SelectContent, { children: pipelineStages.map((s) => /* @__PURE__ */ jsx(SelectItem, { value: s.id, children: s.label }, s.id)) })
|
|
648
653
|
]
|
|
649
654
|
}
|
|
650
655
|
)
|