@open-mercato/core 0.6.4-develop.4363.1.2f376570ae → 0.6.4-develop.4371.1.8f3030407e
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/catalog/backend/catalog/categories/[id]/edit/page.js +66 -44
- package/dist/modules/catalog/backend/catalog/categories/[id]/edit/page.js.map +2 -2
- package/dist/modules/catalog/backend/catalog/products/[productId]/variants/[variantId]/page.js +124 -103
- package/dist/modules/catalog/backend/catalog/products/[productId]/variants/[variantId]/page.js.map +2 -2
- package/dist/modules/customers/backend/config/customers/pipeline-stages/page.js +5 -1
- package/dist/modules/customers/backend/config/customers/pipeline-stages/page.js.map +2 -2
- package/dist/modules/customers/data/validators.js +4 -4
- package/dist/modules/customers/data/validators.js.map +2 -2
- package/dist/modules/directory/backend/directory/organizations/[id]/edit/page.js +26 -4
- package/dist/modules/directory/backend/directory/organizations/[id]/edit/page.js.map +2 -2
- package/dist/modules/directory/backend/directory/tenants/[id]/edit/page.js +24 -4
- package/dist/modules/directory/backend/directory/tenants/[id]/edit/page.js.map +2 -2
- package/dist/modules/planner/backend/planner/availability-rulesets/[id]/page.js +35 -6
- package/dist/modules/planner/backend/planner/availability-rulesets/[id]/page.js.map +3 -3
- package/dist/modules/sales/backend/sales/channels/[channelId]/edit/page.js +67 -47
- package/dist/modules/sales/backend/sales/channels/[channelId]/edit/page.js.map +2 -2
- package/dist/modules/staff/backend/staff/leave-requests/[id]/page.js +29 -6
- package/dist/modules/staff/backend/staff/leave-requests/[id]/page.js.map +2 -2
- package/dist/modules/staff/backend/staff/my-leave-requests/[id]/page.js +29 -6
- package/dist/modules/staff/backend/staff/my-leave-requests/[id]/page.js.map +2 -2
- package/dist/modules/staff/backend/staff/team-members/[id]/page.js +33 -4
- package/dist/modules/staff/backend/staff/team-members/[id]/page.js.map +2 -2
- package/dist/modules/staff/backend/staff/team-roles/[id]/edit/page.js +33 -4
- package/dist/modules/staff/backend/staff/team-roles/[id]/edit/page.js.map +2 -2
- package/dist/modules/staff/backend/staff/teams/[id]/edit/page.js +37 -8
- package/dist/modules/staff/backend/staff/teams/[id]/edit/page.js.map +3 -3
- package/dist/modules/workflows/backend/definitions/[id]/page.js +24 -6
- package/dist/modules/workflows/backend/definitions/[id]/page.js.map +2 -2
- package/package.json +7 -7
- package/src/modules/catalog/backend/catalog/categories/[id]/edit/page.tsx +39 -8
- package/src/modules/catalog/backend/catalog/products/[productId]/variants/[variantId]/page.tsx +38 -6
- package/src/modules/catalog/i18n/de.json +2 -0
- package/src/modules/catalog/i18n/en.json +2 -0
- package/src/modules/catalog/i18n/es.json +2 -0
- package/src/modules/catalog/i18n/pl.json +2 -0
- package/src/modules/customers/backend/config/customers/pipeline-stages/page.tsx +5 -1
- package/src/modules/customers/data/validators.ts +4 -4
- package/src/modules/directory/backend/directory/organizations/[id]/edit/page.tsx +30 -4
- package/src/modules/directory/backend/directory/tenants/[id]/edit/page.tsx +28 -6
- package/src/modules/directory/i18n/de.json +2 -0
- package/src/modules/directory/i18n/en.json +2 -0
- package/src/modules/directory/i18n/es.json +2 -0
- package/src/modules/directory/i18n/pl.json +2 -0
- package/src/modules/planner/backend/planner/availability-rulesets/[id]/page.tsx +44 -4
- package/src/modules/planner/i18n/de.json +1 -0
- package/src/modules/planner/i18n/en.json +1 -0
- package/src/modules/planner/i18n/es.json +1 -0
- package/src/modules/planner/i18n/pl.json +1 -0
- package/src/modules/sales/backend/sales/channels/[channelId]/edit/page.tsx +36 -7
- package/src/modules/sales/i18n/de.json +1 -0
- package/src/modules/sales/i18n/en.json +1 -0
- package/src/modules/sales/i18n/es.json +1 -0
- package/src/modules/sales/i18n/pl.json +1 -0
- package/src/modules/staff/backend/staff/leave-requests/[id]/page.tsx +33 -6
- package/src/modules/staff/backend/staff/my-leave-requests/[id]/page.tsx +33 -6
- package/src/modules/staff/backend/staff/team-members/[id]/page.tsx +44 -4
- package/src/modules/staff/backend/staff/team-roles/[id]/edit/page.tsx +44 -4
- package/src/modules/staff/backend/staff/teams/[id]/edit/page.tsx +44 -4
- package/src/modules/staff/i18n/de.json +5 -0
- package/src/modules/staff/i18n/en.json +5 -0
- package/src/modules/staff/i18n/es.json +5 -0
- package/src/modules/staff/i18n/pl.json +5 -0
- package/src/modules/workflows/backend/definitions/[id]/page.tsx +26 -3
- package/src/modules/workflows/i18n/de.json +1 -0
- package/src/modules/workflows/i18n/en.json +1 -0
- package/src/modules/workflows/i18n/es.json +1 -0
- package/src/modules/workflows/i18n/pl.json +1 -0
package/dist/modules/catalog/backend/catalog/products/[productId]/variants/[variantId]/page.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../../../../../src/modules/catalog/backend/catalog/products/%5BproductId%5D/variants/%5BvariantId%5D/page.tsx"],
|
|
4
|
-
"sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { useRouter } from 'next/navigation'\nimport { Page, PageBody } from '@open-mercato/ui/backend/Page'\nimport { CrudForm, type CrudFormGroup } from '@open-mercato/ui/backend/CrudForm'\nimport { createCrud, updateCrud, deleteCrud } from '@open-mercato/ui/backend/utils/crud'\nimport { createCrudFormError } from '@open-mercato/ui/backend/utils/serverErrors'\nimport { collectCustomFieldValues } from '@open-mercato/ui/backend/utils/customFieldValues'\nimport { apiCall, readApiResultOrThrow } from '@open-mercato/ui/backend/utils/apiCall'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { ErrorMessage } from '@open-mercato/ui/backend/detail'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { extractCustomFieldEntries } from '@open-mercato/shared/lib/crud/custom-fields-client'\nimport { E } from '#generated/entities.ids.generated'\nimport { SendObjectMessageDialog } from '@open-mercato/ui/backend/messages'\nimport {\n type VariantFormValues,\n type VariantPriceDraft,\n type OptionDefinition,\n createVariantInitialValues,\n normalizeOptionSchema,\n mapPriceItemToDraft,\n findInvalidVariantPriceKinds,\n} from '@open-mercato/core/modules/catalog/components/products/variantForm'\nimport {\n type PriceKindSummary,\n type PriceKindApiPayload,\n type TaxRateSummary,\n normalizePriceKindSummary,\n} from '@open-mercato/core/modules/catalog/components/products/productForm'\nimport { parseNumericInput } from '@open-mercato/core/modules/catalog/components/products/productFormUtils'\nimport {\n VariantBasicsSection,\n VariantOptionValuesSection,\n VariantDimensionsSection,\n VariantMetadataSection,\n VariantPricesSection,\n VariantMediaSection,\n} from '@open-mercato/core/modules/catalog/components/products/VariantBuilder'\nimport type { ProductMediaItem } from '@open-mercato/core/modules/catalog/components/products/ProductMediaManager'\nimport { buildAttachmentImageUrl, slugifyAttachmentFileName } from '@open-mercato/core/modules/attachments/lib/imageUrls'\nimport { fetchOptionSchemaTemplate } from '../../../optionSchemaClient'\nimport CreateVariantPage from '../create/page'\n\ntype VariantResponse = {\n items?: Array<Record<string, unknown>>\n}\n\ntype ProductResponse = {\n items?: Array<{\n id?: string\n title?: string | null\n metadata?: Record<string, unknown> | null\n tax_rate_id?: string | null\n taxRateId?: string | null\n tax_rate?: number | string | null\n taxRate?: number | string | null\n }>\n}\n\ntype PriceListResponse = {\n items?: Array<Record<string, unknown>>\n}\n\ntype AttachmentListResponse = {\n items?: ProductMediaItem[]\n}\n\nfunction resolveVariantPriceLabel(prices: Record<string, VariantPriceDraft> | undefined): string | null {\n if (!prices || typeof prices !== 'object') return null\n const entries = Object.values(prices)\n for (const entry of entries) {\n const amount = typeof entry?.amount === 'string' ? entry.amount.trim() : ''\n if (!amount) continue\n const currencyCode =\n typeof entry.currencyCode === 'string' && entry.currencyCode.trim().length\n ? entry.currencyCode.trim().toUpperCase()\n : null\n return currencyCode ? `${currencyCode} ${amount}` : amount\n }\n return null\n}\n\nexport default function EditVariantPage({ params }: { params?: { productId?: string; variantId?: string } }) {\n const router = useRouter()\n const t = useT()\n const productId = params?.productId ? String(params.productId) : null\n const variantId = params?.variantId ? String(params.variantId) : null\n const isCreateSentinel = variantId === 'create'\n const [priceKinds, setPriceKinds] = React.useState<PriceKindSummary[]>([])\n const [taxRates, setTaxRates] = React.useState<TaxRateSummary[]>([])\n const [optionDefinitions, setOptionDefinitions] = React.useState<OptionDefinition[]>([])\n const [initialValues, setInitialValues] = React.useState<VariantFormValues | null>(null)\n const [existingPriceIds, setExistingPriceIds] = React.useState<Record<string, string>>({})\n const [loading, setLoading] = React.useState(true)\n const [error, setError] = React.useState<string | null>(null)\n const [currentProductId, setCurrentProductId] = React.useState<string | null>(productId)\n const [productTitle, setProductTitle] = React.useState<string>('')\n const [productTaxRateId, setProductTaxRateId] = React.useState<string | null>(null)\n const [productTaxRate, setProductTaxRate] = React.useState<number | null>(null)\n\n React.useEffect(() => {\n const loadPriceKinds = async () => {\n try {\n const payload = await readApiResultOrThrow<{ items?: PriceKindApiPayload[] }>(\n '/api/catalog/price-kinds?pageSize=100',\n undefined,\n { errorMessage: t('catalog.priceKinds.errors.load', 'Failed to load price kinds.') },\n )\n const items = Array.isArray(payload.items) ? payload.items : []\n setPriceKinds(items.map((item) => normalizePriceKindSummary(item)).filter((item): item is PriceKindSummary => !!item))\n } catch (err) {\n console.error('catalog.price-kinds.fetch failed', err)\n setPriceKinds([])\n }\n }\n loadPriceKinds().catch(() => {})\n }, [t])\n\n React.useEffect(() => {\n const loadTaxRates = async () => {\n try {\n const payload = await readApiResultOrThrow<{ items?: Array<Record<string, unknown>> }>(\n '/api/sales/tax-rates?pageSize=200',\n undefined,\n { errorMessage: t('catalog.products.create.taxRates.error', 'Failed to load tax rates.'), fallback: { items: [] } },\n )\n const items = Array.isArray(payload.items) ? payload.items : []\n setTaxRates(\n items.map((item) => {\n const rawRate = typeof item.rate === 'number' ? item.rate : Number(item.rate ?? Number.NaN)\n return {\n id: String(item.id),\n name:\n typeof item.name === 'string' && item.name.trim().length\n ? item.name\n : t('catalog.products.create.taxRates.unnamed', 'Untitled tax rate'),\n code: typeof item.code === 'string' && item.code.trim().length ? item.code : null,\n rate: Number.isFinite(rawRate) ? rawRate : null,\n isDefault: Boolean(\n typeof item.isDefault === 'boolean'\n ? item.isDefault\n : typeof item.is_default === 'boolean'\n ? item.is_default\n : false,\n ),\n }\n }),\n )\n } catch (err) {\n console.error('sales.tax-rates.fetch failed', err)\n setTaxRates([])\n }\n }\n loadTaxRates().catch(() => {})\n }, [t])\n\n React.useEffect(() => {\n if (!variantId || isCreateSentinel || priceKinds.length === 0) return\n let cancelled = false\n async function load() {\n setLoading(true)\n setError(null)\n try {\n const variantRes = await apiCall<VariantResponse>(\n `/api/catalog/variants?id=${encodeURIComponent(variantId!)}&page=1&pageSize=1`,\n )\n if (!variantRes.ok) throw new Error(t('catalog.variants.form.errors.load', 'Failed to load variant.'))\n const record = Array.isArray(variantRes.result?.items) ? variantRes.result?.items?.[0] : undefined\n if (!record) throw new Error(t('catalog.variants.form.errors.notFound', 'Variant not found.'))\n const resolvedProductId =\n typeof record.product_id === 'string'\n ? record.product_id\n : typeof record.productId === 'string'\n ? record.productId\n : currentProductId\n if (resolvedProductId) setCurrentProductId(resolvedProductId)\n const metadata = typeof record.metadata === 'object' && record.metadata ? { ...(record.metadata as Record<string, unknown>) } : {}\n const attachments = await fetchVariantAttachments(variantId!)\n const priceDrafts = await loadVariantPrices(variantId!, priceKinds)\n const priceIdMap: Record<string, string> = {}\n Object.entries(priceDrafts).forEach(([kindId, draft]) => {\n if (draft.priceId) priceIdMap[kindId] = draft.priceId\n })\n setExistingPriceIds(priceIdMap)\n const customDefaults = extractCustomFieldEntries(record)\n let loadedOptionDefinitions: OptionDefinition[] = []\n if (resolvedProductId) {\n const productRes = await apiCall<ProductResponse>(\n `/api/catalog/products?id=${encodeURIComponent(resolvedProductId)}&page=1&pageSize=1`,\n )\n if (productRes.ok) {\n const product = Array.isArray(productRes.result?.items) ? productRes.result?.items?.[0] : undefined\n if (product) {\n setProductTitle(typeof product.title === 'string' ? product.title : '')\n const taxRateId =\n typeof (product as any).tax_rate_id === 'string'\n ? (product as any).tax_rate_id\n : typeof (product as any).taxRateId === 'string'\n ? (product as any).taxRateId\n : null\n const taxRateValueRaw =\n typeof (product as any).tax_rate === 'number'\n ? (product as any).tax_rate\n : typeof (product as any).tax_rate === 'string'\n ? Number((product as any).tax_rate)\n : typeof (product as any).taxRate === 'number'\n ? (product as any).taxRate\n : typeof (product as any).taxRate === 'string'\n ? Number((product as any).taxRate)\n : null\n const taxRateValue = Number.isFinite(taxRateValueRaw) ? Number(taxRateValueRaw) : null\n setProductTaxRateId(taxRateId)\n setProductTaxRate(taxRateValue)\n const productMetadata = (product.metadata ?? {}) as Record<string, unknown>\n const optionSchemaId =\n typeof (product as any).option_schema_id === 'string'\n ? (product as any).option_schema_id\n : typeof (product as any).optionSchemaId === 'string'\n ? (product as any).optionSchemaId\n : null\n let schemaSource: unknown =\n productMetadata.optionSchema ?? (productMetadata.option_schema as unknown)\n if (optionSchemaId) {\n const template = await fetchOptionSchemaTemplate(optionSchemaId)\n if (template?.schema?.options) {\n schemaSource = template.schema.options.map((option) => ({\n code: option.code,\n label: option.label,\n values: Array.isArray(option.choices)\n ? option.choices.map((choice) => ({\n id: choice.code ?? undefined,\n label: choice.label ?? choice.code ?? '',\n }))\n : [],\n }))\n }\n }\n loadedOptionDefinitions = normalizeOptionSchema(schemaSource)\n setOptionDefinitions(loadedOptionDefinitions)\n }\n }\n }\n if (!cancelled) {\n const optionValues =\n typeof record.option_values === 'object' && record.option_values\n ? { ...(record.option_values as Record<string, string>) }\n : typeof record.optionValues === 'object' && record.optionValues\n ? { ...(record.optionValues as Record<string, string>) }\n : {}\n const normalizedOptionValues = reconcileOptionValues(optionValues, loadedOptionDefinitions)\n const defaultMediaId =\n typeof record.default_media_id === 'string'\n ? record.default_media_id\n : typeof record.defaultMediaId === 'string'\n ? record.defaultMediaId\n : attachments[0]?.id ?? null\n const defaultMediaUrl =\n typeof record.default_media_url === 'string'\n ? record.default_media_url\n : typeof record.defaultMediaUrl === 'string'\n ? record.defaultMediaUrl\n : ''\n const base = createVariantInitialValues()\n setInitialValues({\n ...base,\n mediaDraftId: variantId!,\n name: typeof record.name === 'string' ? record.name : '',\n sku: typeof record.sku === 'string' ? record.sku : '',\n barcode: typeof record.barcode === 'string' ? record.barcode : '',\n isDefault: record.is_default === true || record.isDefault === true,\n isActive: record.is_active !== false && record.isActive !== false,\n optionValues: normalizedOptionValues,\n metadata,\n mediaItems: attachments,\n defaultMediaId,\n defaultMediaUrl,\n prices: priceDrafts,\n taxRateId:\n typeof (record as any).tax_rate_id === 'string'\n ? (record as any).tax_rate_id\n : typeof (record as any).taxRateId === 'string'\n ? (record as any).taxRateId\n : null,\n customFieldsetCode:\n typeof record.custom_fieldset_code === 'string'\n ? record.custom_fieldset_code\n : typeof record.customFieldsetCode === 'string'\n ? record.customFieldsetCode\n : null,\n ...customDefaults,\n })\n }\n } catch (err) {\n console.error('catalog.variants.load.failed', err)\n if (!cancelled) {\n const message = err instanceof Error && err.message ? err.message : t('catalog.variants.form.errors.load', 'Failed to load variant.')\n setError(message)\n }\n } finally {\n if (!cancelled) setLoading(false)\n }\n }\n load()\n return () => { cancelled = true }\n }, [variantId, t, currentProductId, priceKinds])\n\n const groups = React.useMemo<CrudFormGroup[]>(() => {\n const list: CrudFormGroup[] = [\n {\n id: 'general',\n column: 1,\n title: t('catalog.variants.form.general', 'General'),\n component: ({ values, setValue, errors }) => (\n <VariantBasicsSection values={values as VariantFormValues} setValue={setValue} errors={errors} />\n ),\n },\n {\n id: 'metadata',\n column: 1,\n title: t('catalog.products.edit.metadata.title', 'Metadata'),\n description: t('catalog.products.edit.metadata.hint', 'Attach structured key/value pairs for integrations.'),\n component: ({ values, setValue }) => (\n <VariantMetadataSection values={values as VariantFormValues} setValue={setValue} showIntro={false} embedded />\n ),\n },\n {\n id: 'prices',\n column: 1,\n title: t('catalog.variants.form.pricesLabel', 'Prices'),\n description: t('catalog.variants.form.pricesHint', 'Populate list prices per price kind.'),\n component: ({ values, setValue }) => (\n <VariantPricesSection\n values={values as VariantFormValues}\n setValue={setValue}\n priceKinds={priceKinds}\n taxRates={taxRates}\n showHeader={false}\n embedded\n />\n ),\n },\n {\n id: 'media',\n column: 1,\n title: t('catalog.variants.form.media', 'Media'),\n component: ({ values, setValue }) => (\n <VariantMediaSection values={values as VariantFormValues} setValue={setValue} showLabel={false} />\n ),\n },\n ]\n\n if (optionDefinitions.length) {\n list.push({\n id: 'options',\n column: 2,\n title: t('catalog.variants.form.options', 'Option values'),\n component: ({ values, setValue }) => (\n <VariantOptionValuesSection\n values={values as VariantFormValues}\n setValue={setValue}\n optionDefinitions={optionDefinitions}\n showHeading={false}\n />\n ),\n })\n }\n\n list.push({\n id: 'dimensions',\n column: 2,\n title: t('catalog.variants.form.dimensions', 'Dimensions & weight'),\n component: ({ values, setValue }) => (\n <VariantDimensionsSection values={values as VariantFormValues} setValue={setValue} showHeading={false} />\n ),\n })\n\n list.push({\n id: 'custom',\n column: 2,\n title: t('catalog.variants.form.customFields', 'Custom attributes'),\n kind: 'customFields',\n })\n\n return list\n }, [optionDefinitions, priceKinds, t, taxRates])\n\n if (isCreateSentinel) {\n if (!productId) {\n return (\n <Page>\n <PageBody>\n <div className=\"rounded border border-destructive/40 bg-destructive/10 px-4 py-3 text-sm text-destructive\">\n {t('catalog.variants.form.errors.productMissing', 'Product identifier is missing.')}\n </div>\n </PageBody>\n </Page>\n )\n }\n return <CreateVariantPage params={{ productId }} />\n }\n\n if (!variantId || !currentProductId) {\n return (\n <Page>\n <PageBody>\n <div className=\"rounded border border-destructive/40 bg-destructive/10 px-4 py-3 text-sm text-destructive\">\n {t('catalog.variants.form.errors.variantMissing', 'Variant identifier is missing.')}\n </div>\n </PageBody>\n </Page>\n )\n }\n\n const formTitle = productTitle\n ? t('catalog.variants.form.editTitleFor', 'Edit variant \u2022 {{title}}').replace('{{title}}', productTitle)\n : t('catalog.variants.form.editTitle', 'Edit variant')\n const productVariantsHref = `/backend/catalog/products/${currentProductId}#variants`\n\n return (\n <Page>\n <PageBody>\n {error ? (\n <ErrorMessage label={error} className=\"mb-4\" />\n ) : null}\n <CrudForm<VariantFormValues>\n title={formTitle}\n backHref={productVariantsHref}\n versionHistory={{ resourceKind: 'catalog.variant', resourceId: variantId ? String(variantId) : '' }}\n extraActions={(\n <SendObjectMessageDialog\n object={{\n entityModule: 'catalog',\n entityType: 'variant',\n entityId: variantId,\n previewData: {\n title:\n (typeof initialValues?.name === 'string' && initialValues.name.trim().length\n ? initialValues.name\n : variantId),\n metadata: {\n [t('catalog.variants.form.skuLabel')]:\n (typeof initialValues?.sku === 'string' && initialValues.sku.trim().length\n ? initialValues.sku\n : '-'),\n [t('catalog.variants.form.pricesLabel')]:\n resolveVariantPriceLabel(initialValues?.prices) ?? '-',\n },\n },\n }}\n viewHref={`/backend/catalog/products/${currentProductId}/variants/${variantId}`}\n />\n )}\n fields={[]}\n groups={groups}\n entityId={E.catalog.catalog_product_variant}\n customFieldsetBindings={{ [E.catalog.catalog_product_variant]: { valueKey: 'customFieldsetCode' } }}\n initialValues={initialValues ?? undefined}\n isLoading={loading}\n loadingMessage={t('catalog.variants.form.loading', 'Loading variant...')}\n submitLabel={t('catalog.variants.form.save', 'Save changes')}\n cancelHref={productVariantsHref}\n onSubmit={async (values) => {\n const name = values.name?.trim()\n if (!name) {\n const message = t('catalog.variants.form.errors.nameRequired', 'Provide the variant name.')\n throw createCrudFormError(message, { name: message })\n }\n const invalidPriceKinds = findInvalidVariantPriceKinds(priceKinds, values.prices)\n if (invalidPriceKinds.length) {\n const message = t('catalog.variants.form.errors.invalidPrice', 'Provide a valid non-negative price.')\n throw createCrudFormError(message, { prices: message })\n }\n const resolveTaxRateValue = (taxRateId?: string | null) => {\n if (!taxRateId) return null\n const match = taxRates.find((rate) => rate.id === taxRateId)\n return typeof match?.rate === 'number' && Number.isFinite(match.rate) ? match.rate : null\n }\n const resolvedTaxRateId = values.taxRateId ?? productTaxRateId ?? null\n const resolvedTaxRateValue =\n values.taxRateId && resolvedTaxRateId\n ? resolveTaxRateValue(resolvedTaxRateId)\n : productTaxRateId\n ? resolveTaxRateValue(productTaxRateId) ?? productTaxRate\n : productTaxRate ?? null\n const metadata = typeof values.metadata === 'object' && values.metadata ? { ...values.metadata } : {}\n const defaultMediaEntry = values.defaultMediaId\n ? (Array.isArray(values.mediaItems) ? values.mediaItems : []).find((item) => item.id === values.defaultMediaId)\n : null\n const defaultMediaUrl = defaultMediaEntry\n ? buildAttachmentImageUrl(defaultMediaEntry.id, {\n slug: slugifyAttachmentFileName(defaultMediaEntry.fileName),\n })\n : null\n const payload: Record<string, unknown> = {\n id: variantId,\n productId: currentProductId,\n name,\n sku: values.sku?.trim() || undefined,\n barcode: values.barcode?.trim() || undefined,\n isDefault: Boolean(values.isDefault),\n isActive: values.isActive !== false,\n optionValues: Object.keys(values.optionValues ?? {}).length ? values.optionValues : undefined,\n metadata,\n defaultMediaId: values.defaultMediaId ?? undefined,\n defaultMediaUrl: defaultMediaUrl ?? undefined,\n customFieldsetCode: values.customFieldsetCode?.trim().length ? values.customFieldsetCode : undefined,\n taxRateId: resolvedTaxRateId,\n taxRate: resolvedTaxRateValue,\n }\n const customFields = collectCustomFieldValues(values)\n if (Object.keys(customFields).length) payload.customFields = customFields\n\n await updateCrud('catalog/variants', payload)\n await syncVariantPricesUpdate({\n priceKinds,\n priceDrafts: values.prices ?? {},\n existingPriceIds,\n productId: currentProductId,\n variantId,\n taxRates,\n taxRateId: values.taxRateId,\n productTaxRateId,\n productTaxRate,\n })\n flash(t('catalog.variants.form.updated', 'Variant updated.'), 'success')\n router.push(productVariantsHref)\n }}\n onDelete={async () => {\n await deleteCrud('catalog/variants', variantId!, {\n errorMessage: t('catalog.variants.form.deleteError', 'Failed to delete variant.'),\n })\n flash(t('catalog.variants.form.deleted', 'Variant deleted.'), 'success')\n router.push(productVariantsHref)\n }}\n deleteRedirect={productVariantsHref}\n />\n </PageBody>\n </Page>\n )\n}\n\nfunction reconcileOptionValues(\n optionValues: Record<string, string>,\n optionDefinitions: OptionDefinition[],\n): Record<string, string> {\n if (!optionValues || !optionDefinitions.length) {\n return optionValues ?? {}\n }\n const remaining = new Map(Object.entries(optionValues))\n const normalized: Record<string, string> = {}\n\n for (const option of optionDefinitions) {\n const code = option.code?.trim()\n if (!code) continue\n if (remaining.has(code)) {\n const value = remaining.get(code)\n if (value !== undefined) {\n normalized[code] = value\n }\n remaining.delete(code)\n continue\n }\n const matchKey = findOptionKeyByValue(remaining, option.values)\n if (matchKey) {\n const value = remaining.get(matchKey)\n if (value !== undefined) {\n normalized[code] = value\n }\n remaining.delete(matchKey)\n }\n }\n\n remaining.forEach((value, key) => {\n if (normalized[key] === undefined) {\n normalized[key] = value\n }\n })\n\n return normalized\n}\n\nfunction findOptionKeyByValue(\n candidates: Map<string, string>,\n optionValues: { id: string; label: string }[],\n): string | null {\n if (!optionValues.length) return null\n const matches: string[] = []\n candidates.forEach((value, key) => {\n if (optionValues.some((entry) => entry.label === value)) {\n matches.push(key)\n }\n })\n return matches.length === 1 ? matches[0] : null\n}\n\nasync function fetchVariantAttachments(variantId: string): Promise<ProductMediaItem[]> {\n try {\n const res = await apiCall<AttachmentListResponse>(\n `/api/attachments?entityId=${encodeURIComponent(E.catalog.catalog_product_variant)}&recordId=${encodeURIComponent(variantId)}`,\n )\n if (!res.ok) return []\n return Array.isArray(res.result?.items) ? res.result?.items ?? [] : []\n } catch (err) {\n console.error('catalog.variants.attachments.load', err)\n return []\n }\n}\n\nasync function loadVariantPrices(variantId: string, priceKinds: PriceKindSummary[]): Promise<Record<string, VariantPriceDraft>> {\n const kindDisplayModes = new Map(priceKinds.map((k) => [k.id, k.displayMode]))\n const drafts: Record<string, VariantPriceDraft> = {}\n const pageSize = 100\n let page = 1\n try {\n while (true) {\n const res = await apiCall<PriceListResponse>(\n `/api/catalog/prices?variantId=${encodeURIComponent(variantId)}&page=${page}&pageSize=${pageSize}`,\n )\n if (!res.ok) break\n const items = Array.isArray(res.result?.items) ? res.result?.items : []\n for (const item of items) {\n const draft = mapPriceItemToDraft(item as Record<string, unknown>, kindDisplayModes)\n if (draft) drafts[draft.priceKindId] = draft\n }\n if (items.length < pageSize) break\n page += 1\n }\n } catch (err) {\n console.error('catalog.variants.prices.load', err)\n }\n return drafts\n}\n\nasync function syncVariantPricesUpdate({\n priceKinds,\n priceDrafts,\n existingPriceIds,\n productId,\n variantId,\n taxRates,\n taxRateId,\n productTaxRateId,\n productTaxRate,\n}: {\n priceKinds: PriceKindSummary[]\n priceDrafts: Record<string, VariantPriceDraft>\n existingPriceIds: Record<string, string>\n productId: string\n variantId: string\n taxRates: TaxRateSummary[]\n taxRateId: string | null\n productTaxRateId?: string | null\n productTaxRate?: number | null\n}): Promise<void> {\n const selectedTaxRate = taxRates.find((rate) => rate.id === taxRateId) ?? null\n const fallbackProductTaxRate =\n !selectedTaxRate && productTaxRateId\n ? taxRates.find((rate) => rate.id === productTaxRateId) ?? null\n : null\n const resolvedTaxRateValue =\n selectedTaxRate?.rate ??\n fallbackProductTaxRate?.rate ??\n (Number.isFinite(productTaxRate ?? null) ? productTaxRate ?? null : null)\n const resolvedTaxRateId = (selectedTaxRate ?? fallbackProductTaxRate)?.id ?? null\n for (const kind of priceKinds) {\n const draft = priceDrafts?.[kind.id]\n const amount = typeof draft?.amount === 'string' ? draft.amount.trim() : ''\n const existingId = draft?.priceId ?? existingPriceIds[kind.id]\n if (!amount) {\n if (existingId) {\n try {\n await deleteCrud('catalog/prices', existingId)\n } catch (err) {\n console.error('catalog.prices.delete', err)\n }\n }\n continue\n }\n const numeric = parseNumericInput(amount)\n if (!Number.isFinite(numeric) || numeric < 0) continue\n const payload: Record<string, unknown> = {\n productId,\n variantId,\n priceKindId: kind.id,\n currencyCode: kind.currencyCode ?? undefined,\n }\n if (resolvedTaxRateId) payload.taxRateId = resolvedTaxRateId\n else if (typeof resolvedTaxRateValue === 'number' && Number.isFinite(resolvedTaxRateValue)) payload.taxRate = resolvedTaxRateValue\n if (kind.displayMode === 'including-tax') payload.unitPriceGross = numeric\n else payload.unitPriceNet = numeric\n if (existingId) {\n await updateCrud('catalog/prices', { id: existingId, ...payload })\n } else {\n await createCrud('catalog/prices', payload)\n }\n }\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { useRouter } from 'next/navigation'\nimport { Page, PageBody } from '@open-mercato/ui/backend/Page'\nimport { CrudForm, type CrudFormGroup } from '@open-mercato/ui/backend/CrudForm'\nimport { createCrud, updateCrud, deleteCrud } from '@open-mercato/ui/backend/utils/crud'\nimport { createCrudFormError } from '@open-mercato/ui/backend/utils/serverErrors'\nimport { collectCustomFieldValues } from '@open-mercato/ui/backend/utils/customFieldValues'\nimport { apiCall, readApiResultOrThrow } from '@open-mercato/ui/backend/utils/apiCall'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { ErrorMessage, RecordNotFoundState } from '@open-mercato/ui/backend/detail'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { extractCustomFieldEntries } from '@open-mercato/shared/lib/crud/custom-fields-client'\nimport { E } from '#generated/entities.ids.generated'\nimport { SendObjectMessageDialog } from '@open-mercato/ui/backend/messages'\nimport {\n type VariantFormValues,\n type VariantPriceDraft,\n type OptionDefinition,\n createVariantInitialValues,\n normalizeOptionSchema,\n mapPriceItemToDraft,\n findInvalidVariantPriceKinds,\n} from '@open-mercato/core/modules/catalog/components/products/variantForm'\nimport {\n type PriceKindSummary,\n type PriceKindApiPayload,\n type TaxRateSummary,\n normalizePriceKindSummary,\n} from '@open-mercato/core/modules/catalog/components/products/productForm'\nimport { parseNumericInput } from '@open-mercato/core/modules/catalog/components/products/productFormUtils'\nimport {\n VariantBasicsSection,\n VariantOptionValuesSection,\n VariantDimensionsSection,\n VariantMetadataSection,\n VariantPricesSection,\n VariantMediaSection,\n} from '@open-mercato/core/modules/catalog/components/products/VariantBuilder'\nimport type { ProductMediaItem } from '@open-mercato/core/modules/catalog/components/products/ProductMediaManager'\nimport { buildAttachmentImageUrl, slugifyAttachmentFileName } from '@open-mercato/core/modules/attachments/lib/imageUrls'\nimport { fetchOptionSchemaTemplate } from '../../../optionSchemaClient'\nimport CreateVariantPage from '../create/page'\n\ntype VariantResponse = {\n items?: Array<Record<string, unknown>>\n}\n\ntype ProductResponse = {\n items?: Array<{\n id?: string\n title?: string | null\n metadata?: Record<string, unknown> | null\n tax_rate_id?: string | null\n taxRateId?: string | null\n tax_rate?: number | string | null\n taxRate?: number | string | null\n }>\n}\n\ntype PriceListResponse = {\n items?: Array<Record<string, unknown>>\n}\n\ntype AttachmentListResponse = {\n items?: ProductMediaItem[]\n}\n\nfunction resolveVariantPriceLabel(prices: Record<string, VariantPriceDraft> | undefined): string | null {\n if (!prices || typeof prices !== 'object') return null\n const entries = Object.values(prices)\n for (const entry of entries) {\n const amount = typeof entry?.amount === 'string' ? entry.amount.trim() : ''\n if (!amount) continue\n const currencyCode =\n typeof entry.currencyCode === 'string' && entry.currencyCode.trim().length\n ? entry.currencyCode.trim().toUpperCase()\n : null\n return currencyCode ? `${currencyCode} ${amount}` : amount\n }\n return null\n}\n\nexport default function EditVariantPage({ params }: { params?: { productId?: string; variantId?: string } }) {\n const router = useRouter()\n const t = useT()\n const productId = params?.productId ? String(params.productId) : null\n const variantId = params?.variantId ? String(params.variantId) : null\n const isCreateSentinel = variantId === 'create'\n const [priceKinds, setPriceKinds] = React.useState<PriceKindSummary[]>([])\n const [taxRates, setTaxRates] = React.useState<TaxRateSummary[]>([])\n const [optionDefinitions, setOptionDefinitions] = React.useState<OptionDefinition[]>([])\n const [initialValues, setInitialValues] = React.useState<VariantFormValues | null>(null)\n const [existingPriceIds, setExistingPriceIds] = React.useState<Record<string, string>>({})\n const [loading, setLoading] = React.useState(true)\n const [error, setError] = React.useState<string | null>(null)\n const [isNotFound, setIsNotFound] = React.useState(false)\n const [currentProductId, setCurrentProductId] = React.useState<string | null>(productId)\n const [productTitle, setProductTitle] = React.useState<string>('')\n const [productTaxRateId, setProductTaxRateId] = React.useState<string | null>(null)\n const [productTaxRate, setProductTaxRate] = React.useState<number | null>(null)\n\n React.useEffect(() => {\n const loadPriceKinds = async () => {\n try {\n const payload = await readApiResultOrThrow<{ items?: PriceKindApiPayload[] }>(\n '/api/catalog/price-kinds?pageSize=100',\n undefined,\n { errorMessage: t('catalog.priceKinds.errors.load', 'Failed to load price kinds.') },\n )\n const items = Array.isArray(payload.items) ? payload.items : []\n setPriceKinds(items.map((item) => normalizePriceKindSummary(item)).filter((item): item is PriceKindSummary => !!item))\n } catch (err) {\n console.error('catalog.price-kinds.fetch failed', err)\n setPriceKinds([])\n }\n }\n loadPriceKinds().catch(() => {})\n }, [t])\n\n React.useEffect(() => {\n const loadTaxRates = async () => {\n try {\n const payload = await readApiResultOrThrow<{ items?: Array<Record<string, unknown>> }>(\n '/api/sales/tax-rates?pageSize=200',\n undefined,\n { errorMessage: t('catalog.products.create.taxRates.error', 'Failed to load tax rates.'), fallback: { items: [] } },\n )\n const items = Array.isArray(payload.items) ? payload.items : []\n setTaxRates(\n items.map((item) => {\n const rawRate = typeof item.rate === 'number' ? item.rate : Number(item.rate ?? Number.NaN)\n return {\n id: String(item.id),\n name:\n typeof item.name === 'string' && item.name.trim().length\n ? item.name\n : t('catalog.products.create.taxRates.unnamed', 'Untitled tax rate'),\n code: typeof item.code === 'string' && item.code.trim().length ? item.code : null,\n rate: Number.isFinite(rawRate) ? rawRate : null,\n isDefault: Boolean(\n typeof item.isDefault === 'boolean'\n ? item.isDefault\n : typeof item.is_default === 'boolean'\n ? item.is_default\n : false,\n ),\n }\n }),\n )\n } catch (err) {\n console.error('sales.tax-rates.fetch failed', err)\n setTaxRates([])\n }\n }\n loadTaxRates().catch(() => {})\n }, [t])\n\n React.useEffect(() => {\n if (!variantId || isCreateSentinel || priceKinds.length === 0) return\n let cancelled = false\n async function load() {\n setLoading(true)\n setError(null)\n setIsNotFound(false)\n try {\n const variantRes = await apiCall<VariantResponse>(\n `/api/catalog/variants?id=${encodeURIComponent(variantId!)}&page=1&pageSize=1`,\n )\n if (!variantRes.ok) {\n if (variantRes.status === 404) {\n if (!cancelled) setIsNotFound(true)\n return\n }\n throw new Error(t('catalog.variants.form.errors.load', 'Failed to load variant.'))\n }\n const record = Array.isArray(variantRes.result?.items) ? variantRes.result?.items?.[0] : undefined\n if (!record) {\n if (!cancelled) setIsNotFound(true)\n return\n }\n const resolvedProductId =\n typeof record.product_id === 'string'\n ? record.product_id\n : typeof record.productId === 'string'\n ? record.productId\n : currentProductId\n if (resolvedProductId) setCurrentProductId(resolvedProductId)\n const metadata = typeof record.metadata === 'object' && record.metadata ? { ...(record.metadata as Record<string, unknown>) } : {}\n const attachments = await fetchVariantAttachments(variantId!)\n const priceDrafts = await loadVariantPrices(variantId!, priceKinds)\n const priceIdMap: Record<string, string> = {}\n Object.entries(priceDrafts).forEach(([kindId, draft]) => {\n if (draft.priceId) priceIdMap[kindId] = draft.priceId\n })\n setExistingPriceIds(priceIdMap)\n const customDefaults = extractCustomFieldEntries(record)\n let loadedOptionDefinitions: OptionDefinition[] = []\n if (resolvedProductId) {\n const productRes = await apiCall<ProductResponse>(\n `/api/catalog/products?id=${encodeURIComponent(resolvedProductId)}&page=1&pageSize=1`,\n )\n if (productRes.ok) {\n const product = Array.isArray(productRes.result?.items) ? productRes.result?.items?.[0] : undefined\n if (product) {\n setProductTitle(typeof product.title === 'string' ? product.title : '')\n const taxRateId =\n typeof (product as any).tax_rate_id === 'string'\n ? (product as any).tax_rate_id\n : typeof (product as any).taxRateId === 'string'\n ? (product as any).taxRateId\n : null\n const taxRateValueRaw =\n typeof (product as any).tax_rate === 'number'\n ? (product as any).tax_rate\n : typeof (product as any).tax_rate === 'string'\n ? Number((product as any).tax_rate)\n : typeof (product as any).taxRate === 'number'\n ? (product as any).taxRate\n : typeof (product as any).taxRate === 'string'\n ? Number((product as any).taxRate)\n : null\n const taxRateValue = Number.isFinite(taxRateValueRaw) ? Number(taxRateValueRaw) : null\n setProductTaxRateId(taxRateId)\n setProductTaxRate(taxRateValue)\n const productMetadata = (product.metadata ?? {}) as Record<string, unknown>\n const optionSchemaId =\n typeof (product as any).option_schema_id === 'string'\n ? (product as any).option_schema_id\n : typeof (product as any).optionSchemaId === 'string'\n ? (product as any).optionSchemaId\n : null\n let schemaSource: unknown =\n productMetadata.optionSchema ?? (productMetadata.option_schema as unknown)\n if (optionSchemaId) {\n const template = await fetchOptionSchemaTemplate(optionSchemaId)\n if (template?.schema?.options) {\n schemaSource = template.schema.options.map((option) => ({\n code: option.code,\n label: option.label,\n values: Array.isArray(option.choices)\n ? option.choices.map((choice) => ({\n id: choice.code ?? undefined,\n label: choice.label ?? choice.code ?? '',\n }))\n : [],\n }))\n }\n }\n loadedOptionDefinitions = normalizeOptionSchema(schemaSource)\n setOptionDefinitions(loadedOptionDefinitions)\n }\n }\n }\n if (!cancelled) {\n const optionValues =\n typeof record.option_values === 'object' && record.option_values\n ? { ...(record.option_values as Record<string, string>) }\n : typeof record.optionValues === 'object' && record.optionValues\n ? { ...(record.optionValues as Record<string, string>) }\n : {}\n const normalizedOptionValues = reconcileOptionValues(optionValues, loadedOptionDefinitions)\n const defaultMediaId =\n typeof record.default_media_id === 'string'\n ? record.default_media_id\n : typeof record.defaultMediaId === 'string'\n ? record.defaultMediaId\n : attachments[0]?.id ?? null\n const defaultMediaUrl =\n typeof record.default_media_url === 'string'\n ? record.default_media_url\n : typeof record.defaultMediaUrl === 'string'\n ? record.defaultMediaUrl\n : ''\n const base = createVariantInitialValues()\n setInitialValues({\n ...base,\n mediaDraftId: variantId!,\n name: typeof record.name === 'string' ? record.name : '',\n sku: typeof record.sku === 'string' ? record.sku : '',\n barcode: typeof record.barcode === 'string' ? record.barcode : '',\n isDefault: record.is_default === true || record.isDefault === true,\n isActive: record.is_active !== false && record.isActive !== false,\n optionValues: normalizedOptionValues,\n metadata,\n mediaItems: attachments,\n defaultMediaId,\n defaultMediaUrl,\n prices: priceDrafts,\n taxRateId:\n typeof (record as any).tax_rate_id === 'string'\n ? (record as any).tax_rate_id\n : typeof (record as any).taxRateId === 'string'\n ? (record as any).taxRateId\n : null,\n customFieldsetCode:\n typeof record.custom_fieldset_code === 'string'\n ? record.custom_fieldset_code\n : typeof record.customFieldsetCode === 'string'\n ? record.customFieldsetCode\n : null,\n ...customDefaults,\n })\n }\n } catch (err) {\n console.error('catalog.variants.load.failed', err)\n if (!cancelled) {\n const message = err instanceof Error && err.message ? err.message : t('catalog.variants.form.errors.load', 'Failed to load variant.')\n setError(message)\n }\n } finally {\n if (!cancelled) setLoading(false)\n }\n }\n load()\n return () => { cancelled = true }\n }, [variantId, t, currentProductId, priceKinds])\n\n const groups = React.useMemo<CrudFormGroup[]>(() => {\n const list: CrudFormGroup[] = [\n {\n id: 'general',\n column: 1,\n title: t('catalog.variants.form.general', 'General'),\n component: ({ values, setValue, errors }) => (\n <VariantBasicsSection values={values as VariantFormValues} setValue={setValue} errors={errors} />\n ),\n },\n {\n id: 'metadata',\n column: 1,\n title: t('catalog.products.edit.metadata.title', 'Metadata'),\n description: t('catalog.products.edit.metadata.hint', 'Attach structured key/value pairs for integrations.'),\n component: ({ values, setValue }) => (\n <VariantMetadataSection values={values as VariantFormValues} setValue={setValue} showIntro={false} embedded />\n ),\n },\n {\n id: 'prices',\n column: 1,\n title: t('catalog.variants.form.pricesLabel', 'Prices'),\n description: t('catalog.variants.form.pricesHint', 'Populate list prices per price kind.'),\n component: ({ values, setValue }) => (\n <VariantPricesSection\n values={values as VariantFormValues}\n setValue={setValue}\n priceKinds={priceKinds}\n taxRates={taxRates}\n showHeader={false}\n embedded\n />\n ),\n },\n {\n id: 'media',\n column: 1,\n title: t('catalog.variants.form.media', 'Media'),\n component: ({ values, setValue }) => (\n <VariantMediaSection values={values as VariantFormValues} setValue={setValue} showLabel={false} />\n ),\n },\n ]\n\n if (optionDefinitions.length) {\n list.push({\n id: 'options',\n column: 2,\n title: t('catalog.variants.form.options', 'Option values'),\n component: ({ values, setValue }) => (\n <VariantOptionValuesSection\n values={values as VariantFormValues}\n setValue={setValue}\n optionDefinitions={optionDefinitions}\n showHeading={false}\n />\n ),\n })\n }\n\n list.push({\n id: 'dimensions',\n column: 2,\n title: t('catalog.variants.form.dimensions', 'Dimensions & weight'),\n component: ({ values, setValue }) => (\n <VariantDimensionsSection values={values as VariantFormValues} setValue={setValue} showHeading={false} />\n ),\n })\n\n list.push({\n id: 'custom',\n column: 2,\n title: t('catalog.variants.form.customFields', 'Custom attributes'),\n kind: 'customFields',\n })\n\n return list\n }, [optionDefinitions, priceKinds, t, taxRates])\n\n if (isCreateSentinel) {\n if (!productId) {\n return (\n <Page>\n <PageBody>\n <div className=\"rounded border border-destructive/40 bg-destructive/10 px-4 py-3 text-sm text-destructive\">\n {t('catalog.variants.form.errors.productMissing', 'Product identifier is missing.')}\n </div>\n </PageBody>\n </Page>\n )\n }\n return <CreateVariantPage params={{ productId }} />\n }\n\n if (!variantId || !currentProductId) {\n return (\n <Page>\n <PageBody>\n <div className=\"rounded border border-destructive/40 bg-destructive/10 px-4 py-3 text-sm text-destructive\">\n {t('catalog.variants.form.errors.variantMissing', 'Variant identifier is missing.')}\n </div>\n </PageBody>\n </Page>\n )\n }\n\n const formTitle = productTitle\n ? t('catalog.variants.form.editTitleFor', 'Edit variant \u2022 {{title}}').replace('{{title}}', productTitle)\n : t('catalog.variants.form.editTitle', 'Edit variant')\n const productVariantsHref = `/backend/catalog/products/${currentProductId}#variants`\n\n if (isNotFound) {\n return (\n <Page>\n <PageBody>\n <RecordNotFoundState\n label={t('catalog.variants.form.errors.notFound', 'Variant not found.')}\n backHref={productVariantsHref}\n backLabel={t('catalog.variants.form.actions.backToProduct', 'Back to product variants')}\n />\n </PageBody>\n </Page>\n )\n }\n\n if (error && !loading) {\n return (\n <Page>\n <PageBody>\n <ErrorMessage label={error} />\n </PageBody>\n </Page>\n )\n }\n\n return (\n <Page>\n <PageBody>\n <CrudForm<VariantFormValues>\n title={formTitle}\n backHref={productVariantsHref}\n versionHistory={{ resourceKind: 'catalog.variant', resourceId: variantId ? String(variantId) : '' }}\n extraActions={(\n <SendObjectMessageDialog\n object={{\n entityModule: 'catalog',\n entityType: 'variant',\n entityId: variantId,\n previewData: {\n title:\n (typeof initialValues?.name === 'string' && initialValues.name.trim().length\n ? initialValues.name\n : variantId),\n metadata: {\n [t('catalog.variants.form.skuLabel')]:\n (typeof initialValues?.sku === 'string' && initialValues.sku.trim().length\n ? initialValues.sku\n : '-'),\n [t('catalog.variants.form.pricesLabel')]:\n resolveVariantPriceLabel(initialValues?.prices) ?? '-',\n },\n },\n }}\n viewHref={`/backend/catalog/products/${currentProductId}/variants/${variantId}`}\n />\n )}\n fields={[]}\n groups={groups}\n entityId={E.catalog.catalog_product_variant}\n customFieldsetBindings={{ [E.catalog.catalog_product_variant]: { valueKey: 'customFieldsetCode' } }}\n initialValues={initialValues ?? undefined}\n isLoading={loading}\n loadingMessage={t('catalog.variants.form.loading', 'Loading variant...')}\n submitLabel={t('catalog.variants.form.save', 'Save changes')}\n cancelHref={productVariantsHref}\n onSubmit={async (values) => {\n const name = values.name?.trim()\n if (!name) {\n const message = t('catalog.variants.form.errors.nameRequired', 'Provide the variant name.')\n throw createCrudFormError(message, { name: message })\n }\n const invalidPriceKinds = findInvalidVariantPriceKinds(priceKinds, values.prices)\n if (invalidPriceKinds.length) {\n const message = t('catalog.variants.form.errors.invalidPrice', 'Provide a valid non-negative price.')\n throw createCrudFormError(message, { prices: message })\n }\n const resolveTaxRateValue = (taxRateId?: string | null) => {\n if (!taxRateId) return null\n const match = taxRates.find((rate) => rate.id === taxRateId)\n return typeof match?.rate === 'number' && Number.isFinite(match.rate) ? match.rate : null\n }\n const resolvedTaxRateId = values.taxRateId ?? productTaxRateId ?? null\n const resolvedTaxRateValue =\n values.taxRateId && resolvedTaxRateId\n ? resolveTaxRateValue(resolvedTaxRateId)\n : productTaxRateId\n ? resolveTaxRateValue(productTaxRateId) ?? productTaxRate\n : productTaxRate ?? null\n const metadata = typeof values.metadata === 'object' && values.metadata ? { ...values.metadata } : {}\n const defaultMediaEntry = values.defaultMediaId\n ? (Array.isArray(values.mediaItems) ? values.mediaItems : []).find((item) => item.id === values.defaultMediaId)\n : null\n const defaultMediaUrl = defaultMediaEntry\n ? buildAttachmentImageUrl(defaultMediaEntry.id, {\n slug: slugifyAttachmentFileName(defaultMediaEntry.fileName),\n })\n : null\n const payload: Record<string, unknown> = {\n id: variantId,\n productId: currentProductId,\n name,\n sku: values.sku?.trim() || undefined,\n barcode: values.barcode?.trim() || undefined,\n isDefault: Boolean(values.isDefault),\n isActive: values.isActive !== false,\n optionValues: Object.keys(values.optionValues ?? {}).length ? values.optionValues : undefined,\n metadata,\n defaultMediaId: values.defaultMediaId ?? undefined,\n defaultMediaUrl: defaultMediaUrl ?? undefined,\n customFieldsetCode: values.customFieldsetCode?.trim().length ? values.customFieldsetCode : undefined,\n taxRateId: resolvedTaxRateId,\n taxRate: resolvedTaxRateValue,\n }\n const customFields = collectCustomFieldValues(values)\n if (Object.keys(customFields).length) payload.customFields = customFields\n\n await updateCrud('catalog/variants', payload)\n await syncVariantPricesUpdate({\n priceKinds,\n priceDrafts: values.prices ?? {},\n existingPriceIds,\n productId: currentProductId,\n variantId,\n taxRates,\n taxRateId: values.taxRateId,\n productTaxRateId,\n productTaxRate,\n })\n flash(t('catalog.variants.form.updated', 'Variant updated.'), 'success')\n router.push(productVariantsHref)\n }}\n onDelete={async () => {\n await deleteCrud('catalog/variants', variantId!, {\n errorMessage: t('catalog.variants.form.deleteError', 'Failed to delete variant.'),\n })\n flash(t('catalog.variants.form.deleted', 'Variant deleted.'), 'success')\n router.push(productVariantsHref)\n }}\n deleteRedirect={productVariantsHref}\n />\n </PageBody>\n </Page>\n )\n}\n\nfunction reconcileOptionValues(\n optionValues: Record<string, string>,\n optionDefinitions: OptionDefinition[],\n): Record<string, string> {\n if (!optionValues || !optionDefinitions.length) {\n return optionValues ?? {}\n }\n const remaining = new Map(Object.entries(optionValues))\n const normalized: Record<string, string> = {}\n\n for (const option of optionDefinitions) {\n const code = option.code?.trim()\n if (!code) continue\n if (remaining.has(code)) {\n const value = remaining.get(code)\n if (value !== undefined) {\n normalized[code] = value\n }\n remaining.delete(code)\n continue\n }\n const matchKey = findOptionKeyByValue(remaining, option.values)\n if (matchKey) {\n const value = remaining.get(matchKey)\n if (value !== undefined) {\n normalized[code] = value\n }\n remaining.delete(matchKey)\n }\n }\n\n remaining.forEach((value, key) => {\n if (normalized[key] === undefined) {\n normalized[key] = value\n }\n })\n\n return normalized\n}\n\nfunction findOptionKeyByValue(\n candidates: Map<string, string>,\n optionValues: { id: string; label: string }[],\n): string | null {\n if (!optionValues.length) return null\n const matches: string[] = []\n candidates.forEach((value, key) => {\n if (optionValues.some((entry) => entry.label === value)) {\n matches.push(key)\n }\n })\n return matches.length === 1 ? matches[0] : null\n}\n\nasync function fetchVariantAttachments(variantId: string): Promise<ProductMediaItem[]> {\n try {\n const res = await apiCall<AttachmentListResponse>(\n `/api/attachments?entityId=${encodeURIComponent(E.catalog.catalog_product_variant)}&recordId=${encodeURIComponent(variantId)}`,\n )\n if (!res.ok) return []\n return Array.isArray(res.result?.items) ? res.result?.items ?? [] : []\n } catch (err) {\n console.error('catalog.variants.attachments.load', err)\n return []\n }\n}\n\nasync function loadVariantPrices(variantId: string, priceKinds: PriceKindSummary[]): Promise<Record<string, VariantPriceDraft>> {\n const kindDisplayModes = new Map(priceKinds.map((k) => [k.id, k.displayMode]))\n const drafts: Record<string, VariantPriceDraft> = {}\n const pageSize = 100\n let page = 1\n try {\n while (true) {\n const res = await apiCall<PriceListResponse>(\n `/api/catalog/prices?variantId=${encodeURIComponent(variantId)}&page=${page}&pageSize=${pageSize}`,\n )\n if (!res.ok) break\n const items = Array.isArray(res.result?.items) ? res.result?.items : []\n for (const item of items) {\n const draft = mapPriceItemToDraft(item as Record<string, unknown>, kindDisplayModes)\n if (draft) drafts[draft.priceKindId] = draft\n }\n if (items.length < pageSize) break\n page += 1\n }\n } catch (err) {\n console.error('catalog.variants.prices.load', err)\n }\n return drafts\n}\n\nasync function syncVariantPricesUpdate({\n priceKinds,\n priceDrafts,\n existingPriceIds,\n productId,\n variantId,\n taxRates,\n taxRateId,\n productTaxRateId,\n productTaxRate,\n}: {\n priceKinds: PriceKindSummary[]\n priceDrafts: Record<string, VariantPriceDraft>\n existingPriceIds: Record<string, string>\n productId: string\n variantId: string\n taxRates: TaxRateSummary[]\n taxRateId: string | null\n productTaxRateId?: string | null\n productTaxRate?: number | null\n}): Promise<void> {\n const selectedTaxRate = taxRates.find((rate) => rate.id === taxRateId) ?? null\n const fallbackProductTaxRate =\n !selectedTaxRate && productTaxRateId\n ? taxRates.find((rate) => rate.id === productTaxRateId) ?? null\n : null\n const resolvedTaxRateValue =\n selectedTaxRate?.rate ??\n fallbackProductTaxRate?.rate ??\n (Number.isFinite(productTaxRate ?? null) ? productTaxRate ?? null : null)\n const resolvedTaxRateId = (selectedTaxRate ?? fallbackProductTaxRate)?.id ?? null\n for (const kind of priceKinds) {\n const draft = priceDrafts?.[kind.id]\n const amount = typeof draft?.amount === 'string' ? draft.amount.trim() : ''\n const existingId = draft?.priceId ?? existingPriceIds[kind.id]\n if (!amount) {\n if (existingId) {\n try {\n await deleteCrud('catalog/prices', existingId)\n } catch (err) {\n console.error('catalog.prices.delete', err)\n }\n }\n continue\n }\n const numeric = parseNumericInput(amount)\n if (!Number.isFinite(numeric) || numeric < 0) continue\n const payload: Record<string, unknown> = {\n productId,\n variantId,\n priceKindId: kind.id,\n currencyCode: kind.currencyCode ?? undefined,\n }\n if (resolvedTaxRateId) payload.taxRateId = resolvedTaxRateId\n else if (typeof resolvedTaxRateValue === 'number' && Number.isFinite(resolvedTaxRateValue)) payload.taxRate = resolvedTaxRateValue\n if (kind.displayMode === 'including-tax') payload.unitPriceGross = numeric\n else payload.unitPriceNet = numeric\n if (existingId) {\n await updateCrud('catalog/prices', { id: existingId, ...payload })\n } else {\n await createCrud('catalog/prices', payload)\n }\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -170,9 +170,13 @@ function PipelineStagesPage() {
|
|
|
170
170
|
setSaving(true);
|
|
171
171
|
try {
|
|
172
172
|
if (stageDialog?.mode === "create") {
|
|
173
|
+
const appearancePayload = {
|
|
174
|
+
...stageColor !== null ? { color: stageColor } : {},
|
|
175
|
+
...stageIcon !== null ? { icon: stageIcon } : {}
|
|
176
|
+
};
|
|
173
177
|
const result = await apiCall("/api/customers/pipeline-stages", {
|
|
174
178
|
method: "POST",
|
|
175
|
-
body: JSON.stringify({ pipelineId: selectedPipelineId, label: stageName.trim(),
|
|
179
|
+
body: JSON.stringify({ pipelineId: selectedPipelineId, label: stageName.trim(), ...appearancePayload }),
|
|
176
180
|
headers: { "Content-Type": "application/json" }
|
|
177
181
|
});
|
|
178
182
|
if (!result.ok) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../../../src/modules/customers/backend/config/customers/pipeline-stages/page.tsx"],
|
|
4
|
-
"sourcesContent": ["'use client'\n\nimport * as React from 'react'\nimport { Page, PageBody } from '@open-mercato/ui/backend/Page'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { apiCall } from '@open-mercato/ui/backend/utils/apiCall'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { Input } from '@open-mercato/ui/primitives/input'\nimport { Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter } from '@open-mercato/ui/primitives/dialog'\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from '@open-mercato/ui/primitives/select'\nimport { Spinner } from '@open-mercato/ui/primitives/spinner'\nimport { useConfirmDialog } from '@open-mercato/ui/backend/confirm-dialog'\nimport { AppearanceSelector, type AppearanceSelectorLabels } from '@open-mercato/core/modules/dictionaries/components/AppearanceSelector'\nimport { renderDictionaryColor, renderDictionaryIcon, ICON_SUGGESTIONS } from '@open-mercato/core/modules/dictionaries/components/dictionaryAppearance'\n\ntype Pipeline = {\n id: string\n name: string\n isDefault: boolean\n}\n\ntype PipelineStage = {\n id: string\n pipelineId: string\n label: string\n order: number\n color: string | null\n icon: string | null\n}\n\ntype PipelineDialogState =\n | { mode: 'create' }\n | { mode: 'edit'; pipeline: Pipeline }\n | null\n\ntype StageDialogState =\n | { mode: 'create' }\n | { mode: 'edit'; stage: PipelineStage }\n | null\n\nexport default function PipelineStagesPage() {\n const t = useT()\n const { confirm, ConfirmDialogElement } = useConfirmDialog()\n\n const [pipelines, setPipelines] = React.useState<Pipeline[]>([])\n const [selectedPipelineId, setSelectedPipelineId] = React.useState<string | null>(null)\n const [stages, setStages] = React.useState<PipelineStage[]>([])\n const [loadingPipelines, setLoadingPipelines] = React.useState(true)\n const [loadingStages, setLoadingStages] = React.useState(false)\n const [pipelineDialog, setPipelineDialog] = React.useState<PipelineDialogState>(null)\n const [stageDialog, setStageDialog] = React.useState<StageDialogState>(null)\n const [pipelineName, setPipelineName] = React.useState('')\n const [pipelineIsDefault, setPipelineIsDefault] = React.useState(false)\n const [stageName, setStageName] = React.useState('')\n const [stageColor, setStageColor] = React.useState<string | null>(null)\n const [stageIcon, setStageIcon] = React.useState<string | null>(null)\n const [saving, setSaving] = React.useState(false)\n\n const selectedPipeline = React.useMemo(\n () => pipelines.find((p) => p.id === selectedPipelineId) ?? null,\n [pipelines, selectedPipelineId],\n )\n\n const loadPipelines = React.useCallback(async () => {\n setLoadingPipelines(true)\n try {\n const result = await apiCall<{ items: Pipeline[] }>('/api/customers/pipelines')\n if (result.ok && result.result?.items) {\n const items = result.result.items\n setPipelines(items)\n if (!selectedPipelineId && items.length > 0) {\n const defaultPipeline = items.find((p) => p.isDefault) ?? items[0]\n setSelectedPipelineId(defaultPipeline.id)\n }\n }\n } catch {\n flash(t('customers.config.pipelineStages.errorLoadPipelines', 'Failed to load pipelines'), 'error')\n } finally {\n setLoadingPipelines(false)\n }\n }, [selectedPipelineId, t])\n\n const loadStages = React.useCallback(async (pipelineId: string) => {\n setLoadingStages(true)\n try {\n const result = await apiCall<{ items: PipelineStage[] }>(\n `/api/customers/pipeline-stages?pipelineId=${encodeURIComponent(pipelineId)}`\n )\n if (result.ok && result.result?.items) {\n setStages(result.result.items)\n }\n } catch {\n flash(t('customers.config.pipelineStages.errorLoadStages', 'Failed to load pipeline stages'), 'error')\n } finally {\n setLoadingStages(false)\n }\n }, [t])\n\n React.useEffect(() => {\n void loadPipelines()\n }, [loadPipelines])\n\n React.useEffect(() => {\n if (selectedPipelineId) {\n void loadStages(selectedPipelineId)\n } else {\n setStages([])\n }\n }, [selectedPipelineId, loadStages])\n\n function openCreatePipeline() {\n setPipelineName('')\n setPipelineIsDefault(false)\n setPipelineDialog({ mode: 'create' })\n }\n\n function openEditPipeline(pipeline: Pipeline) {\n setPipelineName(pipeline.name)\n setPipelineIsDefault(pipeline.isDefault)\n setPipelineDialog({ mode: 'edit', pipeline })\n }\n\n async function savePipeline() {\n if (!pipelineName.trim()) return\n setSaving(true)\n try {\n if (pipelineDialog?.mode === 'create') {\n const result = await apiCall<{ id: string }>('/api/customers/pipelines', {\n method: 'POST',\n body: JSON.stringify({ name: pipelineName.trim(), isDefault: pipelineIsDefault }),\n headers: { 'Content-Type': 'application/json' },\n })\n if (!result.ok) {\n flash(t('customers.config.pipelineStages.errorCreatePipeline', 'Failed to create pipeline'), 'error')\n return\n }\n flash(t('customers.config.pipelineStages.createdPipeline', 'Pipeline created'), 'success')\n const newId = result.result?.id ?? null\n await loadPipelines()\n if (newId) setSelectedPipelineId(newId)\n } else if (pipelineDialog?.mode === 'edit') {\n const result = await apiCall('/api/customers/pipelines', {\n method: 'PUT',\n body: JSON.stringify({ id: pipelineDialog.pipeline.id, name: pipelineName.trim(), isDefault: pipelineIsDefault }),\n headers: { 'Content-Type': 'application/json' },\n })\n if (!result.ok) {\n flash(t('customers.config.pipelineStages.errorUpdatePipeline', 'Failed to update pipeline'), 'error')\n return\n }\n flash(t('customers.config.pipelineStages.updatedPipeline', 'Pipeline updated'), 'success')\n await loadPipelines()\n }\n setPipelineDialog(null)\n } finally {\n setSaving(false)\n }\n }\n\n async function deletePipeline(pipeline: Pipeline) {\n const confirmed = await confirm({\n title: t('customers.config.pipelineStages.deletePipelineTitle', 'Delete pipeline?'),\n text: t(\n 'customers.config.pipelineStages.deletePipelineDesc',\n 'This pipeline and all its stages will be permanently removed. Deals assigned to it will lose their pipeline assignment.',\n ),\n confirmText: t('customers.config.pipelineStages.deletePipelineConfirm', 'Delete'),\n variant: 'destructive',\n })\n if (!confirmed) return\n const result = await apiCall('/api/customers/pipelines', {\n method: 'DELETE',\n body: JSON.stringify({ id: pipeline.id }),\n headers: { 'Content-Type': 'application/json' },\n })\n if (!result.ok) {\n const error = (result.result as { error?: string })?.error\n flash(error ?? t('customers.config.pipelineStages.errorDeletePipeline', 'Failed to delete pipeline'), 'error')\n return\n }\n flash(t('customers.config.pipelineStages.deletedPipeline', 'Pipeline deleted'), 'success')\n if (selectedPipelineId === pipeline.id) setSelectedPipelineId(null)\n await loadPipelines()\n }\n\n function openCreateStage() {\n setStageName('')\n setStageColor(null)\n setStageIcon(null)\n setStageDialog({ mode: 'create' })\n }\n\n function openEditStage(stage: PipelineStage) {\n setStageName(stage.label)\n setStageColor(stage.color)\n setStageIcon(stage.icon)\n setStageDialog({ mode: 'edit', stage })\n }\n\n async function saveStage() {\n if (!stageName.trim() || !selectedPipelineId) return\n setSaving(true)\n try {\n if (stageDialog?.mode === 'create') {\n const result = await apiCall('/api/customers/pipeline-stages', {\n method: 'POST',\n body: JSON.stringify({ pipelineId: selectedPipelineId, label: stageName.trim(), color: stageColor, icon: stageIcon }),\n headers: { 'Content-Type': 'application/json' },\n })\n if (!result.ok) {\n flash(t('customers.config.pipelineStages.errorCreateStage', 'Failed to create stage'), 'error')\n return\n }\n flash(t('customers.config.pipelineStages.createdStage', 'Stage created'), 'success')\n } else if (stageDialog?.mode === 'edit') {\n const result = await apiCall('/api/customers/pipeline-stages', {\n method: 'PUT',\n body: JSON.stringify({ id: stageDialog.stage.id, label: stageName.trim(), color: stageColor, icon: stageIcon }),\n headers: { 'Content-Type': 'application/json' },\n })\n if (!result.ok) {\n flash(t('customers.config.pipelineStages.errorUpdateStage', 'Failed to update stage'), 'error')\n return\n }\n flash(t('customers.config.pipelineStages.updatedStage', 'Stage updated'), 'success')\n }\n setStageDialog(null)\n await loadStages(selectedPipelineId)\n } finally {\n setSaving(false)\n }\n }\n\n async function deleteStage(stage: PipelineStage) {\n const confirmed = await confirm({\n title: t('customers.config.pipelineStages.deleteStagTitle', 'Delete stage?'),\n text: t(\n 'customers.config.pipelineStages.deleteStageDesc',\n 'This stage will be permanently removed. Deals assigned to it will lose their stage assignment.',\n ),\n confirmText: t('customers.config.pipelineStages.deleteStageConfirm', 'Delete'),\n variant: 'destructive',\n })\n if (!confirmed) return\n const result = await apiCall('/api/customers/pipeline-stages', {\n method: 'DELETE',\n body: JSON.stringify({ id: stage.id }),\n headers: { 'Content-Type': 'application/json' },\n })\n if (!result.ok) {\n const error = (result.result as { error?: string })?.error\n flash(error ?? t('customers.config.pipelineStages.errorDeleteStage', 'Failed to delete stage'), 'error')\n return\n }\n flash(t('customers.config.pipelineStages.deletedStage', 'Stage deleted'), 'success')\n if (selectedPipelineId) await loadStages(selectedPipelineId)\n }\n\n async function moveStage(index: number, direction: 'up' | 'down') {\n const nextIndex = direction === 'up' ? index - 1 : index + 1\n if (nextIndex < 0 || nextIndex >= stages.length) return\n\n const reordered = [...stages]\n const [moved] = reordered.splice(index, 1)\n reordered.splice(nextIndex, 0, moved)\n\n const updated = reordered.map((stage, i) => ({ ...stage, order: i }))\n setStages(updated)\n\n const result = await apiCall('/api/customers/pipeline-stages/reorder', {\n method: 'POST',\n body: JSON.stringify({ stages: updated.map((s) => ({ id: s.id, order: s.order })) }),\n headers: { 'Content-Type': 'application/json' },\n })\n if (!result.ok) {\n flash(t('customers.config.pipelineStages.errorReorder', 'Failed to reorder stages'), 'error')\n if (selectedPipelineId) await loadStages(selectedPipelineId)\n }\n }\n\n const appearanceLabels = React.useMemo<AppearanceSelectorLabels>(() => ({\n colorLabel: t('customers.config.pipelineStages.colorLabel', 'Color'),\n colorHelp: t('customers.config.pipelineStages.colorHelp', 'Pick a highlight color for this entry.'),\n colorClearLabel: t('customers.config.pipelineStages.colorClear', 'Remove color'),\n iconLabel: t('customers.config.pipelineStages.iconLabel', 'Icon'),\n iconPlaceholder: t('customers.config.pipelineStages.iconPlaceholder', 'Type an emoji or pick one of the suggestions.'),\n iconPickerTriggerLabel: t('customers.config.pipelineStages.iconBrowse', 'Browse icons and emojis'),\n iconSearchPlaceholder: t('customers.config.pipelineStages.iconSearchPlaceholder', 'Search icons or emojis\u2026'),\n iconSearchEmptyLabel: t('customers.config.pipelineStages.iconSearchEmpty', 'No icons match your search.'),\n iconSuggestionsLabel: t('customers.config.pipelineStages.iconSuggestions', 'Suggestions'),\n iconClearLabel: t('customers.config.pipelineStages.iconClear', 'Remove icon'),\n previewEmptyLabel: t('customers.config.pipelineStages.previewEmpty', 'None'),\n }), [t])\n\n return (\n <Page>\n <PageBody>\n <div className=\"space-y-6 max-w-2xl\">\n <div className=\"flex items-center justify-between\">\n <h2 className=\"text-lg font-semibold\">\n {t('customers.config.pipelineStages.title', 'Pipeline stages')}\n </h2>\n <a\n href=\"/backend/customers/deals/pipeline\"\n className=\"text-sm text-muted-foreground hover:underline\"\n >\n {t('customers.config.pipelineStages.viewBoard', 'View pipeline board')} \u2192\n </a>\n </div>\n\n {loadingPipelines ? (\n <div className=\"flex items-center gap-2 text-sm text-muted-foreground\">\n <Spinner size=\"sm\" />\n {t('customers.config.pipelineStages.loadingPipelines', 'Loading pipelines\u2026')}\n </div>\n ) : (\n <>\n <div className=\"flex items-center gap-3\">\n <Select\n value={selectedPipelineId || undefined}\n onValueChange={(value) => setSelectedPipelineId(value || null)}\n disabled={pipelines.length === 0}\n >\n <SelectTrigger className=\"w-full max-w-xs\">\n <SelectValue\n placeholder={\n pipelines.length === 0\n ? t('customers.config.pipelineStages.noPipelines', 'No pipelines yet')\n : undefined\n }\n />\n </SelectTrigger>\n <SelectContent>\n {pipelines.map((p) => (\n <SelectItem key={p.id} value={p.id}>\n {p.name}{p.isDefault ? ` (${t('customers.config.pipelineStages.default', 'default')})` : ''}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n {selectedPipeline && (\n <>\n <Button variant=\"outline\" size=\"sm\" onClick={() => openEditPipeline(selectedPipeline)}>\n {t('customers.config.pipelineStages.editPipeline', 'Edit')}\n </Button>\n <Button\n variant=\"outline\"\n size=\"sm\"\n className=\"text-destructive\"\n onClick={() => deletePipeline(selectedPipeline)}\n >\n {t('customers.config.pipelineStages.deletePipeline', 'Delete')}\n </Button>\n </>\n )}\n <Button variant=\"outline\" size=\"sm\" onClick={openCreatePipeline}>\n {t('customers.config.pipelineStages.addPipeline', '+ Add pipeline')}\n </Button>\n </div>\n\n {selectedPipelineId && (\n <div className=\"space-y-3\">\n <div className=\"flex items-center justify-between\">\n <h3 className=\"text-sm font-medium text-muted-foreground\">\n {t('customers.config.pipelineStages.stagesTitle', 'Stages')}\n </h3>\n <Button size=\"sm\" onClick={openCreateStage}>\n {t('customers.config.pipelineStages.addStage', '+ Add stage')}\n </Button>\n </div>\n\n {loadingStages ? (\n <div className=\"flex items-center gap-2 text-sm text-muted-foreground\">\n <Spinner size=\"sm\" />\n {t('customers.config.pipelineStages.loadingStages', 'Loading stages\u2026')}\n </div>\n ) : stages.length === 0 ? (\n <p className=\"text-sm text-muted-foreground\">\n {t('customers.config.pipelineStages.noStages', 'No stages yet. Add your first stage.')}\n </p>\n ) : (\n <div className=\"divide-y rounded-md border\">\n {stages.map((stage, index) => (\n <div key={stage.id} className=\"flex items-center gap-3 px-4 py-3\">\n <div className=\"flex flex-col gap-1\">\n <button\n type=\"button\"\n className=\"text-muted-foreground hover:text-foreground disabled:opacity-50\"\n onClick={() => moveStage(index, 'up')}\n disabled={index === 0}\n aria-label={t('customers.config.pipelineStages.moveUp', 'Move up')}\n >\n \u2191\n </button>\n <button\n type=\"button\"\n className=\"text-muted-foreground hover:text-foreground disabled:opacity-50\"\n onClick={() => moveStage(index, 'down')}\n disabled={index === stages.length - 1}\n aria-label={t('customers.config.pipelineStages.moveDown', 'Move down')}\n >\n \u2193\n </button>\n </div>\n <span className=\"flex-1 text-sm flex items-center gap-2\">\n {stage.color ? renderDictionaryColor(stage.color) : null}\n {stage.icon ? renderDictionaryIcon(stage.icon) : null}\n {stage.label}\n </span>\n <Button variant=\"ghost\" size=\"sm\" onClick={() => openEditStage(stage)}>\n {t('customers.config.pipelineStages.editStage', 'Edit')}\n </Button>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n className=\"text-destructive\"\n onClick={() => deleteStage(stage)}\n >\n {t('customers.config.pipelineStages.deleteStage', 'Delete')}\n </Button>\n </div>\n ))}\n </div>\n )}\n </div>\n )}\n </>\n )}\n </div>\n\n <Dialog open={pipelineDialog !== null} onOpenChange={(open) => { if (!open) setPipelineDialog(null) }}>\n <DialogContent>\n <DialogHeader>\n <DialogTitle>\n {pipelineDialog?.mode === 'create'\n ? t('customers.config.pipelineStages.createPipelineTitle', 'Create pipeline')\n : t('customers.config.pipelineStages.editPipelineTitle', 'Edit pipeline')}\n </DialogTitle>\n </DialogHeader>\n <div className=\"space-y-4 py-2\">\n <div className=\"space-y-1\">\n <label className=\"text-sm font-medium\">\n {t('customers.config.pipelineStages.pipelineName', 'Name')}\n </label>\n <Input\n value={pipelineName}\n onChange={(e) => setPipelineName(e.target.value)}\n placeholder={t('customers.config.pipelineStages.pipelineNamePlaceholder', 'e.g. Sales Pipeline')}\n onKeyDown={(e) => { if (e.key === 'Enter') { e.preventDefault(); void savePipeline() } }}\n autoFocus\n />\n </div>\n <label className=\"flex items-center gap-2 text-sm cursor-pointer\">\n <input\n type=\"checkbox\"\n checked={pipelineIsDefault}\n onChange={(e) => setPipelineIsDefault(e.target.checked)}\n />\n {t('customers.config.pipelineStages.setAsDefault', 'Set as default pipeline')}\n </label>\n </div>\n <DialogFooter>\n <Button variant=\"outline\" onClick={() => setPipelineDialog(null)} disabled={saving}>\n {t('customers.config.pipelineStages.cancel', 'Cancel')}\n </Button>\n <Button onClick={() => void savePipeline()} disabled={saving || !pipelineName.trim()}>\n {saving ? <Spinner size=\"sm\" /> : t('customers.config.pipelineStages.save', 'Save')}\n </Button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n\n <Dialog open={stageDialog !== null} onOpenChange={(open) => { if (!open) setStageDialog(null) }}>\n <DialogContent>\n <DialogHeader>\n <DialogTitle>\n {stageDialog?.mode === 'create'\n ? t('customers.config.pipelineStages.createStageTitle', 'Create stage')\n : t('customers.config.pipelineStages.editStageTitle', 'Edit stage')}\n </DialogTitle>\n </DialogHeader>\n <div className=\"space-y-4 py-2\">\n <div className=\"space-y-1\">\n <label className=\"text-sm font-medium\">\n {t('customers.config.pipelineStages.stageName', 'Stage name')}\n </label>\n <Input\n value={stageName}\n onChange={(e) => setStageName(e.target.value)}\n placeholder={t('customers.config.pipelineStages.stageNamePlaceholder', 'e.g. Qualification')}\n onKeyDown={(e) => { if (e.key === 'Enter') { e.preventDefault(); void saveStage() } }}\n autoFocus\n />\n </div>\n <AppearanceSelector\n color={stageColor}\n icon={stageIcon}\n onColorChange={setStageColor}\n onIconChange={setStageIcon}\n labels={appearanceLabels}\n iconSuggestions={ICON_SUGGESTIONS}\n />\n </div>\n <DialogFooter>\n <Button variant=\"outline\" onClick={() => setStageDialog(null)} disabled={saving}>\n {t('customers.config.pipelineStages.cancel', 'Cancel')}\n </Button>\n <Button onClick={() => void saveStage()} disabled={saving || !stageName.trim()}>\n {saving ? <Spinner size=\"sm\" /> : t('customers.config.pipelineStages.save', 'Save')}\n </Button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n {ConfirmDialogElement}\n </PageBody>\n </Page>\n )\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["'use client'\n\nimport * as React from 'react'\nimport { Page, PageBody } from '@open-mercato/ui/backend/Page'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { apiCall } from '@open-mercato/ui/backend/utils/apiCall'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { Input } from '@open-mercato/ui/primitives/input'\nimport { Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter } from '@open-mercato/ui/primitives/dialog'\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from '@open-mercato/ui/primitives/select'\nimport { Spinner } from '@open-mercato/ui/primitives/spinner'\nimport { useConfirmDialog } from '@open-mercato/ui/backend/confirm-dialog'\nimport { AppearanceSelector, type AppearanceSelectorLabels } from '@open-mercato/core/modules/dictionaries/components/AppearanceSelector'\nimport { renderDictionaryColor, renderDictionaryIcon, ICON_SUGGESTIONS } from '@open-mercato/core/modules/dictionaries/components/dictionaryAppearance'\n\ntype Pipeline = {\n id: string\n name: string\n isDefault: boolean\n}\n\ntype PipelineStage = {\n id: string\n pipelineId: string\n label: string\n order: number\n color: string | null\n icon: string | null\n}\n\ntype PipelineDialogState =\n | { mode: 'create' }\n | { mode: 'edit'; pipeline: Pipeline }\n | null\n\ntype StageDialogState =\n | { mode: 'create' }\n | { mode: 'edit'; stage: PipelineStage }\n | null\n\nexport default function PipelineStagesPage() {\n const t = useT()\n const { confirm, ConfirmDialogElement } = useConfirmDialog()\n\n const [pipelines, setPipelines] = React.useState<Pipeline[]>([])\n const [selectedPipelineId, setSelectedPipelineId] = React.useState<string | null>(null)\n const [stages, setStages] = React.useState<PipelineStage[]>([])\n const [loadingPipelines, setLoadingPipelines] = React.useState(true)\n const [loadingStages, setLoadingStages] = React.useState(false)\n const [pipelineDialog, setPipelineDialog] = React.useState<PipelineDialogState>(null)\n const [stageDialog, setStageDialog] = React.useState<StageDialogState>(null)\n const [pipelineName, setPipelineName] = React.useState('')\n const [pipelineIsDefault, setPipelineIsDefault] = React.useState(false)\n const [stageName, setStageName] = React.useState('')\n const [stageColor, setStageColor] = React.useState<string | null>(null)\n const [stageIcon, setStageIcon] = React.useState<string | null>(null)\n const [saving, setSaving] = React.useState(false)\n\n const selectedPipeline = React.useMemo(\n () => pipelines.find((p) => p.id === selectedPipelineId) ?? null,\n [pipelines, selectedPipelineId],\n )\n\n const loadPipelines = React.useCallback(async () => {\n setLoadingPipelines(true)\n try {\n const result = await apiCall<{ items: Pipeline[] }>('/api/customers/pipelines')\n if (result.ok && result.result?.items) {\n const items = result.result.items\n setPipelines(items)\n if (!selectedPipelineId && items.length > 0) {\n const defaultPipeline = items.find((p) => p.isDefault) ?? items[0]\n setSelectedPipelineId(defaultPipeline.id)\n }\n }\n } catch {\n flash(t('customers.config.pipelineStages.errorLoadPipelines', 'Failed to load pipelines'), 'error')\n } finally {\n setLoadingPipelines(false)\n }\n }, [selectedPipelineId, t])\n\n const loadStages = React.useCallback(async (pipelineId: string) => {\n setLoadingStages(true)\n try {\n const result = await apiCall<{ items: PipelineStage[] }>(\n `/api/customers/pipeline-stages?pipelineId=${encodeURIComponent(pipelineId)}`\n )\n if (result.ok && result.result?.items) {\n setStages(result.result.items)\n }\n } catch {\n flash(t('customers.config.pipelineStages.errorLoadStages', 'Failed to load pipeline stages'), 'error')\n } finally {\n setLoadingStages(false)\n }\n }, [t])\n\n React.useEffect(() => {\n void loadPipelines()\n }, [loadPipelines])\n\n React.useEffect(() => {\n if (selectedPipelineId) {\n void loadStages(selectedPipelineId)\n } else {\n setStages([])\n }\n }, [selectedPipelineId, loadStages])\n\n function openCreatePipeline() {\n setPipelineName('')\n setPipelineIsDefault(false)\n setPipelineDialog({ mode: 'create' })\n }\n\n function openEditPipeline(pipeline: Pipeline) {\n setPipelineName(pipeline.name)\n setPipelineIsDefault(pipeline.isDefault)\n setPipelineDialog({ mode: 'edit', pipeline })\n }\n\n async function savePipeline() {\n if (!pipelineName.trim()) return\n setSaving(true)\n try {\n if (pipelineDialog?.mode === 'create') {\n const result = await apiCall<{ id: string }>('/api/customers/pipelines', {\n method: 'POST',\n body: JSON.stringify({ name: pipelineName.trim(), isDefault: pipelineIsDefault }),\n headers: { 'Content-Type': 'application/json' },\n })\n if (!result.ok) {\n flash(t('customers.config.pipelineStages.errorCreatePipeline', 'Failed to create pipeline'), 'error')\n return\n }\n flash(t('customers.config.pipelineStages.createdPipeline', 'Pipeline created'), 'success')\n const newId = result.result?.id ?? null\n await loadPipelines()\n if (newId) setSelectedPipelineId(newId)\n } else if (pipelineDialog?.mode === 'edit') {\n const result = await apiCall('/api/customers/pipelines', {\n method: 'PUT',\n body: JSON.stringify({ id: pipelineDialog.pipeline.id, name: pipelineName.trim(), isDefault: pipelineIsDefault }),\n headers: { 'Content-Type': 'application/json' },\n })\n if (!result.ok) {\n flash(t('customers.config.pipelineStages.errorUpdatePipeline', 'Failed to update pipeline'), 'error')\n return\n }\n flash(t('customers.config.pipelineStages.updatedPipeline', 'Pipeline updated'), 'success')\n await loadPipelines()\n }\n setPipelineDialog(null)\n } finally {\n setSaving(false)\n }\n }\n\n async function deletePipeline(pipeline: Pipeline) {\n const confirmed = await confirm({\n title: t('customers.config.pipelineStages.deletePipelineTitle', 'Delete pipeline?'),\n text: t(\n 'customers.config.pipelineStages.deletePipelineDesc',\n 'This pipeline and all its stages will be permanently removed. Deals assigned to it will lose their pipeline assignment.',\n ),\n confirmText: t('customers.config.pipelineStages.deletePipelineConfirm', 'Delete'),\n variant: 'destructive',\n })\n if (!confirmed) return\n const result = await apiCall('/api/customers/pipelines', {\n method: 'DELETE',\n body: JSON.stringify({ id: pipeline.id }),\n headers: { 'Content-Type': 'application/json' },\n })\n if (!result.ok) {\n const error = (result.result as { error?: string })?.error\n flash(error ?? t('customers.config.pipelineStages.errorDeletePipeline', 'Failed to delete pipeline'), 'error')\n return\n }\n flash(t('customers.config.pipelineStages.deletedPipeline', 'Pipeline deleted'), 'success')\n if (selectedPipelineId === pipeline.id) setSelectedPipelineId(null)\n await loadPipelines()\n }\n\n function openCreateStage() {\n setStageName('')\n setStageColor(null)\n setStageIcon(null)\n setStageDialog({ mode: 'create' })\n }\n\n function openEditStage(stage: PipelineStage) {\n setStageName(stage.label)\n setStageColor(stage.color)\n setStageIcon(stage.icon)\n setStageDialog({ mode: 'edit', stage })\n }\n\n async function saveStage() {\n if (!stageName.trim() || !selectedPipelineId) return\n setSaving(true)\n try {\n if (stageDialog?.mode === 'create') {\n const appearancePayload = {\n ...(stageColor !== null ? { color: stageColor } : {}),\n ...(stageIcon !== null ? { icon: stageIcon } : {}),\n }\n const result = await apiCall('/api/customers/pipeline-stages', {\n method: 'POST',\n body: JSON.stringify({ pipelineId: selectedPipelineId, label: stageName.trim(), ...appearancePayload }),\n headers: { 'Content-Type': 'application/json' },\n })\n if (!result.ok) {\n flash(t('customers.config.pipelineStages.errorCreateStage', 'Failed to create stage'), 'error')\n return\n }\n flash(t('customers.config.pipelineStages.createdStage', 'Stage created'), 'success')\n } else if (stageDialog?.mode === 'edit') {\n const result = await apiCall('/api/customers/pipeline-stages', {\n method: 'PUT',\n body: JSON.stringify({ id: stageDialog.stage.id, label: stageName.trim(), color: stageColor, icon: stageIcon }),\n headers: { 'Content-Type': 'application/json' },\n })\n if (!result.ok) {\n flash(t('customers.config.pipelineStages.errorUpdateStage', 'Failed to update stage'), 'error')\n return\n }\n flash(t('customers.config.pipelineStages.updatedStage', 'Stage updated'), 'success')\n }\n setStageDialog(null)\n await loadStages(selectedPipelineId)\n } finally {\n setSaving(false)\n }\n }\n\n async function deleteStage(stage: PipelineStage) {\n const confirmed = await confirm({\n title: t('customers.config.pipelineStages.deleteStagTitle', 'Delete stage?'),\n text: t(\n 'customers.config.pipelineStages.deleteStageDesc',\n 'This stage will be permanently removed. Deals assigned to it will lose their stage assignment.',\n ),\n confirmText: t('customers.config.pipelineStages.deleteStageConfirm', 'Delete'),\n variant: 'destructive',\n })\n if (!confirmed) return\n const result = await apiCall('/api/customers/pipeline-stages', {\n method: 'DELETE',\n body: JSON.stringify({ id: stage.id }),\n headers: { 'Content-Type': 'application/json' },\n })\n if (!result.ok) {\n const error = (result.result as { error?: string })?.error\n flash(error ?? t('customers.config.pipelineStages.errorDeleteStage', 'Failed to delete stage'), 'error')\n return\n }\n flash(t('customers.config.pipelineStages.deletedStage', 'Stage deleted'), 'success')\n if (selectedPipelineId) await loadStages(selectedPipelineId)\n }\n\n async function moveStage(index: number, direction: 'up' | 'down') {\n const nextIndex = direction === 'up' ? index - 1 : index + 1\n if (nextIndex < 0 || nextIndex >= stages.length) return\n\n const reordered = [...stages]\n const [moved] = reordered.splice(index, 1)\n reordered.splice(nextIndex, 0, moved)\n\n const updated = reordered.map((stage, i) => ({ ...stage, order: i }))\n setStages(updated)\n\n const result = await apiCall('/api/customers/pipeline-stages/reorder', {\n method: 'POST',\n body: JSON.stringify({ stages: updated.map((s) => ({ id: s.id, order: s.order })) }),\n headers: { 'Content-Type': 'application/json' },\n })\n if (!result.ok) {\n flash(t('customers.config.pipelineStages.errorReorder', 'Failed to reorder stages'), 'error')\n if (selectedPipelineId) await loadStages(selectedPipelineId)\n }\n }\n\n const appearanceLabels = React.useMemo<AppearanceSelectorLabels>(() => ({\n colorLabel: t('customers.config.pipelineStages.colorLabel', 'Color'),\n colorHelp: t('customers.config.pipelineStages.colorHelp', 'Pick a highlight color for this entry.'),\n colorClearLabel: t('customers.config.pipelineStages.colorClear', 'Remove color'),\n iconLabel: t('customers.config.pipelineStages.iconLabel', 'Icon'),\n iconPlaceholder: t('customers.config.pipelineStages.iconPlaceholder', 'Type an emoji or pick one of the suggestions.'),\n iconPickerTriggerLabel: t('customers.config.pipelineStages.iconBrowse', 'Browse icons and emojis'),\n iconSearchPlaceholder: t('customers.config.pipelineStages.iconSearchPlaceholder', 'Search icons or emojis\u2026'),\n iconSearchEmptyLabel: t('customers.config.pipelineStages.iconSearchEmpty', 'No icons match your search.'),\n iconSuggestionsLabel: t('customers.config.pipelineStages.iconSuggestions', 'Suggestions'),\n iconClearLabel: t('customers.config.pipelineStages.iconClear', 'Remove icon'),\n previewEmptyLabel: t('customers.config.pipelineStages.previewEmpty', 'None'),\n }), [t])\n\n return (\n <Page>\n <PageBody>\n <div className=\"space-y-6 max-w-2xl\">\n <div className=\"flex items-center justify-between\">\n <h2 className=\"text-lg font-semibold\">\n {t('customers.config.pipelineStages.title', 'Pipeline stages')}\n </h2>\n <a\n href=\"/backend/customers/deals/pipeline\"\n className=\"text-sm text-muted-foreground hover:underline\"\n >\n {t('customers.config.pipelineStages.viewBoard', 'View pipeline board')} \u2192\n </a>\n </div>\n\n {loadingPipelines ? (\n <div className=\"flex items-center gap-2 text-sm text-muted-foreground\">\n <Spinner size=\"sm\" />\n {t('customers.config.pipelineStages.loadingPipelines', 'Loading pipelines\u2026')}\n </div>\n ) : (\n <>\n <div className=\"flex items-center gap-3\">\n <Select\n value={selectedPipelineId || undefined}\n onValueChange={(value) => setSelectedPipelineId(value || null)}\n disabled={pipelines.length === 0}\n >\n <SelectTrigger className=\"w-full max-w-xs\">\n <SelectValue\n placeholder={\n pipelines.length === 0\n ? t('customers.config.pipelineStages.noPipelines', 'No pipelines yet')\n : undefined\n }\n />\n </SelectTrigger>\n <SelectContent>\n {pipelines.map((p) => (\n <SelectItem key={p.id} value={p.id}>\n {p.name}{p.isDefault ? ` (${t('customers.config.pipelineStages.default', 'default')})` : ''}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n {selectedPipeline && (\n <>\n <Button variant=\"outline\" size=\"sm\" onClick={() => openEditPipeline(selectedPipeline)}>\n {t('customers.config.pipelineStages.editPipeline', 'Edit')}\n </Button>\n <Button\n variant=\"outline\"\n size=\"sm\"\n className=\"text-destructive\"\n onClick={() => deletePipeline(selectedPipeline)}\n >\n {t('customers.config.pipelineStages.deletePipeline', 'Delete')}\n </Button>\n </>\n )}\n <Button variant=\"outline\" size=\"sm\" onClick={openCreatePipeline}>\n {t('customers.config.pipelineStages.addPipeline', '+ Add pipeline')}\n </Button>\n </div>\n\n {selectedPipelineId && (\n <div className=\"space-y-3\">\n <div className=\"flex items-center justify-between\">\n <h3 className=\"text-sm font-medium text-muted-foreground\">\n {t('customers.config.pipelineStages.stagesTitle', 'Stages')}\n </h3>\n <Button size=\"sm\" onClick={openCreateStage}>\n {t('customers.config.pipelineStages.addStage', '+ Add stage')}\n </Button>\n </div>\n\n {loadingStages ? (\n <div className=\"flex items-center gap-2 text-sm text-muted-foreground\">\n <Spinner size=\"sm\" />\n {t('customers.config.pipelineStages.loadingStages', 'Loading stages\u2026')}\n </div>\n ) : stages.length === 0 ? (\n <p className=\"text-sm text-muted-foreground\">\n {t('customers.config.pipelineStages.noStages', 'No stages yet. Add your first stage.')}\n </p>\n ) : (\n <div className=\"divide-y rounded-md border\">\n {stages.map((stage, index) => (\n <div key={stage.id} className=\"flex items-center gap-3 px-4 py-3\">\n <div className=\"flex flex-col gap-1\">\n <button\n type=\"button\"\n className=\"text-muted-foreground hover:text-foreground disabled:opacity-50\"\n onClick={() => moveStage(index, 'up')}\n disabled={index === 0}\n aria-label={t('customers.config.pipelineStages.moveUp', 'Move up')}\n >\n \u2191\n </button>\n <button\n type=\"button\"\n className=\"text-muted-foreground hover:text-foreground disabled:opacity-50\"\n onClick={() => moveStage(index, 'down')}\n disabled={index === stages.length - 1}\n aria-label={t('customers.config.pipelineStages.moveDown', 'Move down')}\n >\n \u2193\n </button>\n </div>\n <span className=\"flex-1 text-sm flex items-center gap-2\">\n {stage.color ? renderDictionaryColor(stage.color) : null}\n {stage.icon ? renderDictionaryIcon(stage.icon) : null}\n {stage.label}\n </span>\n <Button variant=\"ghost\" size=\"sm\" onClick={() => openEditStage(stage)}>\n {t('customers.config.pipelineStages.editStage', 'Edit')}\n </Button>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n className=\"text-destructive\"\n onClick={() => deleteStage(stage)}\n >\n {t('customers.config.pipelineStages.deleteStage', 'Delete')}\n </Button>\n </div>\n ))}\n </div>\n )}\n </div>\n )}\n </>\n )}\n </div>\n\n <Dialog open={pipelineDialog !== null} onOpenChange={(open) => { if (!open) setPipelineDialog(null) }}>\n <DialogContent>\n <DialogHeader>\n <DialogTitle>\n {pipelineDialog?.mode === 'create'\n ? t('customers.config.pipelineStages.createPipelineTitle', 'Create pipeline')\n : t('customers.config.pipelineStages.editPipelineTitle', 'Edit pipeline')}\n </DialogTitle>\n </DialogHeader>\n <div className=\"space-y-4 py-2\">\n <div className=\"space-y-1\">\n <label className=\"text-sm font-medium\">\n {t('customers.config.pipelineStages.pipelineName', 'Name')}\n </label>\n <Input\n value={pipelineName}\n onChange={(e) => setPipelineName(e.target.value)}\n placeholder={t('customers.config.pipelineStages.pipelineNamePlaceholder', 'e.g. Sales Pipeline')}\n onKeyDown={(e) => { if (e.key === 'Enter') { e.preventDefault(); void savePipeline() } }}\n autoFocus\n />\n </div>\n <label className=\"flex items-center gap-2 text-sm cursor-pointer\">\n <input\n type=\"checkbox\"\n checked={pipelineIsDefault}\n onChange={(e) => setPipelineIsDefault(e.target.checked)}\n />\n {t('customers.config.pipelineStages.setAsDefault', 'Set as default pipeline')}\n </label>\n </div>\n <DialogFooter>\n <Button variant=\"outline\" onClick={() => setPipelineDialog(null)} disabled={saving}>\n {t('customers.config.pipelineStages.cancel', 'Cancel')}\n </Button>\n <Button onClick={() => void savePipeline()} disabled={saving || !pipelineName.trim()}>\n {saving ? <Spinner size=\"sm\" /> : t('customers.config.pipelineStages.save', 'Save')}\n </Button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n\n <Dialog open={stageDialog !== null} onOpenChange={(open) => { if (!open) setStageDialog(null) }}>\n <DialogContent>\n <DialogHeader>\n <DialogTitle>\n {stageDialog?.mode === 'create'\n ? t('customers.config.pipelineStages.createStageTitle', 'Create stage')\n : t('customers.config.pipelineStages.editStageTitle', 'Edit stage')}\n </DialogTitle>\n </DialogHeader>\n <div className=\"space-y-4 py-2\">\n <div className=\"space-y-1\">\n <label className=\"text-sm font-medium\">\n {t('customers.config.pipelineStages.stageName', 'Stage name')}\n </label>\n <Input\n value={stageName}\n onChange={(e) => setStageName(e.target.value)}\n placeholder={t('customers.config.pipelineStages.stageNamePlaceholder', 'e.g. Qualification')}\n onKeyDown={(e) => { if (e.key === 'Enter') { e.preventDefault(); void saveStage() } }}\n autoFocus\n />\n </div>\n <AppearanceSelector\n color={stageColor}\n icon={stageIcon}\n onColorChange={setStageColor}\n onIconChange={setStageIcon}\n labels={appearanceLabels}\n iconSuggestions={ICON_SUGGESTIONS}\n />\n </div>\n <DialogFooter>\n <Button variant=\"outline\" onClick={() => setStageDialog(null)} disabled={saving}>\n {t('customers.config.pipelineStages.cancel', 'Cancel')}\n </Button>\n <Button onClick={() => void saveStage()} disabled={saving || !stageName.trim()}>\n {saving ? <Spinner size=\"sm\" /> : t('customers.config.pipelineStages.save', 'Save')}\n </Button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n {ConfirmDialogElement}\n </PageBody>\n </Page>\n )\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -407,15 +407,15 @@ const pipelineStageCreateSchema = scopedSchema.extend({
|
|
|
407
407
|
pipelineId: uuid(),
|
|
408
408
|
label: z.string().trim().min(1).max(200),
|
|
409
409
|
order: z.number().int().min(0).optional(),
|
|
410
|
-
color: z.string().trim().max(20).
|
|
411
|
-
icon: z.string().trim().max(100).
|
|
410
|
+
color: z.string().trim().max(20).nullish(),
|
|
411
|
+
icon: z.string().trim().max(100).nullish()
|
|
412
412
|
});
|
|
413
413
|
const pipelineStageUpdateSchema = z.object({
|
|
414
414
|
id: uuid(),
|
|
415
415
|
label: z.string().trim().min(1).max(200).optional(),
|
|
416
416
|
order: z.number().int().min(0).optional(),
|
|
417
|
-
color: z.string().trim().max(20).
|
|
418
|
-
icon: z.string().trim().max(100).
|
|
417
|
+
color: z.string().trim().max(20).nullish(),
|
|
418
|
+
icon: z.string().trim().max(100).nullish()
|
|
419
419
|
});
|
|
420
420
|
const pipelineStageDeleteSchema = z.object({
|
|
421
421
|
id: uuid()
|