@open-mercato/sync-akeneo 0.5.1-develop.2681.c559bb2bc3 → 0.5.1-develop.2683.4878a05b8e
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.
|
@@ -7,7 +7,7 @@ import { apiCall } from "@open-mercato/ui/backend/utils/apiCall";
|
|
|
7
7
|
import { useConfirmDialog } from "@open-mercato/ui/backend/confirm-dialog";
|
|
8
8
|
import { flash } from "@open-mercato/ui/backend/FlashMessages";
|
|
9
9
|
import { NextStepCallout } from "@open-mercato/ui/backend/NextStepCallout";
|
|
10
|
-
import {
|
|
10
|
+
import { Alert, AlertDescription, AlertTitle } from "@open-mercato/ui/primitives/alert";
|
|
11
11
|
import { Badge } from "@open-mercato/ui/primitives/badge";
|
|
12
12
|
import { Button } from "@open-mercato/ui/primitives/button";
|
|
13
13
|
import { Progress } from "@open-mercato/ui/primitives/progress";
|
|
@@ -1053,23 +1053,14 @@ function AkeneoConfigWidget({ context, data }) {
|
|
|
1053
1053
|
return /* @__PURE__ */ jsxs("div", { className: "space-y-6 rounded-lg border bg-card p-4", children: [
|
|
1054
1054
|
/* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
|
|
1055
1055
|
/* @__PURE__ */ jsx("h3", { className: "text-sm font-semibold", children: t("sync_akeneo.setup.heading", "Akeneo API setup") }),
|
|
1056
|
-
/* @__PURE__ */ jsx(
|
|
1057
|
-
|
|
1058
|
-
{
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
Notice,
|
|
1065
|
-
{
|
|
1066
|
-
title: t("sync_akeneo.setup.order.title", "Recommended sync order"),
|
|
1067
|
-
message: t(
|
|
1068
|
-
"sync_akeneo.setup.order.message",
|
|
1069
|
-
"Run category sync first, attribute sync second, and product sync last. Product import expects local categories and family-based schemas to exist already."
|
|
1070
|
-
)
|
|
1071
|
-
}
|
|
1072
|
-
),
|
|
1056
|
+
/* @__PURE__ */ jsx(Alert, { variant: "info", children: /* @__PURE__ */ jsx(AlertDescription, { children: t("sync_akeneo.setup.scheduleTab", "Run once and recurring schedules now live in the dedicated Sync schedules tab, shared by all data sync integrations.") }) }),
|
|
1057
|
+
/* @__PURE__ */ jsxs(Alert, { variant: "info", children: [
|
|
1058
|
+
/* @__PURE__ */ jsx(AlertTitle, { children: t("sync_akeneo.setup.order.title", "Recommended sync order") }),
|
|
1059
|
+
/* @__PURE__ */ jsx(AlertDescription, { children: t(
|
|
1060
|
+
"sync_akeneo.setup.order.message",
|
|
1061
|
+
"Run category sync first, attribute sync second, and product sync last. Product import expects local categories and family-based schemas to exist already."
|
|
1062
|
+
) })
|
|
1063
|
+
] }),
|
|
1073
1064
|
shouldShowFirstImportCallout ? /* @__PURE__ */ jsx(
|
|
1074
1065
|
NextStepCallout,
|
|
1075
1066
|
{
|
|
@@ -1173,7 +1164,7 @@ function AkeneoConfigWidget({ context, data }) {
|
|
|
1173
1164
|
"The imported product cleanup is running in the background. Progress also appears in the global progress bar."
|
|
1174
1165
|
) })
|
|
1175
1166
|
] }) : null,
|
|
1176
|
-
discovery?.message ? /* @__PURE__ */ jsx(
|
|
1167
|
+
discovery?.message ? /* @__PURE__ */ jsx(Alert, { variant: discovery.ok ? "info" : "warning", children: /* @__PURE__ */ jsx(AlertDescription, { children: discovery.message }) }) : null,
|
|
1177
1168
|
/* @__PURE__ */ jsxs("div", { className: "grid gap-6 xl:grid-cols-[1.2fr_0.8fr]", children: [
|
|
1178
1169
|
/* @__PURE__ */ jsxs("div", { className: "space-y-5 rounded-lg border p-4", children: [
|
|
1179
1170
|
/* @__PURE__ */ jsxs("div", { className: "grid gap-4 md:grid-cols-2", children: [
|
|
@@ -1343,7 +1334,7 @@ function AkeneoConfigWidget({ context, data }) {
|
|
|
1343
1334
|
/* @__PURE__ */ jsx("td", { className: "px-3 py-2", children: row.skip ? renderSkippedCustomFieldBadge() : renderCustomFieldStatusBadge(exists) })
|
|
1344
1335
|
] }, `${row.attributeCode}:${row.fieldKey}:${index}`);
|
|
1345
1336
|
}) })
|
|
1346
|
-
] }) }) : /* @__PURE__ */ jsx(
|
|
1337
|
+
] }) }) : /* @__PURE__ */ jsx(Alert, { variant: "info", children: /* @__PURE__ */ jsx(AlertDescription, { children: t("sync_akeneo.customFields.empty", "No Akeneo custom fields are shown yet. They are discovered and mapped automatically after credentials are saved or when you use Refresh discovery. Use the editor only if you want to review or override the automatic mapping.") }) }),
|
|
1347
1338
|
customFieldRows.length > 0 ? /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap gap-2 text-xs", children: [
|
|
1348
1339
|
/* @__PURE__ */ jsx("span", { className: "rounded border px-2 py-1", children: t("sync_akeneo.mapping.customFields.total", `${customFieldRows.length} mapped`) }),
|
|
1349
1340
|
skippedCustomFieldCount > 0 ? /* @__PURE__ */ jsx("span", { className: "rounded border px-2 py-1", children: t("sync_akeneo.mapping.customFields.skipped", `${skippedCustomFieldCount} skipped`) }) : null,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../../src/modules/sync_akeneo/widgets/injection/akeneo-config/widget.client.tsx"],
|
|
4
|
-
"sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport type { InjectionWidgetComponentProps } from '@open-mercato/shared/modules/widgets/injection'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { useAppEvent } from '@open-mercato/ui/backend/injection/useAppEvent'\nimport { apiCall } from '@open-mercato/ui/backend/utils/apiCall'\nimport { useConfirmDialog } from '@open-mercato/ui/backend/confirm-dialog'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { NextStepCallout } from '@open-mercato/ui/backend/NextStepCallout'\nimport { Notice } from '@open-mercato/ui/primitives/Notice'\nimport { Badge } from '@open-mercato/ui/primitives/badge'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { Progress } from '@open-mercato/ui/primitives/progress'\nimport {\n Dialog,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n} from '@open-mercato/ui/primitives/dialog'\nimport { Input } from '@open-mercato/ui/primitives/input'\nimport { Label } from '@open-mercato/ui/primitives/label'\nimport { AlertCircle, CheckCircle2, PencilLine, Plus, RefreshCw, Save, Sparkles, Trash2, Wand2, X } from 'lucide-react'\nimport { buildAkeneoFieldsetCode, buildDefaultAkeneoMapping, buildProductFieldMappings, dedupeStrings, normalizeAkeneoMapping, type AkeneoReconciliationSettings } from '../../../lib/shared'\nimport { inferAkeneoProductMapping } from '../../../lib/inference'\nimport type { AkeneoDiscoveryResponse } from '../../../data/validators'\n\ntype MappingRecordResponse = {\n items?: Array<{\n id: string\n mapping: Record<string, unknown>\n }>\n}\n\ntype CustomFieldStatusResponse = {\n ok: boolean\n productKeys: string[]\n variantKeys: string[]\n createdKeys?: string[]\n message?: string\n}\n\ntype DeleteImportedProductsResponse = {\n ok: boolean\n progressJobId: string | null\n message: string\n}\n\ntype DeleteImportedProductsJobResponse = {\n id: string\n status: 'pending' | 'running' | 'completed' | 'failed' | 'cancelled'\n progressPercent: number\n processedCount: number\n totalCount?: number | null\n resultSummary?: Record<string, unknown> | null\n errorMessage?: string | null\n}\n\ntype FirstImportSequenceResponse = {\n ok: boolean\n hasCompletedProductImport: boolean\n sequence: {\n progressJobId: string\n status: 'pending' | 'running' | 'completed' | 'failed' | 'cancelled'\n currentStep: FirstImportStepKey | null\n currentRunId: string | null\n currentRunProgressJobId: string | null\n currentRunStatus: 'pending' | 'running' | 'completed' | 'failed' | 'cancelled' | null\n progressPercent: number | null\n processedCount: number | null\n totalCount: number | null\n errorMessage: string | null\n } | null\n}\n\ntype FirstImportStepKey = 'categories' | 'attributes' | 'products'\n\ntype ProgressEventPayload = {\n jobId?: string\n jobType?: string\n status?: string\n progressPercent?: number\n processedCount?: number\n totalCount?: number | null\n meta?: Record<string, unknown> | null\n errorMessage?: string | null\n resultSummary?: Record<string, unknown> | null\n}\n\ntype FirstImportProgressState = {\n phase: 'idle' | 'running' | 'completed' | 'failed'\n progressJobId: string | null\n step: FirstImportStepKey | null\n runId: string | null\n runProgressJobId: string | null\n progressPercent: number | null\n processedCount: number | null\n totalCount: number | null\n errorMessage: string | null\n}\n\ntype CustomFieldRow = {\n attributeCode: string\n target: 'product' | 'variant'\n fieldKey: string\n kind: '' | 'text' | 'multiline' | 'integer' | 'float' | 'boolean' | 'select'\n skip: boolean\n}\n\ntype PriceMappingRow = {\n attributeCode: string\n priceKindCode: string\n akeneoChannel: string\n localChannelCode: string\n}\n\ntype MediaMappingRow = {\n attributeCode: string\n target: 'product' | 'variant'\n kind: 'image' | 'file'\n}\n\ntype FieldsetMappingRow = {\n sourceType: 'family' | 'familyVariant'\n sourceCode: string\n target: 'product' | 'variant'\n fieldsetCode: string\n fieldsetLabel: string\n description: string\n}\n\ntype AkeneoWidgetContext = {\n state?: {\n isEnabled?: boolean\n } | null\n}\n\ntype AkeneoWidgetData = {\n hasCredentials?: boolean\n}\n\ntype FormState = {\n productLocale: string\n productChannel: string\n productChannels: string[]\n importAllProductChannels: boolean\n categoryLocale: string\n includeTextAttributes: boolean\n includeNumericAttributes: boolean\n familyCodeFilter: string\n customFieldMappings: string\n priceMappings: string\n mediaMappings: string\n fieldsetMappings: string\n createMissingChannels: boolean\n syncAssociations: boolean\n reconciliation: AkeneoReconciliationSettings\n fieldMap: {\n title: string\n subtitle: string\n description: string\n sku: string\n barcode: string\n weight: string\n variantName: string\n }\n}\n\nfunction readDeleteImportedProductsSummaryMessage(summary: Record<string, unknown> | null | undefined): string | null {\n if (!summary || typeof summary !== 'object') return null\n const message = summary.message\n if (typeof message !== 'string') return null\n const trimmed = message.trim()\n return trimmed.length > 0 ? trimmed : null\n}\n\nfunction readProgressMetaString(meta: Record<string, unknown> | null | undefined, key: string): string | null {\n if (!meta || typeof meta[key] !== 'string') return null\n const value = String(meta[key]).trim()\n return value.length > 0 ? value : null\n}\n\nfunction readProgressMetaNumber(meta: Record<string, unknown> | null | undefined, key: string): number | null {\n const value = meta?.[key]\n return typeof value === 'number' && Number.isFinite(value) ? value : null\n}\n\nconst PRODUCT_FIELD_KEYS: Array<{\n key: keyof FormState['fieldMap']\n label: string\n help: string\n}> = [\n { key: 'title', label: 'Title attribute', help: 'Used for the Open Mercato product title.' },\n { key: 'subtitle', label: 'Subtitle attribute', help: 'Optional secondary title field.' },\n { key: 'description', label: 'Description attribute', help: 'Used for the product description.' },\n { key: 'sku', label: 'SKU attribute', help: 'Used for both simple-product and variant SKU matching.' },\n { key: 'barcode', label: 'Barcode attribute', help: 'Optional barcode/EAN source.' },\n { key: 'weight', label: 'Weight attribute', help: 'Metric attribute used for product and default-variant weight.' },\n { key: 'variantName', label: 'Variant label attribute', help: 'Fallback label for generated variant names.' },\n]\n\nfunction buildInitialState(): FormState {\n const products = buildDefaultAkeneoMapping('products')\n const categories = buildDefaultAkeneoMapping('categories')\n const attributes = buildDefaultAkeneoMapping('attributes')\n const productSettings = products.settings?.products\n return {\n productLocale: productSettings?.locale ?? 'en_US',\n productChannel: productSettings?.channel ?? '',\n productChannels: productSettings?.channels ?? [],\n importAllProductChannels: productSettings?.importAllChannels ?? true,\n categoryLocale: categories.settings?.categories?.locale ?? 'en_US',\n includeTextAttributes: attributes.settings?.attributes?.includeTextAttributes ?? true,\n includeNumericAttributes: attributes.settings?.attributes?.includeNumericAttributes ?? true,\n familyCodeFilter: '',\n customFieldMappings: '',\n priceMappings: serializePriceMappingRows(\n (productSettings?.priceMappings ?? []).map((entry) => ({\n attributeCode: entry.attributeCode,\n priceKindCode: entry.priceKindCode,\n akeneoChannel: entry.akeneoChannel ?? '',\n localChannelCode: entry.localChannelCode,\n })),\n ),\n mediaMappings: serializeMediaMappingRows(\n (productSettings?.mediaMappings ?? []).map((entry) => ({\n attributeCode: entry.attributeCode,\n target: entry.target,\n kind: entry.kind,\n })),\n ),\n fieldsetMappings: serializeFieldsetMappingRows(\n (productSettings?.fieldsetMappings ?? []).map((entry) => ({\n sourceType: entry.sourceType,\n sourceCode: entry.sourceCode,\n target: entry.target,\n fieldsetCode: entry.fieldsetCode,\n fieldsetLabel: entry.fieldsetLabel,\n description: entry.description ?? '',\n })),\n ),\n createMissingChannels: productSettings?.createMissingChannels ?? true,\n syncAssociations: productSettings?.syncAssociations ?? true,\n reconciliation: productSettings?.reconciliation ?? {\n deactivateMissingCategories: true,\n deactivateMissingProducts: true,\n deactivateMissingAttributes: true,\n deleteMissingOffers: true,\n deleteMissingPrices: true,\n deleteMissingMedia: true,\n deleteMissingAttachments: true,\n },\n fieldMap: {\n title: productSettings?.fieldMap.title ?? 'name',\n subtitle: productSettings?.fieldMap.subtitle ?? 'subtitle',\n description: productSettings?.fieldMap.description ?? 'description',\n sku: productSettings?.fieldMap.sku ?? 'sku',\n barcode: productSettings?.fieldMap.barcode ?? 'ean',\n weight: productSettings?.fieldMap.weight ?? 'weight',\n variantName: productSettings?.fieldMap.variantName ?? 'name',\n },\n }\n}\n\nfunction mergeMappingsIntoState(\n state: FormState,\n productsMapping: Record<string, unknown> | undefined,\n categoriesMapping: Record<string, unknown> | undefined,\n attributesMapping: Record<string, unknown> | undefined,\n): FormState {\n const normalizedProducts = normalizeAkeneoMapping('products', productsMapping ?? null)\n const normalizedCategories = normalizeAkeneoMapping('categories', categoriesMapping ?? null)\n const normalizedAttributes = normalizeAkeneoMapping('attributes', attributesMapping ?? null)\n return {\n ...state,\n productLocale: normalizedProducts.settings?.products?.locale ?? state.productLocale,\n productChannel: normalizedProducts.settings?.products?.channel ?? '',\n productChannels: normalizedProducts.settings?.products?.channels ?? state.productChannels,\n importAllProductChannels: normalizedProducts.settings?.products?.importAllChannels ?? state.importAllProductChannels,\n categoryLocale: normalizedCategories.settings?.categories?.locale ?? state.categoryLocale,\n includeTextAttributes: normalizedAttributes.settings?.attributes?.includeTextAttributes ?? state.includeTextAttributes,\n includeNumericAttributes: normalizedAttributes.settings?.attributes?.includeNumericAttributes ?? state.includeNumericAttributes,\n familyCodeFilter: (normalizedAttributes.settings?.attributes?.familyCodeFilter ?? []).join(', '),\n customFieldMappings: (normalizedProducts.settings?.products?.customFieldMappings ?? [])\n .map((entry) => `${entry.attributeCode},${entry.target},${entry.fieldKey},${entry.kind ?? ''},${entry.skip === true ? 'skip' : ''}`)\n .join('\\n'),\n priceMappings: (normalizedProducts.settings?.products?.priceMappings ?? [])\n .map((entry) => `${entry.attributeCode},${entry.priceKindCode},${entry.akeneoChannel ?? ''},${entry.localChannelCode}`)\n .join('\\n'),\n mediaMappings: (normalizedProducts.settings?.products?.mediaMappings ?? [])\n .map((entry) => `${entry.attributeCode},${entry.target},${entry.kind}`)\n .join('\\n'),\n fieldsetMappings: (normalizedProducts.settings?.products?.fieldsetMappings ?? [])\n .map((entry) => `${entry.sourceType},${entry.sourceCode},${entry.target},${entry.fieldsetCode},${entry.fieldsetLabel}${entry.description ? `,${entry.description}` : ''}`)\n .join('\\n'),\n createMissingChannels: normalizedProducts.settings?.products?.createMissingChannels ?? state.createMissingChannels,\n syncAssociations: normalizedProducts.settings?.products?.syncAssociations ?? state.syncAssociations,\n reconciliation: normalizedProducts.settings?.products?.reconciliation ?? state.reconciliation,\n fieldMap: {\n title: normalizedProducts.settings?.products?.fieldMap.title ?? state.fieldMap.title,\n subtitle: normalizedProducts.settings?.products?.fieldMap.subtitle ?? state.fieldMap.subtitle,\n description: normalizedProducts.settings?.products?.fieldMap.description ?? state.fieldMap.description,\n sku: normalizedProducts.settings?.products?.fieldMap.sku ?? state.fieldMap.sku,\n barcode: normalizedProducts.settings?.products?.fieldMap.barcode ?? state.fieldMap.barcode,\n weight: normalizedProducts.settings?.products?.fieldMap.weight ?? state.fieldMap.weight,\n variantName: normalizedProducts.settings?.products?.fieldMap.variantName ?? state.fieldMap.variantName,\n },\n }\n}\n\nfunction parseRows(value: string): string[][] {\n return value\n .split('\\n')\n .map((row) => row.trim())\n .filter((row) => row.length > 0)\n .map((row) => row.split(',').map((cell) => cell.trim()))\n}\n\nfunction parseCustomFieldRows(value: string): CustomFieldRow[] {\n return parseRows(value)\n .map(([attributeCode, target, fieldKey, kind, skipFlag]) => {\n const normalizedTarget: CustomFieldRow['target'] = target === 'variant' ? 'variant' : 'product'\n const normalizedKind: CustomFieldRow['kind'] = kind === 'text'\n || kind === 'multiline'\n || kind === 'integer'\n || kind === 'float'\n || kind === 'boolean'\n || kind === 'select'\n ? kind\n : ''\n return {\n attributeCode,\n target: normalizedTarget,\n fieldKey,\n kind: normalizedKind,\n skip: skipFlag === 'skip' || skipFlag === 'true',\n }\n })\n .filter((row) => row.attributeCode.length > 0 || row.fieldKey.length > 0)\n}\n\nfunction serializeCustomFieldRows(rows: CustomFieldRow[]): string {\n return rows\n .filter((row) => row.attributeCode.trim().length > 0 && (row.fieldKey.trim().length > 0 || row.skip))\n .map((row) => [\n row.attributeCode.trim(),\n row.target,\n row.fieldKey.trim() || normalizeFieldKey(row.attributeCode),\n row.kind,\n row.skip ? 'skip' : '',\n ].filter((cell, index) => index < 4 || cell.length > 0).join(','))\n .join('\\n')\n}\n\nfunction mergeCustomFieldRows(existingRows: CustomFieldRow[], discoveredRows: CustomFieldRow[]): CustomFieldRow[] {\n const merged = [...existingRows]\n const existingAttributeCodes = new Set(\n existingRows.map((row) => row.attributeCode.trim()).filter((value) => value.length > 0),\n )\n for (const row of discoveredRows) {\n const attributeCode = row.attributeCode.trim()\n if (!attributeCode || existingAttributeCodes.has(attributeCode)) continue\n merged.push(row)\n existingAttributeCodes.add(attributeCode)\n }\n return merged\n}\n\nfunction parsePriceMappingRows(value: string): PriceMappingRow[] {\n return parseRows(value)\n .map(([attributeCode, priceKindCode, akeneoChannel, localChannelCode]) => ({\n attributeCode,\n priceKindCode,\n akeneoChannel: akeneoChannel ?? '',\n localChannelCode,\n }))\n}\n\nfunction serializePriceMappingRows(rows: PriceMappingRow[]): string {\n return rows\n .map((row) => [\n row.attributeCode.trim(),\n row.priceKindCode.trim(),\n row.akeneoChannel.trim(),\n row.localChannelCode.trim(),\n ].join(','))\n .join('\\n')\n}\n\nfunction parseMediaMappingRows(value: string): MediaMappingRow[] {\n return parseRows(value)\n .map(([attributeCode, target, kind]) => ({\n attributeCode,\n target: target === 'variant' ? 'variant' : 'product',\n kind: kind === 'file' ? 'file' : 'image',\n }))\n}\n\nfunction serializeMediaMappingRows(rows: MediaMappingRow[]): string {\n return rows\n .map((row) => `${row.attributeCode.trim()},${row.target},${row.kind}`)\n .join('\\n')\n}\n\nfunction parseFieldsetMappingRows(value: string): FieldsetMappingRow[] {\n return parseRows(value)\n .map(([sourceType, sourceCode, target, fieldsetCode, fieldsetLabel, ...descriptionParts]): FieldsetMappingRow => ({\n sourceType: sourceType === 'familyVariant' ? 'familyVariant' : 'family',\n sourceCode: sourceCode ?? '',\n target: target === 'variant' ? 'variant' : 'product',\n fieldsetCode: fieldsetCode ?? '',\n fieldsetLabel: fieldsetLabel ?? '',\n description: descriptionParts.join(','),\n }))\n .filter((row) => row.sourceCode.trim().length > 0 || row.fieldsetCode.trim().length > 0 || row.fieldsetLabel.trim().length > 0)\n}\n\nfunction serializeFieldsetMappingRows(rows: FieldsetMappingRow[]): string {\n return rows\n .filter((row) => row.sourceCode.trim().length > 0 && row.fieldsetCode.trim().length > 0 && row.fieldsetLabel.trim().length > 0)\n .map((row) => [\n row.sourceType,\n row.sourceCode.trim(),\n row.target,\n row.fieldsetCode.trim(),\n row.fieldsetLabel.trim(),\n row.description.trim(),\n ].filter((cell, index) => index < 5 || cell.length > 0).join(','))\n .join('\\n')\n}\n\nfunction normalizeFieldKey(value: string): string {\n return value\n .trim()\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '_')\n .replace(/^_+|_+$/g, '')\n .slice(0, 100)\n}\n\nfunction inferCustomFieldKind(attributeType: string): CustomFieldRow['kind'] {\n if (attributeType === 'pim_catalog_boolean') return 'boolean'\n if (attributeType === 'pim_catalog_number') return 'float'\n if (attributeType === 'pim_catalog_metric') return 'float'\n if (attributeType === 'pim_catalog_textarea') return 'multiline'\n if (\n attributeType === 'pim_catalog_simpleselect'\n || attributeType === 'pim_catalog_multiselect'\n || attributeType === 'akeneo_reference_entity'\n || attributeType === 'akeneo_reference_entity_collection'\n ) {\n return 'select'\n }\n return 'text'\n}\n\nfunction inferPriceKindCode(attributeCode: string): string {\n const normalized = attributeCode.trim().toLowerCase()\n return normalized.includes('sale')\n || normalized.includes('promo')\n || normalized.includes('special')\n || normalized.includes('discount')\n ? 'sale'\n : 'regular'\n}\n\nfunction buildSelectValues(values: Array<string | null | undefined>, currentValue?: string | null): string[] {\n return dedupeStrings([\n ...values,\n currentValue ?? null,\n ])\n}\n\nfunction buildDiscoveredFieldsetMappings(discovery: AkeneoDiscoveryResponse): FieldsetMappingRow[] {\n const familyRows = (discovery.families ?? []).flatMap((family) => {\n const productFieldsetCode = buildAkeneoFieldsetCode('product', family.code)\n return productFieldsetCode ? [{\n sourceType: 'family' as const,\n sourceCode: family.code,\n target: 'product' as const,\n fieldsetCode: productFieldsetCode,\n fieldsetLabel: family.label || family.code,\n description: `Akeneo family ${family.code}`,\n }] : []\n })\n\n const familyVariantRows = (discovery.familyVariants ?? []).flatMap((familyVariant) => {\n const variantFieldsetCode = buildAkeneoFieldsetCode('variant', familyVariant.code)\n return variantFieldsetCode ? [{\n sourceType: 'familyVariant' as const,\n sourceCode: familyVariant.code,\n target: 'variant' as const,\n fieldsetCode: variantFieldsetCode,\n fieldsetLabel: familyVariant.label || familyVariant.code,\n description: `Akeneo family variant ${familyVariant.code} from family ${familyVariant.familyCode}`,\n }] : []\n })\n\n return [...familyRows, ...familyVariantRows]\n}\n\nfunction applyDiscoveryDefaults(\n state: FormState,\n discovery: AkeneoDiscoveryResponse | null,\n): FormState {\n if (!discovery?.ok) return state\n\n const discoveredFamilyVariant = (discovery.familyVariants ?? []).length > 0\n ? {\n code: '__discovery__',\n variant_attribute_sets: (discovery.familyVariants ?? []).map((familyVariant, index) => ({\n level: index + 1,\n axes: familyVariant.axes,\n attributes: familyVariant.attributes,\n })),\n }\n : null\n\n const inferred = inferAkeneoProductMapping({\n attributes: (discovery.attributes ?? []).map((attribute) => ({\n code: attribute.code,\n type: attribute.type,\n labels: attribute.label ? { inferred: attribute.label } : undefined,\n localizable: attribute.localizable,\n scopable: attribute.scopable,\n group: attribute.group,\n metric_family: attribute.metricFamily,\n })),\n family: null,\n familyVariant: discoveredFamilyVariant,\n fieldMap: state.fieldMap,\n explicitCustomFieldMappings: parseCustomFieldRows(state.customFieldMappings).map((row) => ({\n attributeCode: row.attributeCode.trim(),\n target: row.target,\n fieldKey: row.fieldKey.trim() || normalizeFieldKey(row.attributeCode),\n kind: row.kind || null,\n skip: row.skip,\n })),\n explicitMediaMappings: parseMediaMappingRows(state.mediaMappings).map((row) => ({\n attributeCode: row.attributeCode.trim(),\n target: row.target,\n kind: row.kind,\n })),\n })\n\n const hasCustomFields = parseCustomFieldRows(state.customFieldMappings).length > 0\n const hasMediaMappings = parseMediaMappingRows(state.mediaMappings).length > 0\n const hasPriceMappings = parsePriceMappingRows(state.priceMappings).some((row) => row.attributeCode.trim().length > 0)\n const hasFieldsetMappings = parseFieldsetMappingRows(state.fieldsetMappings).length > 0\n const currentCustomFieldRows = parseCustomFieldRows(state.customFieldMappings)\n const discoveredCustomFieldRows = inferred.autoCustomFieldMappings.map((mapping) => ({\n attributeCode: mapping.attributeCode,\n target: mapping.target,\n fieldKey: mapping.fieldKey,\n kind: mapping.kind ?? '',\n skip: false,\n }) satisfies CustomFieldRow)\n const preferredLocalChannel = discovery.localChannels.find((channel) => ['web', 'online', 'ecommerce', 'default'].includes(channel.code.trim().toLowerCase()))\n ?? discovery.localChannels[0]\n ?? null\n const preferredAkeneoChannel = discovery.channels[0]?.code ?? ''\n const preferredLocale = discovery.locales.find((locale) => locale.enabled)?.code\n ?? discovery.locales[0]?.code\n ?? state.productLocale\n\n return {\n ...state,\n productLocale: state.productLocale,\n categoryLocale: state.categoryLocale,\n productChannel: state.productChannel || preferredAkeneoChannel,\n productChannels: state.productChannels.length > 0 ? state.productChannels : (preferredAkeneoChannel ? [preferredAkeneoChannel] : []),\n importAllProductChannels: state.importAllProductChannels,\n fieldMap: inferred.fieldMap,\n customFieldMappings: serializeCustomFieldRows(\n mergeCustomFieldRows(currentCustomFieldRows, discoveredCustomFieldRows),\n ),\n mediaMappings: hasMediaMappings\n ? state.mediaMappings\n : serializeMediaMappingRows(\n inferred.autoMediaMappings.map((mapping) => ({\n attributeCode: mapping.attributeCode,\n target: mapping.target,\n kind: mapping.kind,\n })),\n ),\n fieldsetMappings: hasFieldsetMappings\n ? state.fieldsetMappings\n : serializeFieldsetMappingRows(buildDiscoveredFieldsetMappings(discovery)),\n priceMappings: hasPriceMappings || !preferredLocalChannel\n ? state.priceMappings\n : serializePriceMappingRows(\n inferred.autoPriceAttributeCodes.map((attributeCode) => ({\n attributeCode,\n priceKindCode: inferPriceKindCode(attributeCode),\n akeneoChannel: preferredAkeneoChannel,\n localChannelCode: preferredLocalChannel.code,\n })),\n ),\n }\n}\n\nconst FIRST_IMPORT_STEPS: Array<{\n entityType: FirstImportStepKey\n fullSync: boolean\n}> = [\n { entityType: 'categories', fullSync: true },\n { entityType: 'attributes', fullSync: true },\n { entityType: 'products', fullSync: true },\n]\n\nexport default function AkeneoConfigWidget({ context, data }: InjectionWidgetComponentProps<AkeneoWidgetContext, AkeneoWidgetData>) {\n const t = useT()\n const { confirm, ConfirmDialogElement } = useConfirmDialog()\n const [state, setState] = React.useState<FormState>(() => buildInitialState())\n const [discovery, setDiscovery] = React.useState<AkeneoDiscoveryResponse | null>(null)\n const [customFieldStatus, setCustomFieldStatus] = React.useState<CustomFieldStatusResponse | null>(null)\n const [customFieldDialogOpen, setCustomFieldDialogOpen] = React.useState(false)\n const [customFieldEditorRows, setCustomFieldEditorRows] = React.useState<CustomFieldRow[]>([])\n const [isCreatingCustomFields, setIsCreatingCustomFields] = React.useState(false)\n const [isLoading, setIsLoading] = React.useState(true)\n const [isSaving, setIsSaving] = React.useState(false)\n const [isStartingDeleteImportedProducts, setIsStartingDeleteImportedProducts] = React.useState(false)\n const [deleteImportedProductsJobId, setDeleteImportedProductsJobId] = React.useState<string | null>(null)\n const [deleteImportedProductsJob, setDeleteImportedProductsJob] = React.useState<DeleteImportedProductsJobResponse | null>(null)\n const [hasCompletedProductImport, setHasCompletedProductImport] = React.useState(false)\n const [firstImportProgress, setFirstImportProgress] = React.useState<FirstImportProgressState>({\n phase: 'idle',\n progressJobId: null,\n step: null,\n runId: null,\n runProgressJobId: null,\n progressPercent: null,\n processedCount: null,\n totalCount: null,\n errorMessage: null,\n })\n const mountedRef = React.useRef(true)\n const firstImportTerminalNoticeRef = React.useRef<string | null>(null)\n\n React.useEffect(() => {\n return () => {\n mountedRef.current = false\n }\n }, [])\n\n const syncFirstImportStatus = React.useCallback((response: FirstImportSequenceResponse | null | undefined) => {\n setHasCompletedProductImport(response?.hasCompletedProductImport === true)\n\n const sequence = response?.sequence\n if (!sequence) {\n setFirstImportProgress({\n phase: 'idle',\n progressJobId: null,\n step: null,\n runId: null,\n runProgressJobId: null,\n progressPercent: null,\n processedCount: null,\n totalCount: null,\n errorMessage: null,\n })\n return\n }\n\n setFirstImportProgress({\n phase: sequence.status === 'failed'\n ? 'failed'\n : sequence.status === 'pending' || sequence.status === 'running'\n ? 'running'\n : sequence.status === 'completed'\n ? 'completed'\n : 'idle',\n progressJobId: sequence.progressJobId,\n step: sequence.currentStep,\n runId: sequence.currentRunId,\n runProgressJobId: sequence.currentRunProgressJobId,\n progressPercent: sequence.progressPercent,\n processedCount: sequence.processedCount,\n totalCount: sequence.totalCount,\n errorMessage: sequence.errorMessage,\n })\n }, [])\n\n const loadFirstImportStatus = React.useCallback(async () => {\n const result = await apiCall<FirstImportSequenceResponse>('/api/sync_akeneo/first-import')\n if (!result.ok) {\n throw new Error(t('sync_akeneo.firstImport.errors.progress', 'Failed to load sync run progress.'))\n }\n syncFirstImportStatus(result.result ?? null)\n }, [syncFirstImportStatus, t])\n\n const buildMappingPayloads = React.useCallback((currentState: FormState) => {\n const customFieldMappings = parseRows(currentState.customFieldMappings)\n .map(([attributeCode, target, fieldKey, kind, skipFlag]) => {\n const normalizedTarget = target === 'variant' ? 'variant' : target === 'product' ? 'product' : null\n const normalizedKind = kind === 'text'\n || kind === 'multiline'\n || kind === 'integer'\n || kind === 'float'\n || kind === 'boolean'\n || kind === 'select'\n ? kind\n : null\n const normalizedFieldKey = fieldKey || normalizeFieldKey(attributeCode)\n if (!attributeCode || !normalizedFieldKey || !normalizedTarget) return null\n return {\n attributeCode,\n target: normalizedTarget,\n fieldKey: normalizedFieldKey,\n kind: normalizedKind,\n skip: skipFlag === 'skip' || skipFlag === 'true',\n } as const\n })\n .filter((entry): entry is NonNullable<typeof entry> => Boolean(entry))\n const priceMappings = parseRows(currentState.priceMappings)\n .map(([attributeCode, priceKindCode, akeneoChannel, localChannelCode]) => {\n if (!attributeCode || !priceKindCode || !localChannelCode) return null\n return {\n attributeCode,\n priceKindCode,\n akeneoChannel: akeneoChannel || null,\n localChannelCode,\n } as const\n })\n .filter((entry): entry is NonNullable<typeof entry> => Boolean(entry))\n const mediaMappings = parseRows(currentState.mediaMappings)\n .map(([attributeCode, target, kind]) => {\n const normalizedTarget = target === 'variant' ? 'variant' : target === 'product' ? 'product' : null\n const normalizedKind = kind === 'image' ? 'image' : kind === 'file' ? 'file' : null\n if (!attributeCode || !normalizedTarget || !normalizedKind) return null\n return {\n attributeCode,\n target: normalizedTarget,\n kind: normalizedKind,\n } as const\n })\n .filter((entry): entry is NonNullable<typeof entry> => Boolean(entry))\n const fieldsetMappings = parseFieldsetMappingRows(currentState.fieldsetMappings)\n .map((row) => {\n if (!row.sourceCode || !row.fieldsetCode || !row.fieldsetLabel) return null\n return {\n sourceType: row.sourceType,\n sourceCode: row.sourceCode.trim(),\n target: row.target,\n fieldsetCode: row.fieldsetCode.trim(),\n fieldsetLabel: row.fieldsetLabel.trim(),\n description: row.description.trim() || null,\n } as const\n })\n .filter((entry): entry is NonNullable<typeof entry> => Boolean(entry))\n\n const productsMapping = {\n ...buildDefaultAkeneoMapping('products'),\n settings: {\n products: {\n locale: currentState.productLocale,\n channel: currentState.productChannel || null,\n channels: currentState.importAllProductChannels ? [] : currentState.productChannels,\n importAllChannels: currentState.importAllProductChannels,\n fieldMap: { ...currentState.fieldMap },\n customFieldMappings,\n priceMappings,\n mediaMappings,\n fieldsetMappings,\n createMissingChannels: currentState.createMissingChannels,\n syncAssociations: currentState.syncAssociations,\n reconciliation: { ...currentState.reconciliation },\n },\n },\n }\n productsMapping.fields = buildProductFieldMappings(productsMapping.settings.products)\n\n const categoriesMapping = {\n ...buildDefaultAkeneoMapping('categories'),\n settings: {\n categories: {\n locale: currentState.categoryLocale,\n },\n },\n }\n\n const attributesMapping = {\n ...buildDefaultAkeneoMapping('attributes'),\n settings: {\n attributes: {\n includeTextAttributes: currentState.includeTextAttributes,\n includeNumericAttributes: currentState.includeNumericAttributes,\n familyCodeFilter: currentState.familyCodeFilter\n .split(',')\n .map((value) => value.trim())\n .filter((value) => value.length > 0),\n },\n },\n }\n\n return { productsMapping, categoriesMapping, attributesMapping }\n }, [])\n\n const persistMappings = React.useCallback(async (\n currentState: FormState,\n options?: { successMessage?: string | null },\n ) => {\n const { productsMapping, categoriesMapping, attributesMapping } = buildMappingPayloads(currentState)\n const saves = await Promise.all([\n apiCall('/api/data_sync/mappings', {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({\n integrationId: 'sync_akeneo',\n entityType: 'products',\n mapping: productsMapping,\n }),\n }),\n apiCall('/api/data_sync/mappings', {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({\n integrationId: 'sync_akeneo',\n entityType: 'categories',\n mapping: categoriesMapping,\n }),\n }),\n apiCall('/api/data_sync/mappings', {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({\n integrationId: 'sync_akeneo',\n entityType: 'attributes',\n mapping: attributesMapping,\n }),\n }),\n ])\n\n if (saves.some((result) => !result.ok)) {\n throw new Error('Failed to save one or more Akeneo mapping records')\n }\n\n if (options?.successMessage) {\n flash(options.successMessage, 'success')\n }\n }, [buildMappingPayloads])\n\n const runFirstFullImport = React.useCallback(async () => {\n firstImportTerminalNoticeRef.current = null\n setFirstImportProgress({\n phase: 'running',\n progressJobId: null,\n step: null,\n runId: null,\n runProgressJobId: null,\n progressPercent: null,\n processedCount: null,\n totalCount: null,\n errorMessage: null,\n })\n\n try {\n await persistMappings(state)\n const result = await apiCall<{ ok?: boolean; progressJobId?: string; error?: string }>('/api/sync_akeneo/first-import', {\n method: 'POST',\n })\n\n if (!result.ok) {\n if (result.status === 409) {\n await loadFirstImportStatus()\n return\n }\n throw new Error(\n (result.result as { error?: string } | null)?.error\n ?? t('sync_akeneo.firstImport.errors.start', 'Failed to start the sync run.'),\n )\n }\n\n setFirstImportProgress((current) => ({\n ...current,\n progressJobId: result.result?.progressJobId ?? current.progressJobId,\n }))\n } catch (error) {\n if (!mountedRef.current) return\n const message = error instanceof Error\n ? error.message\n : t('sync_akeneo.firstImport.errors.generic', 'The first full Akeneo import could not be completed.')\n setFirstImportProgress((current) => ({\n ...current,\n phase: 'failed',\n errorMessage: message,\n }))\n flash(message, 'error')\n }\n }, [loadFirstImportStatus, persistMappings, state, t])\n\n const load = React.useCallback(async (refresh = false) => {\n setIsLoading(true)\n try {\n const [discoveryCall, productsCall, categoriesCall, attributesCall, customFieldsCall, firstImportStatusCall] = await Promise.all([\n apiCall<AkeneoDiscoveryResponse>(`/api/sync_akeneo/discovery${refresh ? '?refresh=true' : ''}`),\n apiCall<MappingRecordResponse>('/api/data_sync/mappings?integrationId=sync_akeneo&entityType=products&page=1&pageSize=1'),\n apiCall<MappingRecordResponse>('/api/data_sync/mappings?integrationId=sync_akeneo&entityType=categories&page=1&pageSize=1'),\n apiCall<MappingRecordResponse>('/api/data_sync/mappings?integrationId=sync_akeneo&entityType=attributes&page=1&pageSize=1'),\n apiCall<CustomFieldStatusResponse>('/api/sync_akeneo/custom-fields'),\n apiCall<FirstImportSequenceResponse>('/api/sync_akeneo/first-import').catch(() => null),\n ])\n\n let nextState = mergeMappingsIntoState(\n buildInitialState(),\n productsCall.result?.items?.[0]?.mapping,\n categoriesCall.result?.items?.[0]?.mapping,\n attributesCall.result?.items?.[0]?.mapping,\n )\n nextState = applyDiscoveryDefaults(nextState, discoveryCall.result ?? null)\n\n const hasSavedMappings = Boolean(productsCall.result?.items?.[0] || categoriesCall.result?.items?.[0] || attributesCall.result?.items?.[0])\n if (!hasSavedMappings && discoveryCall.result?.ok) {\n try {\n await persistMappings(nextState)\n } catch (error) {\n const message = error instanceof Error ? error.message : 'Failed to save discovered Akeneo mappings'\n flash(message, 'error')\n }\n }\n\n setState(nextState)\n setDiscovery(discoveryCall.result ?? null)\n setCustomFieldStatus(customFieldsCall.result ?? null)\n syncFirstImportStatus(firstImportStatusCall?.result ?? null)\n } catch (error) {\n const message = error instanceof Error ? error.message : 'Failed to load Akeneo configuration'\n flash(message, 'error')\n } finally {\n setIsLoading(false)\n }\n }, [persistMappings, syncFirstImportStatus])\n\n const applyFirstImportProgressEvent = React.useCallback((payload: ProgressEventPayload) => {\n const meta = payload.meta && typeof payload.meta === 'object' ? payload.meta : null\n const workflow = readProgressMetaString(meta, 'workflow')\n const integrationId = readProgressMetaString(meta, 'integrationId')\n const isFirstImportEvent = payload.jobType === 'sync_akeneo.first_import'\n || (workflow === 'first_import' && integrationId === 'sync_akeneo')\n\n if (!isFirstImportEvent || !payload.jobId) return\n\n const currentStep = readProgressMetaString(meta, 'currentStep')\n const nextPhase = payload.status === 'failed'\n ? 'failed'\n : payload.status === 'pending' || payload.status === 'running'\n ? 'running'\n : payload.status === 'completed'\n ? 'completed'\n : 'idle'\n\n setFirstImportProgress({\n phase: nextPhase,\n progressJobId: payload.jobId,\n step: currentStep === 'categories' || currentStep === 'attributes' || currentStep === 'products'\n ? currentStep\n : null,\n runId: readProgressMetaString(meta, 'currentRunId'),\n runProgressJobId: readProgressMetaString(meta, 'currentRunProgressJobId'),\n progressPercent: readProgressMetaNumber(meta, 'currentRunProgressPercent'),\n processedCount: readProgressMetaNumber(meta, 'currentRunProcessedCount'),\n totalCount: readProgressMetaNumber(meta, 'currentRunTotalCount'),\n errorMessage: typeof payload.errorMessage === 'string' ? payload.errorMessage : null,\n })\n\n if (nextPhase === 'running') {\n firstImportTerminalNoticeRef.current = null\n return\n }\n\n const terminalNoticeKey = `${payload.jobId}:${payload.status ?? 'unknown'}`\n if (firstImportTerminalNoticeRef.current === terminalNoticeKey) return\n firstImportTerminalNoticeRef.current = terminalNoticeKey\n\n if (nextPhase === 'completed') {\n setHasCompletedProductImport(true)\n flash(t('sync_akeneo.firstImport.completed', 'The first full Akeneo import finished successfully.'), 'success')\n void load(false)\n return\n }\n\n if (nextPhase === 'failed') {\n flash(\n typeof payload.errorMessage === 'string' && payload.errorMessage.trim().length > 0\n ? payload.errorMessage\n : t('sync_akeneo.firstImport.errors.failed', 'The sync run failed.'),\n 'error',\n )\n void loadFirstImportStatus().catch(() => undefined)\n return\n }\n\n if (payload.status === 'cancelled') {\n flash(t('sync_akeneo.firstImport.errors.cancelled', 'The first full Akeneo import was cancelled.'), 'error')\n void loadFirstImportStatus().catch(() => undefined)\n }\n }, [load, loadFirstImportStatus, t])\n\n const applyFirstImportChildRunProgressEvent = React.useCallback((payload: ProgressEventPayload) => {\n const jobId = typeof payload.jobId === 'string' ? payload.jobId : null\n if (!jobId) return\n\n setFirstImportProgress((current) => {\n if (!current.runProgressJobId || current.runProgressJobId !== jobId) {\n return current\n }\n\n return {\n ...current,\n phase: payload.status === 'failed' || payload.status === 'cancelled'\n ? 'failed'\n : current.phase === 'idle'\n ? 'running'\n : current.phase,\n progressPercent: typeof payload.progressPercent === 'number'\n ? payload.progressPercent\n : current.progressPercent,\n processedCount: typeof payload.processedCount === 'number'\n ? payload.processedCount\n : current.processedCount,\n totalCount: typeof payload.totalCount === 'number'\n ? payload.totalCount\n : current.totalCount,\n errorMessage: typeof payload.errorMessage === 'string'\n ? payload.errorMessage\n : current.errorMessage,\n }\n })\n }, [])\n\n const applyDeleteImportedProductsEvent = React.useCallback((payload: ProgressEventPayload) => {\n if (!deleteImportedProductsJobId || payload.jobId !== deleteImportedProductsJobId) return\n\n const nextJob: DeleteImportedProductsJobResponse = {\n id: payload.jobId,\n status: payload.status === 'pending'\n || payload.status === 'running'\n || payload.status === 'completed'\n || payload.status === 'failed'\n || payload.status === 'cancelled'\n ? payload.status\n : 'running',\n progressPercent: typeof payload.progressPercent === 'number' ? payload.progressPercent : 0,\n processedCount: typeof payload.processedCount === 'number' ? payload.processedCount : 0,\n totalCount: typeof payload.totalCount === 'number' ? payload.totalCount : null,\n resultSummary: payload.resultSummary ?? null,\n errorMessage: typeof payload.errorMessage === 'string' ? payload.errorMessage : null,\n }\n\n setDeleteImportedProductsJob(nextJob)\n\n if (nextJob.status === 'completed') {\n setDeleteImportedProductsJobId(null)\n setDeleteImportedProductsJob(null)\n flash(\n readDeleteImportedProductsSummaryMessage(nextJob.resultSummary)\n ?? t('sync_akeneo.deleteImportedProducts.completed', 'Imported Akeneo product deletion completed.'),\n 'success',\n )\n void load(false)\n return\n }\n\n if (nextJob.status === 'failed') {\n setDeleteImportedProductsJobId(null)\n setDeleteImportedProductsJob(null)\n flash(\n nextJob.errorMessage\n ?? t('sync_akeneo.deleteImportedProducts.failed', 'Imported Akeneo product deletion failed.'),\n 'error',\n )\n return\n }\n\n if (nextJob.status === 'cancelled') {\n setDeleteImportedProductsJobId(null)\n setDeleteImportedProductsJob(null)\n flash(\n t('sync_akeneo.deleteImportedProducts.cancelled', 'Imported Akeneo product deletion was cancelled.'),\n 'warning',\n )\n }\n }, [deleteImportedProductsJobId, load, t])\n\n React.useEffect(() => {\n void load(false)\n }, [load])\n\n useAppEvent('progress.job.created', (event) => {\n const payload = event.payload as ProgressEventPayload\n applyFirstImportProgressEvent(payload)\n applyFirstImportChildRunProgressEvent(payload)\n applyDeleteImportedProductsEvent(payload)\n }, [applyDeleteImportedProductsEvent, applyFirstImportChildRunProgressEvent, applyFirstImportProgressEvent])\n\n useAppEvent('progress.job.started', (event) => {\n const payload = event.payload as ProgressEventPayload\n applyFirstImportProgressEvent(payload)\n applyFirstImportChildRunProgressEvent(payload)\n applyDeleteImportedProductsEvent(payload)\n }, [applyDeleteImportedProductsEvent, applyFirstImportChildRunProgressEvent, applyFirstImportProgressEvent])\n\n useAppEvent('progress.job.updated', (event) => {\n const payload = event.payload as ProgressEventPayload\n applyFirstImportProgressEvent(payload)\n applyFirstImportChildRunProgressEvent(payload)\n applyDeleteImportedProductsEvent(payload)\n }, [applyDeleteImportedProductsEvent, applyFirstImportChildRunProgressEvent, applyFirstImportProgressEvent])\n\n useAppEvent('progress.job.completed', (event) => {\n const payload = event.payload as ProgressEventPayload\n applyFirstImportProgressEvent(payload)\n applyFirstImportChildRunProgressEvent(payload)\n applyDeleteImportedProductsEvent(payload)\n }, [applyDeleteImportedProductsEvent, applyFirstImportChildRunProgressEvent, applyFirstImportProgressEvent])\n\n useAppEvent('progress.job.failed', (event) => {\n const payload = event.payload as ProgressEventPayload\n applyFirstImportProgressEvent(payload)\n applyFirstImportChildRunProgressEvent(payload)\n applyDeleteImportedProductsEvent(payload)\n }, [applyDeleteImportedProductsEvent, applyFirstImportChildRunProgressEvent, applyFirstImportProgressEvent])\n\n useAppEvent('progress.job.cancelled', (event) => {\n const payload = event.payload as ProgressEventPayload\n applyFirstImportProgressEvent(payload)\n applyFirstImportChildRunProgressEvent(payload)\n applyDeleteImportedProductsEvent(payload)\n }, [applyDeleteImportedProductsEvent, applyFirstImportChildRunProgressEvent, applyFirstImportProgressEvent])\n\n useAppEvent('om:bridge:reconnected', () => {\n void loadFirstImportStatus().catch(() => undefined)\n }, [loadFirstImportStatus])\n\n const attributeCodes = React.useMemo(\n () => (discovery?.attributes ?? []).map((attribute) => attribute.code).sort(),\n [discovery],\n )\n const customFieldRows = React.useMemo(\n () => parseCustomFieldRows(state.customFieldMappings),\n [state.customFieldMappings],\n )\n const priceMappingRows = React.useMemo(\n () => parsePriceMappingRows(state.priceMappings),\n [state.priceMappings],\n )\n const mediaMappingRows = React.useMemo(\n () => parseMediaMappingRows(state.mediaMappings),\n [state.mediaMappings],\n )\n const fieldsetMappingRows = React.useMemo(\n () => parseFieldsetMappingRows(state.fieldsetMappings),\n [state.fieldsetMappings],\n )\n const discoveredAkeneoChannelCodes = React.useMemo(\n () => (discovery?.channels ?? []).map((channel) => channel.code),\n [discovery],\n )\n const selectedAkeneoChannelSet = React.useMemo(\n () => new Set(state.productChannels),\n [state.productChannels],\n )\n const discoveredLocalChannelCodes = React.useMemo(\n () => (discovery?.localChannels ?? []).map((channel) => channel.code),\n [discovery],\n )\n const deleteImportedProductsBusy = isStartingDeleteImportedProducts\n || deleteImportedProductsJob?.status === 'pending'\n || deleteImportedProductsJob?.status === 'running'\n const firstImportBusy = firstImportProgress.phase === 'running'\n const firstImportReady = Boolean(context?.state?.isEnabled) && Boolean(data?.hasCredentials)\n const shouldShowFirstImportCallout = !isLoading && (\n firstImportBusy\n || firstImportProgress.phase === 'failed'\n || !hasCompletedProductImport\n )\n const firstImportCurrentStepLabel = firstImportProgress.step\n ? t(`sync_akeneo.firstImport.steps.${firstImportProgress.step}`, firstImportProgress.step)\n : null\n const discoveredPriceKindCodes = React.useMemo(\n () => (discovery?.priceKinds ?? []).map((priceKind) => priceKind.code),\n [discovery],\n )\n const productFieldKeys = React.useMemo(\n () => new Set(customFieldStatus?.productKeys ?? []),\n [customFieldStatus],\n )\n const variantFieldKeys = React.useMemo(\n () => new Set(customFieldStatus?.variantKeys ?? []),\n [customFieldStatus],\n )\n const missingCustomFieldCount = React.useMemo(\n () => customFieldRows.filter((row) => {\n if (row.skip) return false\n if (!row.fieldKey.trim()) return false\n return row.target === 'product'\n ? !productFieldKeys.has(row.fieldKey.trim())\n : !variantFieldKeys.has(row.fieldKey.trim())\n }).length,\n [customFieldRows, productFieldKeys, variantFieldKeys],\n )\n const editorMappedAttributeCodes = React.useMemo(\n () => new Set(customFieldEditorRows.map((row) => row.attributeCode).filter((value) => value.length > 0)),\n [customFieldEditorRows],\n )\n const suggestedCustomFieldAttributes = React.useMemo(\n () => (discovery?.attributes ?? []).filter((attribute) => !editorMappedAttributeCodes.has(attribute.code)).slice(0, 24),\n [discovery, editorMappedAttributeCodes],\n )\n const dialogMissingCustomFieldCount = React.useMemo(\n () => customFieldEditorRows.filter((row) => {\n if (row.skip) return false\n if (!row.fieldKey.trim()) return false\n return row.target === 'product'\n ? !productFieldKeys.has(row.fieldKey.trim())\n : !variantFieldKeys.has(row.fieldKey.trim())\n }).length,\n [customFieldEditorRows, productFieldKeys, variantFieldKeys],\n )\n const skippedCustomFieldCount = React.useMemo(\n () => customFieldRows.filter((row) => row.skip).length,\n [customFieldRows],\n )\n const renderCustomFieldStatusBadge = React.useCallback((exists: boolean) => (\n <Badge\n variant=\"outline\"\n className={exists\n ? 'inline-flex items-center gap-1.5 border-emerald-200 bg-emerald-50 text-emerald-700'\n : 'inline-flex items-center gap-1.5 border-amber-200 bg-amber-50 text-amber-700'}\n >\n {exists ? <CheckCircle2 className=\"size-3.5\" /> : <AlertCircle className=\"size-3.5\" />}\n <span>\n {exists\n ? t('sync_akeneo.customFields.status.ready', 'Exists')\n : t('sync_akeneo.customFields.status.missing', 'Missing')}\n </span>\n </Badge>\n ), [t])\n const renderSkippedCustomFieldBadge = React.useCallback(() => (\n <Badge\n variant=\"outline\"\n className=\"inline-flex items-center gap-1.5 border-slate-300 bg-slate-100 text-slate-700\"\n >\n <X className=\"size-3.5\" />\n <span>{t('sync_akeneo.customFields.status.skipped', 'Skipped')}</span>\n </Badge>\n ), [t])\n\n function openCustomFieldDialog() {\n setCustomFieldEditorRows(parseCustomFieldRows(state.customFieldMappings))\n setCustomFieldDialogOpen(true)\n }\n\n function toggleImportedAkeneoChannel(code: string, checked: boolean) {\n setState((current) => {\n const next = checked\n ? Array.from(new Set([...current.productChannels, code]))\n : current.productChannels.filter((entry) => entry !== code)\n const nextPrimary = next.includes(current.productChannel)\n ? current.productChannel\n : next[0] ?? ''\n return {\n ...current,\n productChannels: next,\n productChannel: nextPrimary,\n }\n })\n }\n\n async function createMissingCustomFields(sourceRows?: CustomFieldRow[]) {\n setIsCreatingCustomFields(true)\n try {\n const customFieldMappings = (sourceRows ?? parseCustomFieldRows(state.customFieldMappings))\n .filter((row) => !row.skip)\n if (customFieldMappings.length === 0) {\n flash(t('sync_akeneo.customFields.createNothing', 'There are no non-skipped custom-field mappings to create.'), 'info')\n return\n }\n const currentProductsMapping = {\n ...buildDefaultAkeneoMapping('products'),\n settings: {\n products: {\n locale: state.productLocale,\n channel: state.productChannel || null,\n channels: state.importAllProductChannels ? [] : state.productChannels,\n importAllChannels: state.importAllProductChannels,\n fieldMap: { ...state.fieldMap },\n customFieldMappings: customFieldMappings.map((row) => ({\n attributeCode: row.attributeCode.trim(),\n target: row.target,\n fieldKey: row.fieldKey.trim() || normalizeFieldKey(row.attributeCode),\n kind: row.kind || null,\n skip: false,\n })),\n priceMappings: [],\n mediaMappings: [],\n fieldsetMappings: parseFieldsetMappingRows(state.fieldsetMappings).map((row) => ({\n sourceType: row.sourceType,\n sourceCode: row.sourceCode.trim(),\n target: row.target,\n fieldsetCode: row.fieldsetCode.trim(),\n fieldsetLabel: row.fieldsetLabel.trim(),\n description: row.description.trim() || null,\n })),\n createMissingChannels: state.createMissingChannels,\n syncAssociations: state.syncAssociations,\n reconciliation: { ...state.reconciliation },\n },\n },\n }\n currentProductsMapping.fields = buildProductFieldMappings(currentProductsMapping.settings.products)\n const result = await apiCall<CustomFieldStatusResponse>('/api/sync_akeneo/custom-fields', {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({\n mapping: currentProductsMapping,\n }),\n })\n setCustomFieldStatus(result.result ?? null)\n flash(\n result.result?.message\n ?? t('sync_akeneo.customFields.created', 'Akeneo-backed custom fields created.'),\n 'success',\n )\n } catch (error) {\n const message = error instanceof Error ? error.message : 'Failed to create custom fields'\n flash(message, 'error')\n } finally {\n setIsCreatingCustomFields(false)\n }\n }\n\n function applyCustomFieldEditor() {\n setState((current) => ({\n ...current,\n customFieldMappings: serializeCustomFieldRows(customFieldEditorRows),\n }))\n setCustomFieldDialogOpen(false)\n }\n\n function updatePriceMappingRows(nextRows: PriceMappingRow[]) {\n setState((current) => ({\n ...current,\n priceMappings: serializePriceMappingRows(nextRows),\n }))\n }\n\n function updateMediaMappingRows(nextRows: MediaMappingRow[]) {\n setState((current) => ({\n ...current,\n mediaMappings: serializeMediaMappingRows(nextRows),\n }))\n }\n\n function updateFieldsetMappingRows(nextRows: FieldsetMappingRow[]) {\n setState((current) => ({\n ...current,\n fieldsetMappings: serializeFieldsetMappingRows(nextRows),\n }))\n }\n\n async function refreshDiscoveredMappings() {\n setIsSaving(true)\n try {\n const discoveryCall = await apiCall<AkeneoDiscoveryResponse>('/api/sync_akeneo/discovery?refresh=true')\n const discovered = discoveryCall.result ?? null\n if (!discovered?.ok) {\n throw new Error(discovered?.message ?? 'Failed to load Akeneo discovery metadata')\n }\n\n const nextState = applyDiscoveryDefaults({ ...state }, discovered)\n\n await persistMappings(nextState, {\n successMessage: t('sync_akeneo.discovery.rediscovered', 'Akeneo fields refreshed and missing mappings added.'),\n })\n\n setState(nextState)\n setDiscovery(discovered)\n const customFieldsCall = await apiCall<CustomFieldStatusResponse>('/api/sync_akeneo/custom-fields')\n setCustomFieldStatus(customFieldsCall.result ?? null)\n } catch (error) {\n const message = error instanceof Error ? error.message : 'Failed to refresh Akeneo mappings'\n flash(message, 'error')\n } finally {\n setIsSaving(false)\n }\n }\n\n async function saveMappings() {\n setIsSaving(true)\n try {\n await persistMappings(state, {\n successMessage: t('sync_akeneo.saved', 'Akeneo sync settings saved.'),\n })\n await load(false)\n } catch (error) {\n const message = error instanceof Error ? error.message : 'Failed to save Akeneo mapping'\n flash(message, 'error')\n } finally {\n setIsSaving(false)\n }\n }\n\n async function deleteImportedProducts() {\n const confirmed = await confirm({\n title: t('sync_akeneo.deleteImportedProducts.confirmTitle', 'Force delete all imported Akeneo products?'),\n text: t('sync_akeneo.deleteImportedProducts.confirmText', 'This will permanently delete products imported by the Akeneo integration for the current organization, together with their imported variants and related catalog data. The Akeneo product cursor will also be reset so a fresh import can start from scratch.'),\n confirmText: t('sync_akeneo.deleteImportedProducts.confirmAction', 'Force delete'),\n cancelText: t('sync_akeneo.deleteImportedProducts.cancel', 'Cancel'),\n variant: 'destructive',\n })\n if (!confirmed) return\n\n setIsStartingDeleteImportedProducts(true)\n try {\n const result = await apiCall<DeleteImportedProductsResponse>('/api/sync_akeneo/delete-products', {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ confirm: true }),\n })\n if (!result.ok || !result.result) {\n throw new Error('Failed to delete imported Akeneo products')\n }\n\n if (!result.result.progressJobId) {\n flash(result.result.message, 'success')\n await load(false)\n return\n }\n\n setDeleteImportedProductsJob({\n id: result.result.progressJobId,\n status: 'pending',\n progressPercent: 0,\n processedCount: 0,\n totalCount: null,\n })\n setDeleteImportedProductsJobId(result.result.progressJobId)\n } catch (error) {\n const message = error instanceof Error ? error.message : 'Failed to delete imported Akeneo products'\n flash(message, 'error')\n } finally {\n setIsStartingDeleteImportedProducts(false)\n }\n }\n\n return (\n <div className=\"space-y-6 rounded-lg border bg-card p-4\">\n <div className=\"space-y-3\">\n <h3 className=\"text-sm font-semibold\">\n {t('sync_akeneo.setup.heading', 'Akeneo API setup')}\n </h3>\n <Notice\n compact\n message={t('sync_akeneo.setup.scheduleTab', 'Run once and recurring schedules now live in the dedicated Sync schedules tab, shared by all data sync integrations.')}\n />\n <Notice\n title={t('sync_akeneo.setup.order.title', 'Recommended sync order')}\n message={t(\n 'sync_akeneo.setup.order.message',\n 'Run category sync first, attribute sync second, and product sync last. Product import expects local categories and family-based schemas to exist already.',\n )}\n />\n {shouldShowFirstImportCallout ? (\n <NextStepCallout\n icon={<Sparkles className=\"h-6 w-6\" />}\n title={t('sync_akeneo.firstImport.title', 'Run the first full import')}\n description={t(\n 'sync_akeneo.firstImport.help',\n 'Launch the standard Akeneo sync sequence in the recommended order: categories first, attributes second, products last.',\n )}\n steps={FIRST_IMPORT_STEPS.map((step, stepIndex) => {\n const currentStepIndex = firstImportProgress.step\n ? FIRST_IMPORT_STEPS.findIndex((item) => item.entityType === firstImportProgress.step)\n : -1\n const isActive = firstImportProgress.step === step.entityType && firstImportProgress.phase === 'running'\n const isDone = firstImportProgress.phase === 'running' && currentStepIndex > stepIndex\n return {\n id: step.entityType,\n label: t(`sync_akeneo.firstImport.steps.${step.entityType}`, step.entityType),\n state: isActive ? 'active' : isDone ? 'completed' : 'pending',\n }\n })}\n actionLabel={firstImportBusy\n ? t('sync_akeneo.firstImport.running', 'Running full import sequence...')\n : t('sync_akeneo.firstImport.action', 'Run the first full import')}\n actionIcon={firstImportBusy ? <RefreshCw className=\"mr-2 h-4 w-4 animate-spin\" /> : <Wand2 className=\"mr-2 h-4 w-4\" />}\n onAction={() => void runFirstFullImport()}\n disabled={isLoading || isSaving || deleteImportedProductsBusy || !firstImportReady}\n busy={firstImportBusy}\n disabledMessage={!firstImportReady\n ? context?.state?.isEnabled\n ? t('sync_akeneo.firstImport.missingCredentials', 'Save valid Akeneo credentials before starting the first full import.')\n : t('sync_akeneo.firstImport.integrationDisabled', 'Enable the integration and save valid Akeneo credentials before starting the first full import.')\n : undefined}\n status={firstImportProgress.phase !== 'idle'\n ? {\n tone: firstImportProgress.phase === 'failed' ? 'danger' : 'info',\n icon: firstImportProgress.phase === 'failed'\n ? <AlertCircle className=\"h-4 w-4\" />\n : <RefreshCw className={firstImportBusy ? 'h-4 w-4 animate-spin' : 'h-4 w-4'} />,\n label: firstImportProgress.phase === 'failed'\n ? t('sync_akeneo.firstImport.status.failed', 'Full import failed')\n : t('sync_akeneo.firstImport.status.running', 'Full import sequence running'),\n badge: firstImportCurrentStepLabel ? <Badge variant=\"outline\">{firstImportCurrentStepLabel}</Badge> : null,\n progressValue: typeof firstImportProgress.progressPercent === 'number' ? firstImportProgress.progressPercent : null,\n progressDescription: firstImportBusy\n ? firstImportProgress.totalCount && firstImportProgress.totalCount > 0\n ? t(\n 'sync_akeneo.firstImport.progressCount',\n '{processed} of {total} items processed in the current run.',\n {\n processed: firstImportProgress.processedCount ?? 0,\n total: firstImportProgress.totalCount,\n },\n )\n : t('sync_akeneo.firstImport.progressUnknown', 'The current run is active. Live progress also appears in the global operations bar.')\n : undefined,\n errorMessage: firstImportProgress.errorMessage,\n }\n : null}\n />\n ) : null}\n <div className=\"grid gap-4 lg:grid-cols-2\">\n <div className=\"rounded-lg border p-4\">\n <h4 className=\"text-sm font-medium\">{t('sync_akeneo.setup.credentials.title', 'Create API credentials in Akeneo')}</h4>\n <ol className=\"mt-3 list-decimal space-y-2 pl-5 text-sm text-muted-foreground\">\n <li>{t('sync_akeneo.setup.credentials.step1', 'In Akeneo, open Settings -> Connections and create a new API connection or connected app for Open Mercato.')}</li>\n <li>{t('sync_akeneo.setup.credentials.step2', 'Copy the Akeneo base URL, client id, and client secret into the Integration credentials tab in Open Mercato.')}</li>\n <li>{t('sync_akeneo.setup.credentials.step3', 'Create a dedicated Akeneo API user, assign it to the right catalog permissions, and use that username/password in the credential form.')}</li>\n <li>{t('sync_akeneo.setup.credentials.step4', 'Grant the API user access to products, categories, attributes, families, family variants, locales, and channels. Limit write permissions if you only import.')}</li>\n </ol>\n </div>\n <div className=\"rounded-lg border p-4\">\n <h4 className=\"text-sm font-medium\">{t('sync_akeneo.setup.docs.title', 'Operational notes')}</h4>\n <ul className=\"mt-3 list-disc space-y-2 pl-5 text-sm text-muted-foreground\">\n <li>{t('sync_akeneo.setup.docs.note1', 'Akeneo authentication uses client id, client secret, username, and password. Open Mercato exchanges those for access/refresh tokens automatically.')}</li>\n <li>{t('sync_akeneo.setup.docs.note2', 'For large catalogs, keep batch sizes at 100 and prefer incremental product syncs. The importer resumes from the last processed Akeneo updated timestamp plus search_after pagination state.')}</li>\n <li>{t('sync_akeneo.setup.docs.note3', 'Simple Akeneo products still create a default Open Mercato variant. Variant Akeneo products flatten the full Akeneo product-model tree into one configurable product plus child variants.')}</li>\n <li>{t('sync_akeneo.setup.docs.note4', 'If you want channel offers and prices, create matching Sales Channels and Catalog Price Kinds in Open Mercato first, then reference their codes in the mapping blocks below.')}</li>\n </ul>\n <div className=\"mt-4 flex flex-wrap gap-2 text-sm\">\n <a className=\"underline\" href=\"https://api.akeneo.com/documentation/authentication.html\" target=\"_blank\" rel=\"noreferrer\">\n {t('sync_akeneo.links.auth', 'Akeneo authentication docs')}\n </a>\n <a className=\"underline\" href=\"https://api.akeneo.com/documentation/pagination.html\" target=\"_blank\" rel=\"noreferrer\">\n {t('sync_akeneo.links.pagination', 'Akeneo pagination docs')}\n </a>\n </div>\n </div>\n </div>\n </div>\n\n <div className=\"space-y-3\">\n <div className=\"flex items-center justify-between gap-3\">\n <div>\n <h3 className=\"text-sm font-semibold\">{t('sync_akeneo.mapping.heading', 'Field mapping')}</h3>\n <p className=\"text-sm text-muted-foreground\">\n {t('sync_akeneo.mapping.help', 'Mappings are discovered automatically from the saved Akeneo credentials. Use refresh discovery to pull the latest Akeneo metadata and add any missing mappings without deleting your existing overrides.')}\n </p>\n </div>\n <div className=\"flex flex-wrap gap-2\">\n <Button type=\"button\" variant=\"outline\" onClick={() => void refreshDiscoveredMappings()} disabled={isLoading || isSaving || deleteImportedProductsBusy || firstImportBusy}>\n <RefreshCw className=\"mr-2 h-4 w-4\" />\n {t('sync_akeneo.mapping.refresh', 'Refresh discovery')}\n </Button>\n <Button type=\"button\" variant=\"destructive\" onClick={() => void deleteImportedProducts()} disabled={isLoading || isSaving || deleteImportedProductsBusy || firstImportBusy}>\n <Trash2 className=\"mr-2 h-4 w-4\" />\n {deleteImportedProductsBusy\n ? t('sync_akeneo.deleteImportedProducts.inProgress', 'Deletion in progress...')\n : t('sync_akeneo.deleteImportedProducts.action', 'Force delete all imported products')}\n </Button>\n </div>\n </div>\n\n {deleteImportedProductsBusy && deleteImportedProductsJob ? (\n <div className=\"rounded-lg border border-destructive/30 bg-destructive/5 p-3\">\n <div className=\"flex flex-wrap items-center justify-between gap-2 text-sm\">\n <div className=\"font-medium\">\n {t('sync_akeneo.deleteImportedProducts.progressTitle', 'Deleting imported Akeneo products')}\n </div>\n <Badge variant=\"outline\">\n {deleteImportedProductsJob.totalCount && deleteImportedProductsJob.totalCount > 0\n ? t(\n 'sync_akeneo.deleteImportedProducts.progressCount',\n '{processed} / {total}',\n {\n processed: deleteImportedProductsJob.processedCount,\n total: deleteImportedProductsJob.totalCount,\n },\n )\n : t('sync_akeneo.deleteImportedProducts.preparing', 'Preparing...')}\n </Badge>\n </div>\n {deleteImportedProductsJob.totalCount && deleteImportedProductsJob.totalCount > 0 ? (\n <Progress value={deleteImportedProductsJob.progressPercent} className=\"mt-3 h-2\" />\n ) : (\n <div className=\"mt-3 h-2 rounded-full bg-secondary\" />\n )}\n <p className=\"mt-2 text-xs text-muted-foreground\">\n {deleteImportedProductsJob.status === 'pending'\n ? t('sync_akeneo.deleteImportedProducts.pending', 'The deletion job is being prepared.')\n : t(\n 'sync_akeneo.deleteImportedProducts.running',\n 'The imported product cleanup is running in the background. Progress also appears in the global progress bar.',\n )}\n </p>\n </div>\n ) : null}\n\n {discovery?.message ? (\n <Notice compact variant={discovery.ok ? 'info' : 'warning'}>\n {discovery.message}\n </Notice>\n ) : null}\n\n <div className=\"grid gap-6 xl:grid-cols-[1.2fr_0.8fr]\">\n <div className=\"space-y-5 rounded-lg border p-4\">\n <div className=\"grid gap-4 md:grid-cols-2\">\n <div className=\"space-y-2\">\n <Label htmlFor=\"akeneo-product-locale\">{t('sync_akeneo.mapping.productLocale', 'Product locale')}</Label>\n <select\n id=\"akeneo-product-locale\"\n value={state.productLocale}\n onChange={(event) => setState((current) => ({ ...current, productLocale: event.target.value }))}\n disabled={isLoading || isSaving || (discovery?.locales?.length ?? 0) === 0}\n className=\"flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background\"\n >\n {(discovery?.locales ?? []).map((locale) => (\n <option key={locale.code} value={locale.code}>\n {locale.code}\n </option>\n ))}\n </select>\n <p className=\"text-xs text-muted-foreground\">\n {t('sync_akeneo.mapping.productLocale.help', 'Only this Akeneo locale is imported into the base Open Mercato fields for now. Other locales are ignored until translation import is added.')}\n </p>\n </div>\n <div className=\"space-y-2\">\n <Label htmlFor=\"akeneo-product-channel\">{t('sync_akeneo.mapping.productChannel', 'Primary content channel')}</Label>\n <select\n id=\"akeneo-product-channel\"\n value={state.productChannel}\n onChange={(event) => setState((current) => {\n const nextChannel = event.target.value\n return {\n ...current,\n productChannel: nextChannel,\n productChannels: current.importAllProductChannels || !nextChannel || current.productChannels.includes(nextChannel)\n ? current.productChannels\n : [...current.productChannels, nextChannel],\n }\n })}\n disabled={isLoading || isSaving || (discovery?.channels?.length ?? 0) === 0}\n className=\"h-10 w-full appearance-auto rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background\"\n >\n <option value=\"\">{t('sync_akeneo.mapping.channelPlaceholder', 'Optional')}</option>\n {(discovery?.channels ?? []).map((channel) => (\n <option key={channel.code} value={channel.code}>\n {channel.code}\n </option>\n ))}\n </select>\n <p className=\"text-xs text-muted-foreground\">\n {t('sync_akeneo.mapping.productChannel.help', 'This single Akeneo channel is used for base product content, custom fields, media, and variant labels when attributes are channel-scoped.')}\n </p>\n </div>\n </div>\n\n <div className=\"space-y-3 rounded-lg border p-3\">\n <div className=\"space-y-1\">\n <Label>{t('sync_akeneo.mapping.importChannels', 'Imported Akeneo channels')}</Label>\n <p className=\"text-xs text-muted-foreground\">\n {t('sync_akeneo.mapping.importChannels.help', 'Choose which Akeneo channels should be imported for channel-scoped data like offers and prices. Locale stays single-select.')}\n </p>\n </div>\n <label className=\"flex items-center gap-2 text-sm\">\n <input\n type=\"checkbox\"\n checked={state.importAllProductChannels}\n onChange={(event) => setState((current) => ({\n ...current,\n importAllProductChannels: event.target.checked,\n productChannels: event.target.checked\n ? current.productChannels\n : (current.productChannels.length > 0\n ? current.productChannels\n : current.productChannel\n ? [current.productChannel]\n : []),\n }))}\n disabled={isLoading || isSaving}\n />\n <span>{t('sync_akeneo.mapping.importChannels.all', 'Import all Akeneo channels')}</span>\n </label>\n {!state.importAllProductChannels ? (\n <div className=\"grid gap-2 md:grid-cols-2\">\n {(discovery?.channels ?? []).map((channel) => (\n <label key={channel.code} className=\"flex items-center gap-2 rounded border px-3 py-2 text-sm\">\n <input\n type=\"checkbox\"\n checked={selectedAkeneoChannelSet.has(channel.code)}\n onChange={(event) => toggleImportedAkeneoChannel(channel.code, event.target.checked)}\n disabled={isLoading || isSaving}\n />\n <span>{channel.code}</span>\n </label>\n ))}\n </div>\n ) : null}\n </div>\n\n <div className=\"grid gap-4 md:grid-cols-2\">\n {PRODUCT_FIELD_KEYS.map((field) => (\n <div key={field.key} className=\"space-y-2\">\n <Label htmlFor={`akeneo-${field.key}`}>{t(`sync_akeneo.mapping.${field.key}`, field.label)}</Label>\n <Input\n id={`akeneo-${field.key}`}\n list=\"akeneo-attributes\"\n value={state.fieldMap[field.key]}\n onChange={(event) => {\n const value = event.target.value\n setState((current) => ({\n ...current,\n fieldMap: {\n ...current.fieldMap,\n [field.key]: value,\n },\n }))\n }}\n disabled={isLoading || isSaving}\n />\n <p className=\"text-xs text-muted-foreground\">{t(`sync_akeneo.mapping.${field.key}.help`, field.help)}</p>\n </div>\n ))}\n </div>\n\n <div className=\"grid gap-4 md:grid-cols-2\">\n <div className=\"space-y-2\">\n <Label htmlFor=\"akeneo-category-locale\">{t('sync_akeneo.mapping.categoryLocale', 'Category label locale')}</Label>\n <select\n id=\"akeneo-category-locale\"\n value={state.categoryLocale}\n onChange={(event) => setState((current) => ({ ...current, categoryLocale: event.target.value }))}\n disabled={isLoading || isSaving || (discovery?.locales?.length ?? 0) === 0}\n className=\"flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background\"\n >\n {(discovery?.locales ?? []).map((locale) => (\n <option key={locale.code} value={locale.code}>\n {locale.code}\n </option>\n ))}\n </select>\n </div>\n <div className=\"space-y-2\">\n <Label htmlFor=\"akeneo-family-filter\">{t('sync_akeneo.mapping.familyFilter', 'Attribute sync family filter')}</Label>\n <Input\n id=\"akeneo-family-filter\"\n value={state.familyCodeFilter}\n onChange={(event) => setState((current) => ({ ...current, familyCodeFilter: event.target.value }))}\n disabled={isLoading || isSaving}\n placeholder={t('sync_akeneo.mapping.familyFilterPlaceholder', 'family_a, family_b')}\n />\n <p className=\"text-xs text-muted-foreground\">\n {t('sync_akeneo.mapping.familyFilter.help', 'Leave empty to sync family-driven schemas for all Akeneo families.')}\n </p>\n </div>\n </div>\n\n <div className=\"grid gap-4\">\n <div className=\"space-y-2\">\n <div className=\"flex items-center justify-between gap-3\">\n <Label>{t('sync_akeneo.mapping.customFields', 'Custom field mappings')}</Label>\n <div className=\"flex flex-wrap items-center gap-2\">\n <Button type=\"button\" variant=\"outline\" onClick={() => openCustomFieldDialog()} disabled={isLoading || isSaving}>\n <PencilLine className=\"mr-2 h-4 w-4\" />\n {t('sync_akeneo.mapping.customFields.editor', 'Open editor')}\n </Button>\n <Button type=\"button\" variant=\"outline\" onClick={() => void createMissingCustomFields()} disabled={isLoading || isSaving || isCreatingCustomFields || customFieldRows.length === 0}>\n {isCreatingCustomFields ? <RefreshCw className=\"mr-2 h-4 w-4 animate-spin\" /> : <Wand2 className=\"mr-2 h-4 w-4\" />}\n {isCreatingCustomFields\n ? t('sync_akeneo.mapping.customFields.creating', 'Creating...')\n : t('sync_akeneo.mapping.customFields.createMissing', 'Pre-create missing fields')}\n </Button>\n </div>\n </div>\n <p className=\"text-xs text-muted-foreground\">\n {t('sync_akeneo.mapping.customFields.help', 'One mapping per line: attribute_code,target(product|variant),field_key[,kind][,skip]. After valid Akeneo credentials are saved, Open Mercato discovers mappings automatically: variant axes stay as product options, and other relevant Akeneo attributes are auto-mapped as custom fields unless you override them here. Use the editor skip checkbox when an Akeneo attribute should be ignored entirely. Product imports create or update missing Open Mercato custom field definitions automatically and store the Akeneo metadata, validation rules, and groups on those fields.')}\n </p>\n <div className=\"flex items-start gap-2 rounded-md border border-emerald-200 bg-emerald-50/70 px-3 py-2 text-xs text-emerald-800\">\n <Sparkles className=\"mt-0.5 size-3.5 shrink-0\" />\n <span>\n {t('sync_akeneo.mapping.customFields.autoCreate', 'Running the Akeneo product import also creates any missing mapped fields automatically. Use the manual action only when you want to provision them before the first import.')}\n </span>\n </div>\n {customFieldRows.length > 0 ? (\n <div className=\"overflow-x-auto rounded-lg border\">\n <table className=\"w-full min-w-[760px] text-sm\">\n <thead className=\"bg-muted/50 text-left\">\n <tr>\n <th className=\"px-3 py-2 font-medium\">{t('sync_akeneo.mapping.from', 'From')}</th>\n <th className=\"px-3 py-2 font-medium\">{t('sync_akeneo.customFields.columns.target', 'Target')}</th>\n <th className=\"px-3 py-2 font-medium\">{t('sync_akeneo.customFields.columns.key', 'Field key')}</th>\n <th className=\"px-3 py-2 font-medium\">{t('sync_akeneo.customFields.columns.kind', 'Kind')}</th>\n <th className=\"px-3 py-2 font-medium\">{t('sync_akeneo.customFields.columns.status', 'Status')}</th>\n </tr>\n </thead>\n <tbody>\n {customFieldRows.map((row, index) => {\n const exists = row.target === 'product'\n ? productFieldKeys.has(row.fieldKey.trim())\n : variantFieldKeys.has(row.fieldKey.trim())\n return (\n <tr key={`${row.attributeCode}:${row.fieldKey}:${index}`} className={`border-t ${row.skip ? 'opacity-70' : ''}`}>\n <td className=\"px-3 py-2 font-medium\">{row.attributeCode}</td>\n <td className=\"px-3 py-2\">{row.target}</td>\n <td className=\"px-3 py-2\">{row.fieldKey}</td>\n <td className=\"px-3 py-2 text-muted-foreground\">{row.kind || t('sync_akeneo.customFields.kinds.auto', 'Auto')}</td>\n <td className=\"px-3 py-2\">\n {row.skip ? renderSkippedCustomFieldBadge() : renderCustomFieldStatusBadge(exists)}\n </td>\n </tr>\n )\n })}\n </tbody>\n </table>\n </div>\n ) : (\n <Notice compact>\n {t('sync_akeneo.customFields.empty', 'No Akeneo custom fields are shown yet. They are discovered and mapped automatically after credentials are saved or when you use Refresh discovery. Use the editor only if you want to review or override the automatic mapping.')}\n </Notice>\n )}\n {customFieldRows.length > 0 ? (\n <div className=\"flex flex-wrap gap-2 text-xs\">\n <span className=\"rounded border px-2 py-1\">\n {t('sync_akeneo.mapping.customFields.total', `${customFieldRows.length} mapped`)}\n </span>\n {skippedCustomFieldCount > 0 ? (\n <span className=\"rounded border px-2 py-1\">\n {t('sync_akeneo.mapping.customFields.skipped', `${skippedCustomFieldCount} skipped`)}\n </span>\n ) : null}\n <span className={`rounded border px-2 py-1 ${missingCustomFieldCount > 0 ? 'border-amber-300 text-amber-700' : ''}`}>\n {missingCustomFieldCount > 0\n ? t('sync_akeneo.mapping.customFields.missing', `${missingCustomFieldCount} missing locally`)\n : t('sync_akeneo.mapping.customFields.ready', 'All mapped fields already exist')}\n </span>\n </div>\n ) : null}\n </div>\n <div className=\"space-y-2\">\n <div className=\"flex items-center justify-between gap-3\">\n <Label>{t('sync_akeneo.mapping.prices', 'Price and offer mappings')}</Label>\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={() => updatePriceMappingRows([\n ...priceMappingRows,\n { attributeCode: '', priceKindCode: '', akeneoChannel: '', localChannelCode: '' },\n ])}\n disabled={isLoading || isSaving}\n >\n <Plus className=\"mr-2 h-4 w-4\" />\n {t('sync_akeneo.mapping.addRow', 'Add row')}\n </Button>\n </div>\n <p className=\"text-xs text-muted-foreground\">\n {t('sync_akeneo.mapping.prices.help', 'One mapping per line: price_attribute,price_kind_code,akeneo_channel,local_channel_code. Each distinct local channel creates or updates an offer, and each price collection entry becomes a Catalog Product Price in the matching currency.')}\n </p>\n <div className=\"overflow-x-auto rounded-lg border\">\n <table className=\"w-full min-w-[900px] text-sm\">\n <thead className=\"bg-muted/50 text-left\">\n <tr>\n <th className=\"px-3 py-2 font-medium\">{t('sync_akeneo.mapping.from', 'From')}</th>\n <th className=\"px-3 py-2 font-medium\">{t('sync_akeneo.mapping.priceKind', 'Price kind')}</th>\n <th className=\"px-3 py-2 font-medium\">{t('sync_akeneo.mapping.akeneoChannel', 'Akeneo channel')}</th>\n <th className=\"px-3 py-2 font-medium\">{t('sync_akeneo.mapping.localChannel', 'Open Mercato channel')}</th>\n <th className=\"px-3 py-2 font-medium\">{t('sync_akeneo.customFields.columns.actions', 'Actions')}</th>\n </tr>\n </thead>\n <tbody>\n {priceMappingRows.length > 0 ? priceMappingRows.map((row, index) => (\n <tr key={`price-mapping-${index}`} className=\"border-t\">\n <td className=\"px-3 py-2\">\n <Input\n list=\"akeneo-attributes\"\n value={row.attributeCode}\n onChange={(event) => {\n const nextRows = [...priceMappingRows]\n nextRows[index] = { ...row, attributeCode: event.target.value }\n updatePriceMappingRows(nextRows)\n }}\n disabled={isLoading || isSaving}\n />\n </td>\n <td className=\"px-3 py-2\">\n <select\n className=\"flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm\"\n value={row.priceKindCode}\n onChange={(event) => {\n const nextRows = [...priceMappingRows]\n nextRows[index] = { ...row, priceKindCode: event.target.value }\n updatePriceMappingRows(nextRows)\n }}\n disabled={isLoading || isSaving}\n >\n <option value=\"\">{t('sync_akeneo.mapping.priceKindPlaceholder', 'Select price kind')}</option>\n {buildSelectValues(discoveredPriceKindCodes, row.priceKindCode).map((priceKindCode) => (\n <option key={priceKindCode} value={priceKindCode}>{priceKindCode}</option>\n ))}\n </select>\n </td>\n <td className=\"px-3 py-2\">\n <select\n className=\"flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm\"\n value={row.akeneoChannel}\n onChange={(event) => {\n const nextRows = [...priceMappingRows]\n nextRows[index] = { ...row, akeneoChannel: event.target.value }\n updatePriceMappingRows(nextRows)\n }}\n disabled={isLoading || isSaving}\n >\n <option value=\"\">{t('sync_akeneo.mapping.channelPlaceholder', 'Optional')}</option>\n {buildSelectValues(discoveredAkeneoChannelCodes, row.akeneoChannel).map((channelCode) => (\n <option key={channelCode} value={channelCode}>{channelCode}</option>\n ))}\n </select>\n </td>\n <td className=\"px-3 py-2\">\n <select\n className=\"flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm\"\n value={row.localChannelCode}\n onChange={(event) => {\n const nextRows = [...priceMappingRows]\n nextRows[index] = { ...row, localChannelCode: event.target.value }\n updatePriceMappingRows(nextRows)\n }}\n disabled={isLoading || isSaving}\n >\n <option value=\"\">{t('sync_akeneo.mapping.localChannelPlaceholder', 'Select Open Mercato channel')}</option>\n {buildSelectValues(discoveredLocalChannelCodes, row.localChannelCode).map((channelCode) => (\n <option key={channelCode} value={channelCode}>{channelCode}</option>\n ))}\n </select>\n </td>\n <td className=\"px-3 py-2\">\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n onClick={() => updatePriceMappingRows(priceMappingRows.filter((_, rowIndex) => rowIndex !== index))}\n disabled={isLoading || isSaving}\n >\n <Trash2 className=\"mr-2 h-4 w-4\" />\n {t('sync_akeneo.customFields.actions.remove', 'Remove')}\n </Button>\n </td>\n </tr>\n )) : (\n <tr>\n <td colSpan={5} className=\"px-3 py-6 text-center text-sm text-muted-foreground\">\n {t('sync_akeneo.mapping.emptyPrices', 'No price mappings configured yet.')}\n </td>\n </tr>\n )}\n </tbody>\n </table>\n </div>\n </div>\n <div className=\"space-y-2\">\n <div className=\"flex items-center justify-between gap-3\">\n <Label>{t('sync_akeneo.mapping.media', 'Media and attachment mappings')}</Label>\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={() => updateMediaMappingRows([\n ...mediaMappingRows,\n { attributeCode: '', target: 'product', kind: 'image' },\n ])}\n disabled={isLoading || isSaving}\n >\n <Plus className=\"mr-2 h-4 w-4\" />\n {t('sync_akeneo.mapping.addRow', 'Add row')}\n </Button>\n </div>\n <p className=\"text-xs text-muted-foreground\">\n {t('sync_akeneo.mapping.media.help', 'One mapping per line: attribute_code,target(product|variant),kind(image|file). Image mappings are re-hosted into Open Mercato attachments and can become default media; file mappings are imported as attachments.')}\n </p>\n <div className=\"overflow-x-auto rounded-lg border\">\n <table className=\"w-full min-w-[760px] text-sm\">\n <thead className=\"bg-muted/50 text-left\">\n <tr>\n <th className=\"px-3 py-2 font-medium\">{t('sync_akeneo.mapping.from', 'From')}</th>\n <th className=\"px-3 py-2 font-medium\">{t('sync_akeneo.customFields.columns.target', 'Target')}</th>\n <th className=\"px-3 py-2 font-medium\">{t('sync_akeneo.customFields.columns.kind', 'Kind')}</th>\n <th className=\"px-3 py-2 font-medium\">{t('sync_akeneo.customFields.columns.actions', 'Actions')}</th>\n </tr>\n </thead>\n <tbody>\n {mediaMappingRows.length > 0 ? mediaMappingRows.map((row, index) => (\n <tr key={`media-mapping-${index}`} className=\"border-t\">\n <td className=\"px-3 py-2\">\n <Input\n list=\"akeneo-attributes\"\n value={row.attributeCode}\n onChange={(event) => {\n const nextRows = [...mediaMappingRows]\n nextRows[index] = { ...row, attributeCode: event.target.value }\n updateMediaMappingRows(nextRows)\n }}\n disabled={isLoading || isSaving}\n />\n </td>\n <td className=\"px-3 py-2\">\n <select\n className=\"flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm\"\n value={row.target}\n onChange={(event) => {\n const nextRows = [...mediaMappingRows]\n nextRows[index] = { ...row, target: event.target.value === 'variant' ? 'variant' : 'product' }\n updateMediaMappingRows(nextRows)\n }}\n disabled={isLoading || isSaving}\n >\n <option value=\"product\">{t('sync_akeneo.customFields.targets.product', 'Product')}</option>\n <option value=\"variant\">{t('sync_akeneo.customFields.targets.variant', 'Variant')}</option>\n </select>\n </td>\n <td className=\"px-3 py-2\">\n <select\n className=\"flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm\"\n value={row.kind}\n onChange={(event) => {\n const nextRows = [...mediaMappingRows]\n nextRows[index] = { ...row, kind: event.target.value === 'file' ? 'file' : 'image' }\n updateMediaMappingRows(nextRows)\n }}\n disabled={isLoading || isSaving}\n >\n <option value=\"image\">{t('sync_akeneo.mapping.mediaKinds.image', 'Image')}</option>\n <option value=\"file\">{t('sync_akeneo.mapping.mediaKinds.file', 'File')}</option>\n </select>\n </td>\n <td className=\"px-3 py-2\">\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n onClick={() => updateMediaMappingRows(mediaMappingRows.filter((_, rowIndex) => rowIndex !== index))}\n disabled={isLoading || isSaving}\n >\n <Trash2 className=\"mr-2 h-4 w-4\" />\n {t('sync_akeneo.customFields.actions.remove', 'Remove')}\n </Button>\n </td>\n </tr>\n )) : (\n <tr>\n <td colSpan={4} className=\"px-3 py-6 text-center text-sm text-muted-foreground\">\n {t('sync_akeneo.mapping.emptyMedia', 'No media mappings configured yet.')}\n </td>\n </tr>\n )}\n </tbody>\n </table>\n </div>\n </div>\n <div className=\"space-y-2\">\n <div className=\"flex items-center justify-between gap-3\">\n <Label>{t('sync_akeneo.mapping.fieldsets', 'Family to fieldset mappings')}</Label>\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={() => updateFieldsetMappingRows([\n ...fieldsetMappingRows,\n {\n sourceType: 'family',\n sourceCode: '',\n target: 'product',\n fieldsetCode: '',\n fieldsetLabel: '',\n description: '',\n },\n ])}\n disabled={isLoading || isSaving}\n >\n <Plus className=\"mr-2 h-4 w-4\" />\n {t('sync_akeneo.mapping.addRow', 'Add row')}\n </Button>\n </div>\n <p className=\"text-xs text-muted-foreground\">\n {t('sync_akeneo.mapping.fieldsets.help', 'Discovered Akeneo families become Open Mercato fieldsets automatically. Adjust the fieldset code, label, or description here, and add manual family-variant rows when a specific Akeneo family variant should use a different variant fieldset.')}\n </p>\n <div className=\"overflow-x-auto rounded-lg border\">\n <table className=\"w-full min-w-[1100px] text-sm\">\n <thead className=\"bg-muted/50 text-left\">\n <tr>\n <th className=\"px-3 py-2 font-medium\">{t('sync_akeneo.mapping.sourceType', 'Source type')}</th>\n <th className=\"px-3 py-2 font-medium\">{t('sync_akeneo.mapping.sourceCode', 'Akeneo code')}</th>\n <th className=\"px-3 py-2 font-medium\">{t('sync_akeneo.customFields.columns.target', 'Target')}</th>\n <th className=\"px-3 py-2 font-medium\">{t('sync_akeneo.mapping.fieldsetCode', 'Fieldset code')}</th>\n <th className=\"px-3 py-2 font-medium\">{t('sync_akeneo.mapping.fieldsetLabel', 'Fieldset label')}</th>\n <th className=\"px-3 py-2 font-medium\">{t('sync_akeneo.mapping.fieldsetDescription', 'Description')}</th>\n <th className=\"px-3 py-2 font-medium\">{t('sync_akeneo.customFields.columns.actions', 'Actions')}</th>\n </tr>\n </thead>\n <tbody>\n {fieldsetMappingRows.length > 0 ? fieldsetMappingRows.map((row, index) => (\n <tr key={`fieldset-mapping-${index}`} className=\"border-t\">\n <td className=\"px-3 py-2\">\n <select\n className=\"flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm\"\n value={row.sourceType}\n onChange={(event) => {\n const nextRows = [...fieldsetMappingRows]\n nextRows[index] = {\n ...row,\n sourceType: event.target.value === 'familyVariant' ? 'familyVariant' : 'family',\n }\n updateFieldsetMappingRows(nextRows)\n }}\n disabled={isLoading || isSaving}\n >\n <option value=\"family\">{t('sync_akeneo.mapping.sourceType.family', 'Family')}</option>\n <option value=\"familyVariant\">{t('sync_akeneo.mapping.sourceType.familyVariant', 'Family variant')}</option>\n </select>\n </td>\n <td className=\"px-3 py-2\">\n <Input\n value={row.sourceCode}\n onChange={(event) => {\n const nextRows = [...fieldsetMappingRows]\n const sourceCode = event.target.value\n nextRows[index] = {\n ...row,\n sourceCode,\n fieldsetCode: row.fieldsetCode || buildAkeneoFieldsetCode(row.target, sourceCode) || '',\n }\n updateFieldsetMappingRows(nextRows)\n }}\n disabled={isLoading || isSaving}\n list={row.sourceType === 'family' ? 'akeneo-families' : undefined}\n />\n </td>\n <td className=\"px-3 py-2\">\n <select\n className=\"flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm\"\n value={row.target}\n onChange={(event) => {\n const nextRows = [...fieldsetMappingRows]\n const target = event.target.value === 'variant' ? 'variant' : 'product'\n nextRows[index] = {\n ...row,\n target,\n fieldsetCode: buildAkeneoFieldsetCode(target, row.sourceCode) || row.fieldsetCode,\n }\n updateFieldsetMappingRows(nextRows)\n }}\n disabled={isLoading || isSaving}\n >\n <option value=\"product\">{t('sync_akeneo.customFields.targets.product', 'Product')}</option>\n <option value=\"variant\">{t('sync_akeneo.customFields.targets.variant', 'Variant')}</option>\n </select>\n </td>\n <td className=\"px-3 py-2\">\n <Input\n value={row.fieldsetCode}\n onChange={(event) => {\n const nextRows = [...fieldsetMappingRows]\n nextRows[index] = { ...row, fieldsetCode: normalizeFieldKey(event.target.value) }\n updateFieldsetMappingRows(nextRows)\n }}\n disabled={isLoading || isSaving}\n />\n </td>\n <td className=\"px-3 py-2\">\n <Input\n value={row.fieldsetLabel}\n onChange={(event) => {\n const nextRows = [...fieldsetMappingRows]\n nextRows[index] = { ...row, fieldsetLabel: event.target.value }\n updateFieldsetMappingRows(nextRows)\n }}\n disabled={isLoading || isSaving}\n />\n </td>\n <td className=\"px-3 py-2\">\n <Input\n value={row.description}\n onChange={(event) => {\n const nextRows = [...fieldsetMappingRows]\n nextRows[index] = { ...row, description: event.target.value }\n updateFieldsetMappingRows(nextRows)\n }}\n disabled={isLoading || isSaving}\n />\n </td>\n <td className=\"px-3 py-2\">\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n onClick={() => updateFieldsetMappingRows(fieldsetMappingRows.filter((_, rowIndex) => rowIndex !== index))}\n disabled={isLoading || isSaving}\n >\n <Trash2 className=\"mr-2 h-4 w-4\" />\n {t('sync_akeneo.customFields.actions.remove', 'Remove')}\n </Button>\n </td>\n </tr>\n )) : (\n <tr>\n <td colSpan={7} className=\"px-3 py-6 text-center text-sm text-muted-foreground\">\n {t('sync_akeneo.mapping.emptyFieldsets', 'No family fieldset mappings discovered yet. Save credentials and use Refresh discovery to generate them.')}\n </td>\n </tr>\n )}\n </tbody>\n </table>\n </div>\n </div>\n </div>\n\n <div className=\"flex flex-wrap gap-3\">\n <label className=\"flex items-center gap-2 text-sm\">\n <input\n type=\"checkbox\"\n checked={state.includeTextAttributes}\n onChange={(event) => setState((current) => ({ ...current, includeTextAttributes: event.target.checked }))}\n disabled={isLoading || isSaving}\n />\n <span>{t('sync_akeneo.mapping.includeText', 'Include text attributes in generated family schemas')}</span>\n </label>\n <label className=\"flex items-center gap-2 text-sm\">\n <input\n type=\"checkbox\"\n checked={state.includeNumericAttributes}\n onChange={(event) => setState((current) => ({ ...current, includeNumericAttributes: event.target.checked }))}\n disabled={isLoading || isSaving}\n />\n <span>{t('sync_akeneo.mapping.includeNumeric', 'Include numeric and metric attributes in generated family schemas')}</span>\n </label>\n <label className=\"flex items-center gap-2 text-sm\">\n <input\n type=\"checkbox\"\n checked={state.createMissingChannels}\n onChange={(event) => setState((current) => ({ ...current, createMissingChannels: event.target.checked }))}\n disabled={isLoading || isSaving}\n />\n <span>{t('sync_akeneo.mapping.createMissingChannels', 'Create missing Open Mercato sales channels from Akeneo scopes by default')}</span>\n </label>\n <label className=\"flex items-center gap-2 text-sm\">\n <input\n type=\"checkbox\"\n checked={state.syncAssociations}\n onChange={(event) => setState((current) => ({ ...current, syncAssociations: event.target.checked }))}\n disabled={isLoading || isSaving}\n />\n <span>{t('sync_akeneo.mapping.syncAssociations', 'Import Akeneo associations into product/variant relation records')}</span>\n </label>\n </div>\n\n <div className=\"space-y-3 rounded-md border p-3\">\n <div>\n <h4 className=\"text-sm font-medium\">{t('sync_akeneo.mapping.reconciliation.title', 'Reconciliation and deletions')}</h4>\n <p className=\"text-xs text-muted-foreground\">\n {t('sync_akeneo.mapping.reconciliation.help', 'These cleanup rules apply during full syncs. Incremental syncs continue to upsert changed records, while stale Akeneo-managed offers, prices, and media are reconciled per product on every product import.')}\n </p>\n </div>\n <div className=\"grid gap-2 md:grid-cols-2\">\n {[\n ['deactivateMissingCategories', 'Deactivate categories missing from Akeneo'],\n ['deactivateMissingProducts', 'Deactivate products and variants missing from Akeneo'],\n ['deactivateMissingAttributes', 'Deactivate Akeneo-managed schemas and custom fields missing from Akeneo'],\n ['deleteMissingOffers', 'Delete Akeneo-managed offers no longer produced by mapping'],\n ['deleteMissingPrices', 'Delete Akeneo-managed prices no longer produced by mapping'],\n ['deleteMissingMedia', 'Delete stale Akeneo-managed images/default media'],\n ['deleteMissingAttachments', 'Delete stale Akeneo-managed file attachments'],\n ].map(([key, label]) => (\n <label key={key} className=\"flex items-center gap-2 text-sm\">\n <input\n type=\"checkbox\"\n checked={state.reconciliation[key as keyof AkeneoReconciliationSettings]}\n onChange={(event) => setState((current) => ({\n ...current,\n reconciliation: {\n ...current.reconciliation,\n [key]: event.target.checked,\n },\n }))}\n disabled={isLoading || isSaving}\n />\n <span>{t(`sync_akeneo.mapping.reconciliation.${key}`, label)}</span>\n </label>\n ))}\n </div>\n </div>\n\n <div className=\"flex justify-end\">\n <Button type=\"button\" onClick={() => void saveMappings()} disabled={isLoading || isSaving}>\n <Save className=\"mr-2 h-4 w-4\" />\n {isSaving ? t('sync_akeneo.mapping.saving', 'Saving...') : t('sync_akeneo.mapping.save', 'Save mappings')}\n </Button>\n </div>\n </div>\n\n <div className=\"space-y-4 rounded-lg border p-4\">\n <div>\n <h4 className=\"text-sm font-medium\">{t('sync_akeneo.discovery.heading', 'Discovered Akeneo fields')}</h4>\n <p className=\"text-sm text-muted-foreground\">\n {t('sync_akeneo.discovery.help', 'These values come from the current Akeneo credentials and are safe to paste into the mapping inputs.')}\n </p>\n </div>\n <div className=\"space-y-3\">\n <div>\n <div className=\"mb-2 text-xs font-medium uppercase text-muted-foreground\">{t('sync_akeneo.discovery.locales', 'Locales')}</div>\n <div className=\"flex flex-wrap gap-2\">\n {(discovery?.locales ?? []).map((locale) => (\n <span key={locale.code} className=\"rounded border px-2 py-1 text-xs\">\n {locale.code}\n </span>\n ))}\n </div>\n </div>\n <div>\n <div className=\"mb-2 text-xs font-medium uppercase text-muted-foreground\">{t('sync_akeneo.discovery.channels', 'Channels')}</div>\n <div className=\"flex flex-wrap gap-2\">\n {(discovery?.channels ?? []).map((channel) => (\n <span key={channel.code} className=\"rounded border px-2 py-1 text-xs\">\n {channel.code}\n </span>\n ))}\n </div>\n </div>\n <div>\n <div className=\"mb-2 text-xs font-medium uppercase text-muted-foreground\">{t('sync_akeneo.discovery.families', 'Families')}</div>\n <div className=\"flex flex-wrap gap-2\">\n {(discovery?.families ?? []).slice(0, 20).map((family) => (\n <span key={family.code} className=\"rounded border px-2 py-1 text-xs\">\n {family.code}\n </span>\n ))}\n </div>\n </div>\n <div>\n <div className=\"mb-2 text-xs font-medium uppercase text-muted-foreground\">{t('sync_akeneo.discovery.localChannels', 'Open Mercato channels')}</div>\n <div className=\"flex flex-wrap gap-2\">\n {(discovery?.localChannels ?? []).map((channel) => (\n <span key={channel.code} className=\"rounded border px-2 py-1 text-xs\">\n {channel.code}\n </span>\n ))}\n </div>\n </div>\n <div>\n <div className=\"mb-2 text-xs font-medium uppercase text-muted-foreground\">{t('sync_akeneo.discovery.priceKinds', 'Catalog price kinds')}</div>\n <div className=\"flex flex-wrap gap-2\">\n {(discovery?.priceKinds ?? []).map((priceKind) => (\n <span key={priceKind.code} className=\"rounded border px-2 py-1 text-xs\">\n {priceKind.code}\n </span>\n ))}\n </div>\n </div>\n <div>\n <div className=\"mb-2 text-xs font-medium uppercase text-muted-foreground\">{t('sync_akeneo.discovery.attributes', 'Attributes')}</div>\n <div className=\"max-h-80 space-y-2 overflow-auto pr-1\">\n {(discovery?.attributes ?? []).map((attribute) => (\n <div key={attribute.code} className=\"rounded border p-2 text-xs\">\n <div className=\"font-medium\">{attribute.code}</div>\n <div className=\"text-muted-foreground\">\n {attribute.type}\n {attribute.localizable ? ' | localizable' : ''}\n {attribute.scopable ? ' | channel-scoped' : ''}\n {attribute.group ? ` | group:${attribute.group}` : ''}\n {attribute.metricFamily ? ` | metric:${attribute.metricFamily}` : ''}\n </div>\n </div>\n ))}\n </div>\n </div>\n </div>\n </div>\n </div>\n\n <datalist id=\"akeneo-attributes\">\n {attributeCodes.map((code) => (\n <option key={code} value={code} />\n ))}\n </datalist>\n <datalist id=\"akeneo-locales\">\n {(discovery?.locales ?? []).map((locale) => (\n <option key={locale.code} value={locale.code} />\n ))}\n </datalist>\n <datalist id=\"akeneo-channels\">\n {(discovery?.channels ?? []).map((channel) => (\n <option key={channel.code} value={channel.code} />\n ))}\n </datalist>\n <datalist id=\"akeneo-families\">\n {(discovery?.families ?? []).map((family) => (\n <option key={family.code} value={family.code} />\n ))}\n </datalist>\n </div>\n\n <Dialog open={customFieldDialogOpen} onOpenChange={setCustomFieldDialogOpen}>\n <DialogContent\n className=\"sm:max-w-5xl\"\n onKeyDown={(event) => {\n if ((event.metaKey || event.ctrlKey) && event.key === 'Enter') {\n event.preventDefault()\n applyCustomFieldEditor()\n }\n }}\n >\n <DialogHeader>\n <DialogTitle>{t('sync_akeneo.customFields.dialog.title', 'Akeneo custom field editor')}</DialogTitle>\n <DialogDescription>\n {t('sync_akeneo.customFields.dialog.description', 'Edit structured custom-field mappings, review which local field definitions already exist, generate missing ones immediately, or mark specific Akeneo attributes to be skipped during import.')}\n </DialogDescription>\n </DialogHeader>\n\n <div className=\"space-y-4\">\n <div className=\"flex flex-wrap items-center gap-2\">\n <span className=\"rounded border px-2 py-1 text-xs\">\n {t('sync_akeneo.customFields.dialog.summary.total', `${customFieldEditorRows.length} mapping rows`)}\n </span>\n <span className={`rounded border px-2 py-1 text-xs ${dialogMissingCustomFieldCount > 0 ? 'border-amber-300 text-amber-700' : ''}`}>\n {dialogMissingCustomFieldCount > 0\n ? t('sync_akeneo.customFields.dialog.summary.missing', `${dialogMissingCustomFieldCount} rows missing local fields`)\n : t('sync_akeneo.customFields.dialog.summary.ready', 'Everything in this mapping already exists locally')}\n </span>\n </div>\n\n <div className=\"overflow-x-auto rounded-lg border\">\n <table className=\"w-full min-w-[780px] text-sm\">\n <thead className=\"bg-muted/50 text-left\">\n <tr>\n <th className=\"px-3 py-2 font-medium\">{t('sync_akeneo.customFields.columns.attribute', 'Akeneo attribute')}</th>\n <th className=\"px-3 py-2 font-medium\">{t('sync_akeneo.customFields.columns.skip', 'Skip import')}</th>\n <th className=\"px-3 py-2 font-medium\">{t('sync_akeneo.customFields.columns.target', 'Target')}</th>\n <th className=\"px-3 py-2 font-medium\">{t('sync_akeneo.customFields.columns.key', 'Field key')}</th>\n <th className=\"px-3 py-2 font-medium\">{t('sync_akeneo.customFields.columns.kind', 'Kind')}</th>\n <th className=\"px-3 py-2 font-medium\">{t('sync_akeneo.customFields.columns.status', 'Status')}</th>\n <th className=\"px-3 py-2 font-medium\">{t('sync_akeneo.customFields.columns.actions', 'Actions')}</th>\n </tr>\n </thead>\n <tbody>\n {customFieldEditorRows.length > 0 ? customFieldEditorRows.map((row, index) => {\n const exists = row.target === 'product'\n ? productFieldKeys.has(row.fieldKey.trim())\n : variantFieldKeys.has(row.fieldKey.trim())\n return (\n <tr key={`${row.attributeCode}:${row.fieldKey}:${index}`} className={`border-t ${row.skip ? 'opacity-70' : ''}`}>\n <td className=\"px-3 py-2\">\n <Input\n list=\"akeneo-attributes\"\n value={row.attributeCode}\n onChange={(event) => {\n const nextRows = [...customFieldEditorRows]\n nextRows[index] = { ...row, attributeCode: event.target.value }\n setCustomFieldEditorRows(nextRows)\n }}\n disabled={isLoading || isSaving || isCreatingCustomFields}\n />\n </td>\n <td className=\"px-3 py-2\">\n <label className=\"flex items-center justify-center\">\n <input\n type=\"checkbox\"\n checked={row.skip}\n onChange={(event) => {\n const nextRows = [...customFieldEditorRows]\n nextRows[index] = {\n ...row,\n skip: event.target.checked,\n fieldKey: row.fieldKey || normalizeFieldKey(row.attributeCode),\n }\n setCustomFieldEditorRows(nextRows)\n }}\n disabled={isLoading || isSaving || isCreatingCustomFields}\n />\n </label>\n </td>\n <td className=\"px-3 py-2\">\n <select\n className=\"flex h-10 w-full rounded-md border border-input bg-background px-3 py-2\"\n value={row.target}\n onChange={(event) => {\n const nextRows = [...customFieldEditorRows]\n nextRows[index] = { ...row, target: event.target.value === 'variant' ? 'variant' : 'product' }\n setCustomFieldEditorRows(nextRows)\n }}\n disabled={isLoading || isSaving || isCreatingCustomFields}\n >\n <option value=\"product\">{t('sync_akeneo.customFields.targets.product', 'Product')}</option>\n <option value=\"variant\">{t('sync_akeneo.customFields.targets.variant', 'Variant')}</option>\n </select>\n </td>\n <td className=\"px-3 py-2\">\n <Input\n value={row.fieldKey}\n onChange={(event) => {\n const nextRows = [...customFieldEditorRows]\n nextRows[index] = { ...row, fieldKey: normalizeFieldKey(event.target.value) }\n setCustomFieldEditorRows(nextRows)\n }}\n disabled={isLoading || isSaving || isCreatingCustomFields}\n />\n </td>\n <td className=\"px-3 py-2\">\n <select\n className=\"flex h-10 w-full rounded-md border border-input bg-background px-3 py-2\"\n value={row.kind}\n onChange={(event) => {\n const nextRows = [...customFieldEditorRows]\n nextRows[index] = {\n ...row,\n kind: event.target.value === ''\n ? ''\n : event.target.value as CustomFieldRow['kind'],\n }\n setCustomFieldEditorRows(nextRows)\n }}\n disabled={isLoading || isSaving || isCreatingCustomFields}\n >\n <option value=\"\">{t('sync_akeneo.customFields.kinds.auto', 'Auto')}</option>\n <option value=\"text\">text</option>\n <option value=\"multiline\">multiline</option>\n <option value=\"integer\">integer</option>\n <option value=\"float\">float</option>\n <option value=\"boolean\">boolean</option>\n <option value=\"select\">select</option>\n </select>\n </td>\n <td className=\"px-3 py-2\">\n {row.skip ? renderSkippedCustomFieldBadge() : renderCustomFieldStatusBadge(exists)}\n </td>\n <td className=\"px-3 py-2\">\n <Button\n type=\"button\"\n variant=\"ghost\"\n onClick={() => {\n const nextRows = customFieldEditorRows.filter((_, rowIndex) => rowIndex !== index)\n setCustomFieldEditorRows(nextRows)\n }}\n disabled={isLoading || isSaving || isCreatingCustomFields}\n >\n <Trash2 className=\"mr-2 h-4 w-4\" />\n {t('sync_akeneo.customFields.actions.remove', 'Remove')}\n </Button>\n </td>\n </tr>\n )\n }) : (\n <tr>\n <td colSpan={7} className=\"px-3 py-6 text-center text-sm text-muted-foreground\">\n {t('sync_akeneo.customFields.empty', 'No Akeneo custom fields are mapped yet. Use the suggestions below or add a row manually.')}\n </td>\n </tr>\n )}\n </tbody>\n </table>\n </div>\n\n <div className=\"flex flex-wrap gap-2\">\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={() => setCustomFieldEditorRows([\n ...customFieldEditorRows,\n { attributeCode: '', target: 'product', fieldKey: '', kind: '', skip: false },\n ])}\n disabled={isLoading || isSaving || isCreatingCustomFields}\n >\n <Plus className=\"mr-2 h-4 w-4\" />\n {t('sync_akeneo.customFields.actions.add', 'Add row')}\n </Button>\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={() => void createMissingCustomFields(customFieldEditorRows)}\n disabled={isLoading || isSaving || isCreatingCustomFields || customFieldEditorRows.length === 0}\n >\n {isCreatingCustomFields ? <RefreshCw className=\"mr-2 h-4 w-4 animate-spin\" /> : <Sparkles className=\"mr-2 h-4 w-4\" />}\n {isCreatingCustomFields\n ? t('sync_akeneo.customFields.actions.creating', 'Creating...')\n : t('sync_akeneo.customFields.actions.createMissing', 'Pre-create missing fields now')}\n </Button>\n </div>\n\n <div className=\"rounded-lg border p-4\">\n <div className=\"mb-3\">\n <h4 className=\"text-sm font-medium\">{t('sync_akeneo.customFields.suggestions.title', 'Suggested Akeneo attributes')}</h4>\n <p className=\"text-xs text-muted-foreground\">\n {t('sync_akeneo.customFields.suggestions.help', 'Quick-add discovered attributes that are not yet part of the Akeneo custom-field mapping.')}\n </p>\n </div>\n <div className=\"flex flex-wrap gap-2\">\n {suggestedCustomFieldAttributes.map((attribute) => (\n <Button\n key={attribute.code}\n type=\"button\"\n variant=\"outline\"\n onClick={() => {\n setCustomFieldEditorRows([\n ...customFieldEditorRows,\n {\n attributeCode: attribute.code,\n target: 'product',\n fieldKey: normalizeFieldKey(`akeneo_${attribute.code}`),\n kind: inferCustomFieldKind(attribute.type),\n skip: false,\n },\n ])\n }}\n disabled={isLoading || isSaving || isCreatingCustomFields}\n >\n <Plus className=\"mr-2 h-4 w-4\" />\n {attribute.code}\n </Button>\n ))}\n </div>\n </div>\n </div>\n\n <DialogFooter>\n <Button\n type=\"button\"\n onClick={() => applyCustomFieldEditor()}\n disabled={isCreatingCustomFields}\n >\n <Save className=\"mr-2 h-4 w-4\" />\n {t('sync_akeneo.customFields.dialog.apply', 'Apply')}\n </Button>\n <Button type=\"button\" variant=\"outline\" onClick={() => setCustomFieldDialogOpen(false)} disabled={isCreatingCustomFields}>\n <X className=\"mr-2 h-4 w-4\" />\n {t('sync_akeneo.customFields.dialog.close', 'Close')}\n </Button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n {ConfirmDialogElement}\n </div>\n )\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport type { InjectionWidgetComponentProps } from '@open-mercato/shared/modules/widgets/injection'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { useAppEvent } from '@open-mercato/ui/backend/injection/useAppEvent'\nimport { apiCall } from '@open-mercato/ui/backend/utils/apiCall'\nimport { useConfirmDialog } from '@open-mercato/ui/backend/confirm-dialog'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { NextStepCallout } from '@open-mercato/ui/backend/NextStepCallout'\nimport { Alert, AlertDescription, AlertTitle } from '@open-mercato/ui/primitives/alert'\nimport { Badge } from '@open-mercato/ui/primitives/badge'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { Progress } from '@open-mercato/ui/primitives/progress'\nimport {\n Dialog,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n} from '@open-mercato/ui/primitives/dialog'\nimport { Input } from '@open-mercato/ui/primitives/input'\nimport { Label } from '@open-mercato/ui/primitives/label'\nimport { AlertCircle, CheckCircle2, PencilLine, Plus, RefreshCw, Save, Sparkles, Trash2, Wand2, X } from 'lucide-react'\nimport { buildAkeneoFieldsetCode, buildDefaultAkeneoMapping, buildProductFieldMappings, dedupeStrings, normalizeAkeneoMapping, type AkeneoReconciliationSettings } from '../../../lib/shared'\nimport { inferAkeneoProductMapping } from '../../../lib/inference'\nimport type { AkeneoDiscoveryResponse } from '../../../data/validators'\n\ntype MappingRecordResponse = {\n items?: Array<{\n id: string\n mapping: Record<string, unknown>\n }>\n}\n\ntype CustomFieldStatusResponse = {\n ok: boolean\n productKeys: string[]\n variantKeys: string[]\n createdKeys?: string[]\n message?: string\n}\n\ntype DeleteImportedProductsResponse = {\n ok: boolean\n progressJobId: string | null\n message: string\n}\n\ntype DeleteImportedProductsJobResponse = {\n id: string\n status: 'pending' | 'running' | 'completed' | 'failed' | 'cancelled'\n progressPercent: number\n processedCount: number\n totalCount?: number | null\n resultSummary?: Record<string, unknown> | null\n errorMessage?: string | null\n}\n\ntype FirstImportSequenceResponse = {\n ok: boolean\n hasCompletedProductImport: boolean\n sequence: {\n progressJobId: string\n status: 'pending' | 'running' | 'completed' | 'failed' | 'cancelled'\n currentStep: FirstImportStepKey | null\n currentRunId: string | null\n currentRunProgressJobId: string | null\n currentRunStatus: 'pending' | 'running' | 'completed' | 'failed' | 'cancelled' | null\n progressPercent: number | null\n processedCount: number | null\n totalCount: number | null\n errorMessage: string | null\n } | null\n}\n\ntype FirstImportStepKey = 'categories' | 'attributes' | 'products'\n\ntype ProgressEventPayload = {\n jobId?: string\n jobType?: string\n status?: string\n progressPercent?: number\n processedCount?: number\n totalCount?: number | null\n meta?: Record<string, unknown> | null\n errorMessage?: string | null\n resultSummary?: Record<string, unknown> | null\n}\n\ntype FirstImportProgressState = {\n phase: 'idle' | 'running' | 'completed' | 'failed'\n progressJobId: string | null\n step: FirstImportStepKey | null\n runId: string | null\n runProgressJobId: string | null\n progressPercent: number | null\n processedCount: number | null\n totalCount: number | null\n errorMessage: string | null\n}\n\ntype CustomFieldRow = {\n attributeCode: string\n target: 'product' | 'variant'\n fieldKey: string\n kind: '' | 'text' | 'multiline' | 'integer' | 'float' | 'boolean' | 'select'\n skip: boolean\n}\n\ntype PriceMappingRow = {\n attributeCode: string\n priceKindCode: string\n akeneoChannel: string\n localChannelCode: string\n}\n\ntype MediaMappingRow = {\n attributeCode: string\n target: 'product' | 'variant'\n kind: 'image' | 'file'\n}\n\ntype FieldsetMappingRow = {\n sourceType: 'family' | 'familyVariant'\n sourceCode: string\n target: 'product' | 'variant'\n fieldsetCode: string\n fieldsetLabel: string\n description: string\n}\n\ntype AkeneoWidgetContext = {\n state?: {\n isEnabled?: boolean\n } | null\n}\n\ntype AkeneoWidgetData = {\n hasCredentials?: boolean\n}\n\ntype FormState = {\n productLocale: string\n productChannel: string\n productChannels: string[]\n importAllProductChannels: boolean\n categoryLocale: string\n includeTextAttributes: boolean\n includeNumericAttributes: boolean\n familyCodeFilter: string\n customFieldMappings: string\n priceMappings: string\n mediaMappings: string\n fieldsetMappings: string\n createMissingChannels: boolean\n syncAssociations: boolean\n reconciliation: AkeneoReconciliationSettings\n fieldMap: {\n title: string\n subtitle: string\n description: string\n sku: string\n barcode: string\n weight: string\n variantName: string\n }\n}\n\nfunction readDeleteImportedProductsSummaryMessage(summary: Record<string, unknown> | null | undefined): string | null {\n if (!summary || typeof summary !== 'object') return null\n const message = summary.message\n if (typeof message !== 'string') return null\n const trimmed = message.trim()\n return trimmed.length > 0 ? trimmed : null\n}\n\nfunction readProgressMetaString(meta: Record<string, unknown> | null | undefined, key: string): string | null {\n if (!meta || typeof meta[key] !== 'string') return null\n const value = String(meta[key]).trim()\n return value.length > 0 ? value : null\n}\n\nfunction readProgressMetaNumber(meta: Record<string, unknown> | null | undefined, key: string): number | null {\n const value = meta?.[key]\n return typeof value === 'number' && Number.isFinite(value) ? value : null\n}\n\nconst PRODUCT_FIELD_KEYS: Array<{\n key: keyof FormState['fieldMap']\n label: string\n help: string\n}> = [\n { key: 'title', label: 'Title attribute', help: 'Used for the Open Mercato product title.' },\n { key: 'subtitle', label: 'Subtitle attribute', help: 'Optional secondary title field.' },\n { key: 'description', label: 'Description attribute', help: 'Used for the product description.' },\n { key: 'sku', label: 'SKU attribute', help: 'Used for both simple-product and variant SKU matching.' },\n { key: 'barcode', label: 'Barcode attribute', help: 'Optional barcode/EAN source.' },\n { key: 'weight', label: 'Weight attribute', help: 'Metric attribute used for product and default-variant weight.' },\n { key: 'variantName', label: 'Variant label attribute', help: 'Fallback label for generated variant names.' },\n]\n\nfunction buildInitialState(): FormState {\n const products = buildDefaultAkeneoMapping('products')\n const categories = buildDefaultAkeneoMapping('categories')\n const attributes = buildDefaultAkeneoMapping('attributes')\n const productSettings = products.settings?.products\n return {\n productLocale: productSettings?.locale ?? 'en_US',\n productChannel: productSettings?.channel ?? '',\n productChannels: productSettings?.channels ?? [],\n importAllProductChannels: productSettings?.importAllChannels ?? true,\n categoryLocale: categories.settings?.categories?.locale ?? 'en_US',\n includeTextAttributes: attributes.settings?.attributes?.includeTextAttributes ?? true,\n includeNumericAttributes: attributes.settings?.attributes?.includeNumericAttributes ?? true,\n familyCodeFilter: '',\n customFieldMappings: '',\n priceMappings: serializePriceMappingRows(\n (productSettings?.priceMappings ?? []).map((entry) => ({\n attributeCode: entry.attributeCode,\n priceKindCode: entry.priceKindCode,\n akeneoChannel: entry.akeneoChannel ?? '',\n localChannelCode: entry.localChannelCode,\n })),\n ),\n mediaMappings: serializeMediaMappingRows(\n (productSettings?.mediaMappings ?? []).map((entry) => ({\n attributeCode: entry.attributeCode,\n target: entry.target,\n kind: entry.kind,\n })),\n ),\n fieldsetMappings: serializeFieldsetMappingRows(\n (productSettings?.fieldsetMappings ?? []).map((entry) => ({\n sourceType: entry.sourceType,\n sourceCode: entry.sourceCode,\n target: entry.target,\n fieldsetCode: entry.fieldsetCode,\n fieldsetLabel: entry.fieldsetLabel,\n description: entry.description ?? '',\n })),\n ),\n createMissingChannels: productSettings?.createMissingChannels ?? true,\n syncAssociations: productSettings?.syncAssociations ?? true,\n reconciliation: productSettings?.reconciliation ?? {\n deactivateMissingCategories: true,\n deactivateMissingProducts: true,\n deactivateMissingAttributes: true,\n deleteMissingOffers: true,\n deleteMissingPrices: true,\n deleteMissingMedia: true,\n deleteMissingAttachments: true,\n },\n fieldMap: {\n title: productSettings?.fieldMap.title ?? 'name',\n subtitle: productSettings?.fieldMap.subtitle ?? 'subtitle',\n description: productSettings?.fieldMap.description ?? 'description',\n sku: productSettings?.fieldMap.sku ?? 'sku',\n barcode: productSettings?.fieldMap.barcode ?? 'ean',\n weight: productSettings?.fieldMap.weight ?? 'weight',\n variantName: productSettings?.fieldMap.variantName ?? 'name',\n },\n }\n}\n\nfunction mergeMappingsIntoState(\n state: FormState,\n productsMapping: Record<string, unknown> | undefined,\n categoriesMapping: Record<string, unknown> | undefined,\n attributesMapping: Record<string, unknown> | undefined,\n): FormState {\n const normalizedProducts = normalizeAkeneoMapping('products', productsMapping ?? null)\n const normalizedCategories = normalizeAkeneoMapping('categories', categoriesMapping ?? null)\n const normalizedAttributes = normalizeAkeneoMapping('attributes', attributesMapping ?? null)\n return {\n ...state,\n productLocale: normalizedProducts.settings?.products?.locale ?? state.productLocale,\n productChannel: normalizedProducts.settings?.products?.channel ?? '',\n productChannels: normalizedProducts.settings?.products?.channels ?? state.productChannels,\n importAllProductChannels: normalizedProducts.settings?.products?.importAllChannels ?? state.importAllProductChannels,\n categoryLocale: normalizedCategories.settings?.categories?.locale ?? state.categoryLocale,\n includeTextAttributes: normalizedAttributes.settings?.attributes?.includeTextAttributes ?? state.includeTextAttributes,\n includeNumericAttributes: normalizedAttributes.settings?.attributes?.includeNumericAttributes ?? state.includeNumericAttributes,\n familyCodeFilter: (normalizedAttributes.settings?.attributes?.familyCodeFilter ?? []).join(', '),\n customFieldMappings: (normalizedProducts.settings?.products?.customFieldMappings ?? [])\n .map((entry) => `${entry.attributeCode},${entry.target},${entry.fieldKey},${entry.kind ?? ''},${entry.skip === true ? 'skip' : ''}`)\n .join('\\n'),\n priceMappings: (normalizedProducts.settings?.products?.priceMappings ?? [])\n .map((entry) => `${entry.attributeCode},${entry.priceKindCode},${entry.akeneoChannel ?? ''},${entry.localChannelCode}`)\n .join('\\n'),\n mediaMappings: (normalizedProducts.settings?.products?.mediaMappings ?? [])\n .map((entry) => `${entry.attributeCode},${entry.target},${entry.kind}`)\n .join('\\n'),\n fieldsetMappings: (normalizedProducts.settings?.products?.fieldsetMappings ?? [])\n .map((entry) => `${entry.sourceType},${entry.sourceCode},${entry.target},${entry.fieldsetCode},${entry.fieldsetLabel}${entry.description ? `,${entry.description}` : ''}`)\n .join('\\n'),\n createMissingChannels: normalizedProducts.settings?.products?.createMissingChannels ?? state.createMissingChannels,\n syncAssociations: normalizedProducts.settings?.products?.syncAssociations ?? state.syncAssociations,\n reconciliation: normalizedProducts.settings?.products?.reconciliation ?? state.reconciliation,\n fieldMap: {\n title: normalizedProducts.settings?.products?.fieldMap.title ?? state.fieldMap.title,\n subtitle: normalizedProducts.settings?.products?.fieldMap.subtitle ?? state.fieldMap.subtitle,\n description: normalizedProducts.settings?.products?.fieldMap.description ?? state.fieldMap.description,\n sku: normalizedProducts.settings?.products?.fieldMap.sku ?? state.fieldMap.sku,\n barcode: normalizedProducts.settings?.products?.fieldMap.barcode ?? state.fieldMap.barcode,\n weight: normalizedProducts.settings?.products?.fieldMap.weight ?? state.fieldMap.weight,\n variantName: normalizedProducts.settings?.products?.fieldMap.variantName ?? state.fieldMap.variantName,\n },\n }\n}\n\nfunction parseRows(value: string): string[][] {\n return value\n .split('\\n')\n .map((row) => row.trim())\n .filter((row) => row.length > 0)\n .map((row) => row.split(',').map((cell) => cell.trim()))\n}\n\nfunction parseCustomFieldRows(value: string): CustomFieldRow[] {\n return parseRows(value)\n .map(([attributeCode, target, fieldKey, kind, skipFlag]) => {\n const normalizedTarget: CustomFieldRow['target'] = target === 'variant' ? 'variant' : 'product'\n const normalizedKind: CustomFieldRow['kind'] = kind === 'text'\n || kind === 'multiline'\n || kind === 'integer'\n || kind === 'float'\n || kind === 'boolean'\n || kind === 'select'\n ? kind\n : ''\n return {\n attributeCode,\n target: normalizedTarget,\n fieldKey,\n kind: normalizedKind,\n skip: skipFlag === 'skip' || skipFlag === 'true',\n }\n })\n .filter((row) => row.attributeCode.length > 0 || row.fieldKey.length > 0)\n}\n\nfunction serializeCustomFieldRows(rows: CustomFieldRow[]): string {\n return rows\n .filter((row) => row.attributeCode.trim().length > 0 && (row.fieldKey.trim().length > 0 || row.skip))\n .map((row) => [\n row.attributeCode.trim(),\n row.target,\n row.fieldKey.trim() || normalizeFieldKey(row.attributeCode),\n row.kind,\n row.skip ? 'skip' : '',\n ].filter((cell, index) => index < 4 || cell.length > 0).join(','))\n .join('\\n')\n}\n\nfunction mergeCustomFieldRows(existingRows: CustomFieldRow[], discoveredRows: CustomFieldRow[]): CustomFieldRow[] {\n const merged = [...existingRows]\n const existingAttributeCodes = new Set(\n existingRows.map((row) => row.attributeCode.trim()).filter((value) => value.length > 0),\n )\n for (const row of discoveredRows) {\n const attributeCode = row.attributeCode.trim()\n if (!attributeCode || existingAttributeCodes.has(attributeCode)) continue\n merged.push(row)\n existingAttributeCodes.add(attributeCode)\n }\n return merged\n}\n\nfunction parsePriceMappingRows(value: string): PriceMappingRow[] {\n return parseRows(value)\n .map(([attributeCode, priceKindCode, akeneoChannel, localChannelCode]) => ({\n attributeCode,\n priceKindCode,\n akeneoChannel: akeneoChannel ?? '',\n localChannelCode,\n }))\n}\n\nfunction serializePriceMappingRows(rows: PriceMappingRow[]): string {\n return rows\n .map((row) => [\n row.attributeCode.trim(),\n row.priceKindCode.trim(),\n row.akeneoChannel.trim(),\n row.localChannelCode.trim(),\n ].join(','))\n .join('\\n')\n}\n\nfunction parseMediaMappingRows(value: string): MediaMappingRow[] {\n return parseRows(value)\n .map(([attributeCode, target, kind]) => ({\n attributeCode,\n target: target === 'variant' ? 'variant' : 'product',\n kind: kind === 'file' ? 'file' : 'image',\n }))\n}\n\nfunction serializeMediaMappingRows(rows: MediaMappingRow[]): string {\n return rows\n .map((row) => `${row.attributeCode.trim()},${row.target},${row.kind}`)\n .join('\\n')\n}\n\nfunction parseFieldsetMappingRows(value: string): FieldsetMappingRow[] {\n return parseRows(value)\n .map(([sourceType, sourceCode, target, fieldsetCode, fieldsetLabel, ...descriptionParts]): FieldsetMappingRow => ({\n sourceType: sourceType === 'familyVariant' ? 'familyVariant' : 'family',\n sourceCode: sourceCode ?? '',\n target: target === 'variant' ? 'variant' : 'product',\n fieldsetCode: fieldsetCode ?? '',\n fieldsetLabel: fieldsetLabel ?? '',\n description: descriptionParts.join(','),\n }))\n .filter((row) => row.sourceCode.trim().length > 0 || row.fieldsetCode.trim().length > 0 || row.fieldsetLabel.trim().length > 0)\n}\n\nfunction serializeFieldsetMappingRows(rows: FieldsetMappingRow[]): string {\n return rows\n .filter((row) => row.sourceCode.trim().length > 0 && row.fieldsetCode.trim().length > 0 && row.fieldsetLabel.trim().length > 0)\n .map((row) => [\n row.sourceType,\n row.sourceCode.trim(),\n row.target,\n row.fieldsetCode.trim(),\n row.fieldsetLabel.trim(),\n row.description.trim(),\n ].filter((cell, index) => index < 5 || cell.length > 0).join(','))\n .join('\\n')\n}\n\nfunction normalizeFieldKey(value: string): string {\n return value\n .trim()\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '_')\n .replace(/^_+|_+$/g, '')\n .slice(0, 100)\n}\n\nfunction inferCustomFieldKind(attributeType: string): CustomFieldRow['kind'] {\n if (attributeType === 'pim_catalog_boolean') return 'boolean'\n if (attributeType === 'pim_catalog_number') return 'float'\n if (attributeType === 'pim_catalog_metric') return 'float'\n if (attributeType === 'pim_catalog_textarea') return 'multiline'\n if (\n attributeType === 'pim_catalog_simpleselect'\n || attributeType === 'pim_catalog_multiselect'\n || attributeType === 'akeneo_reference_entity'\n || attributeType === 'akeneo_reference_entity_collection'\n ) {\n return 'select'\n }\n return 'text'\n}\n\nfunction inferPriceKindCode(attributeCode: string): string {\n const normalized = attributeCode.trim().toLowerCase()\n return normalized.includes('sale')\n || normalized.includes('promo')\n || normalized.includes('special')\n || normalized.includes('discount')\n ? 'sale'\n : 'regular'\n}\n\nfunction buildSelectValues(values: Array<string | null | undefined>, currentValue?: string | null): string[] {\n return dedupeStrings([\n ...values,\n currentValue ?? null,\n ])\n}\n\nfunction buildDiscoveredFieldsetMappings(discovery: AkeneoDiscoveryResponse): FieldsetMappingRow[] {\n const familyRows = (discovery.families ?? []).flatMap((family) => {\n const productFieldsetCode = buildAkeneoFieldsetCode('product', family.code)\n return productFieldsetCode ? [{\n sourceType: 'family' as const,\n sourceCode: family.code,\n target: 'product' as const,\n fieldsetCode: productFieldsetCode,\n fieldsetLabel: family.label || family.code,\n description: `Akeneo family ${family.code}`,\n }] : []\n })\n\n const familyVariantRows = (discovery.familyVariants ?? []).flatMap((familyVariant) => {\n const variantFieldsetCode = buildAkeneoFieldsetCode('variant', familyVariant.code)\n return variantFieldsetCode ? [{\n sourceType: 'familyVariant' as const,\n sourceCode: familyVariant.code,\n target: 'variant' as const,\n fieldsetCode: variantFieldsetCode,\n fieldsetLabel: familyVariant.label || familyVariant.code,\n description: `Akeneo family variant ${familyVariant.code} from family ${familyVariant.familyCode}`,\n }] : []\n })\n\n return [...familyRows, ...familyVariantRows]\n}\n\nfunction applyDiscoveryDefaults(\n state: FormState,\n discovery: AkeneoDiscoveryResponse | null,\n): FormState {\n if (!discovery?.ok) return state\n\n const discoveredFamilyVariant = (discovery.familyVariants ?? []).length > 0\n ? {\n code: '__discovery__',\n variant_attribute_sets: (discovery.familyVariants ?? []).map((familyVariant, index) => ({\n level: index + 1,\n axes: familyVariant.axes,\n attributes: familyVariant.attributes,\n })),\n }\n : null\n\n const inferred = inferAkeneoProductMapping({\n attributes: (discovery.attributes ?? []).map((attribute) => ({\n code: attribute.code,\n type: attribute.type,\n labels: attribute.label ? { inferred: attribute.label } : undefined,\n localizable: attribute.localizable,\n scopable: attribute.scopable,\n group: attribute.group,\n metric_family: attribute.metricFamily,\n })),\n family: null,\n familyVariant: discoveredFamilyVariant,\n fieldMap: state.fieldMap,\n explicitCustomFieldMappings: parseCustomFieldRows(state.customFieldMappings).map((row) => ({\n attributeCode: row.attributeCode.trim(),\n target: row.target,\n fieldKey: row.fieldKey.trim() || normalizeFieldKey(row.attributeCode),\n kind: row.kind || null,\n skip: row.skip,\n })),\n explicitMediaMappings: parseMediaMappingRows(state.mediaMappings).map((row) => ({\n attributeCode: row.attributeCode.trim(),\n target: row.target,\n kind: row.kind,\n })),\n })\n\n const hasCustomFields = parseCustomFieldRows(state.customFieldMappings).length > 0\n const hasMediaMappings = parseMediaMappingRows(state.mediaMappings).length > 0\n const hasPriceMappings = parsePriceMappingRows(state.priceMappings).some((row) => row.attributeCode.trim().length > 0)\n const hasFieldsetMappings = parseFieldsetMappingRows(state.fieldsetMappings).length > 0\n const currentCustomFieldRows = parseCustomFieldRows(state.customFieldMappings)\n const discoveredCustomFieldRows = inferred.autoCustomFieldMappings.map((mapping) => ({\n attributeCode: mapping.attributeCode,\n target: mapping.target,\n fieldKey: mapping.fieldKey,\n kind: mapping.kind ?? '',\n skip: false,\n }) satisfies CustomFieldRow)\n const preferredLocalChannel = discovery.localChannels.find((channel) => ['web', 'online', 'ecommerce', 'default'].includes(channel.code.trim().toLowerCase()))\n ?? discovery.localChannels[0]\n ?? null\n const preferredAkeneoChannel = discovery.channels[0]?.code ?? ''\n const preferredLocale = discovery.locales.find((locale) => locale.enabled)?.code\n ?? discovery.locales[0]?.code\n ?? state.productLocale\n\n return {\n ...state,\n productLocale: state.productLocale,\n categoryLocale: state.categoryLocale,\n productChannel: state.productChannel || preferredAkeneoChannel,\n productChannels: state.productChannels.length > 0 ? state.productChannels : (preferredAkeneoChannel ? [preferredAkeneoChannel] : []),\n importAllProductChannels: state.importAllProductChannels,\n fieldMap: inferred.fieldMap,\n customFieldMappings: serializeCustomFieldRows(\n mergeCustomFieldRows(currentCustomFieldRows, discoveredCustomFieldRows),\n ),\n mediaMappings: hasMediaMappings\n ? state.mediaMappings\n : serializeMediaMappingRows(\n inferred.autoMediaMappings.map((mapping) => ({\n attributeCode: mapping.attributeCode,\n target: mapping.target,\n kind: mapping.kind,\n })),\n ),\n fieldsetMappings: hasFieldsetMappings\n ? state.fieldsetMappings\n : serializeFieldsetMappingRows(buildDiscoveredFieldsetMappings(discovery)),\n priceMappings: hasPriceMappings || !preferredLocalChannel\n ? state.priceMappings\n : serializePriceMappingRows(\n inferred.autoPriceAttributeCodes.map((attributeCode) => ({\n attributeCode,\n priceKindCode: inferPriceKindCode(attributeCode),\n akeneoChannel: preferredAkeneoChannel,\n localChannelCode: preferredLocalChannel.code,\n })),\n ),\n }\n}\n\nconst FIRST_IMPORT_STEPS: Array<{\n entityType: FirstImportStepKey\n fullSync: boolean\n}> = [\n { entityType: 'categories', fullSync: true },\n { entityType: 'attributes', fullSync: true },\n { entityType: 'products', fullSync: true },\n]\n\nexport default function AkeneoConfigWidget({ context, data }: InjectionWidgetComponentProps<AkeneoWidgetContext, AkeneoWidgetData>) {\n const t = useT()\n const { confirm, ConfirmDialogElement } = useConfirmDialog()\n const [state, setState] = React.useState<FormState>(() => buildInitialState())\n const [discovery, setDiscovery] = React.useState<AkeneoDiscoveryResponse | null>(null)\n const [customFieldStatus, setCustomFieldStatus] = React.useState<CustomFieldStatusResponse | null>(null)\n const [customFieldDialogOpen, setCustomFieldDialogOpen] = React.useState(false)\n const [customFieldEditorRows, setCustomFieldEditorRows] = React.useState<CustomFieldRow[]>([])\n const [isCreatingCustomFields, setIsCreatingCustomFields] = React.useState(false)\n const [isLoading, setIsLoading] = React.useState(true)\n const [isSaving, setIsSaving] = React.useState(false)\n const [isStartingDeleteImportedProducts, setIsStartingDeleteImportedProducts] = React.useState(false)\n const [deleteImportedProductsJobId, setDeleteImportedProductsJobId] = React.useState<string | null>(null)\n const [deleteImportedProductsJob, setDeleteImportedProductsJob] = React.useState<DeleteImportedProductsJobResponse | null>(null)\n const [hasCompletedProductImport, setHasCompletedProductImport] = React.useState(false)\n const [firstImportProgress, setFirstImportProgress] = React.useState<FirstImportProgressState>({\n phase: 'idle',\n progressJobId: null,\n step: null,\n runId: null,\n runProgressJobId: null,\n progressPercent: null,\n processedCount: null,\n totalCount: null,\n errorMessage: null,\n })\n const mountedRef = React.useRef(true)\n const firstImportTerminalNoticeRef = React.useRef<string | null>(null)\n\n React.useEffect(() => {\n return () => {\n mountedRef.current = false\n }\n }, [])\n\n const syncFirstImportStatus = React.useCallback((response: FirstImportSequenceResponse | null | undefined) => {\n setHasCompletedProductImport(response?.hasCompletedProductImport === true)\n\n const sequence = response?.sequence\n if (!sequence) {\n setFirstImportProgress({\n phase: 'idle',\n progressJobId: null,\n step: null,\n runId: null,\n runProgressJobId: null,\n progressPercent: null,\n processedCount: null,\n totalCount: null,\n errorMessage: null,\n })\n return\n }\n\n setFirstImportProgress({\n phase: sequence.status === 'failed'\n ? 'failed'\n : sequence.status === 'pending' || sequence.status === 'running'\n ? 'running'\n : sequence.status === 'completed'\n ? 'completed'\n : 'idle',\n progressJobId: sequence.progressJobId,\n step: sequence.currentStep,\n runId: sequence.currentRunId,\n runProgressJobId: sequence.currentRunProgressJobId,\n progressPercent: sequence.progressPercent,\n processedCount: sequence.processedCount,\n totalCount: sequence.totalCount,\n errorMessage: sequence.errorMessage,\n })\n }, [])\n\n const loadFirstImportStatus = React.useCallback(async () => {\n const result = await apiCall<FirstImportSequenceResponse>('/api/sync_akeneo/first-import')\n if (!result.ok) {\n throw new Error(t('sync_akeneo.firstImport.errors.progress', 'Failed to load sync run progress.'))\n }\n syncFirstImportStatus(result.result ?? null)\n }, [syncFirstImportStatus, t])\n\n const buildMappingPayloads = React.useCallback((currentState: FormState) => {\n const customFieldMappings = parseRows(currentState.customFieldMappings)\n .map(([attributeCode, target, fieldKey, kind, skipFlag]) => {\n const normalizedTarget = target === 'variant' ? 'variant' : target === 'product' ? 'product' : null\n const normalizedKind = kind === 'text'\n || kind === 'multiline'\n || kind === 'integer'\n || kind === 'float'\n || kind === 'boolean'\n || kind === 'select'\n ? kind\n : null\n const normalizedFieldKey = fieldKey || normalizeFieldKey(attributeCode)\n if (!attributeCode || !normalizedFieldKey || !normalizedTarget) return null\n return {\n attributeCode,\n target: normalizedTarget,\n fieldKey: normalizedFieldKey,\n kind: normalizedKind,\n skip: skipFlag === 'skip' || skipFlag === 'true',\n } as const\n })\n .filter((entry): entry is NonNullable<typeof entry> => Boolean(entry))\n const priceMappings = parseRows(currentState.priceMappings)\n .map(([attributeCode, priceKindCode, akeneoChannel, localChannelCode]) => {\n if (!attributeCode || !priceKindCode || !localChannelCode) return null\n return {\n attributeCode,\n priceKindCode,\n akeneoChannel: akeneoChannel || null,\n localChannelCode,\n } as const\n })\n .filter((entry): entry is NonNullable<typeof entry> => Boolean(entry))\n const mediaMappings = parseRows(currentState.mediaMappings)\n .map(([attributeCode, target, kind]) => {\n const normalizedTarget = target === 'variant' ? 'variant' : target === 'product' ? 'product' : null\n const normalizedKind = kind === 'image' ? 'image' : kind === 'file' ? 'file' : null\n if (!attributeCode || !normalizedTarget || !normalizedKind) return null\n return {\n attributeCode,\n target: normalizedTarget,\n kind: normalizedKind,\n } as const\n })\n .filter((entry): entry is NonNullable<typeof entry> => Boolean(entry))\n const fieldsetMappings = parseFieldsetMappingRows(currentState.fieldsetMappings)\n .map((row) => {\n if (!row.sourceCode || !row.fieldsetCode || !row.fieldsetLabel) return null\n return {\n sourceType: row.sourceType,\n sourceCode: row.sourceCode.trim(),\n target: row.target,\n fieldsetCode: row.fieldsetCode.trim(),\n fieldsetLabel: row.fieldsetLabel.trim(),\n description: row.description.trim() || null,\n } as const\n })\n .filter((entry): entry is NonNullable<typeof entry> => Boolean(entry))\n\n const productsMapping = {\n ...buildDefaultAkeneoMapping('products'),\n settings: {\n products: {\n locale: currentState.productLocale,\n channel: currentState.productChannel || null,\n channels: currentState.importAllProductChannels ? [] : currentState.productChannels,\n importAllChannels: currentState.importAllProductChannels,\n fieldMap: { ...currentState.fieldMap },\n customFieldMappings,\n priceMappings,\n mediaMappings,\n fieldsetMappings,\n createMissingChannels: currentState.createMissingChannels,\n syncAssociations: currentState.syncAssociations,\n reconciliation: { ...currentState.reconciliation },\n },\n },\n }\n productsMapping.fields = buildProductFieldMappings(productsMapping.settings.products)\n\n const categoriesMapping = {\n ...buildDefaultAkeneoMapping('categories'),\n settings: {\n categories: {\n locale: currentState.categoryLocale,\n },\n },\n }\n\n const attributesMapping = {\n ...buildDefaultAkeneoMapping('attributes'),\n settings: {\n attributes: {\n includeTextAttributes: currentState.includeTextAttributes,\n includeNumericAttributes: currentState.includeNumericAttributes,\n familyCodeFilter: currentState.familyCodeFilter\n .split(',')\n .map((value) => value.trim())\n .filter((value) => value.length > 0),\n },\n },\n }\n\n return { productsMapping, categoriesMapping, attributesMapping }\n }, [])\n\n const persistMappings = React.useCallback(async (\n currentState: FormState,\n options?: { successMessage?: string | null },\n ) => {\n const { productsMapping, categoriesMapping, attributesMapping } = buildMappingPayloads(currentState)\n const saves = await Promise.all([\n apiCall('/api/data_sync/mappings', {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({\n integrationId: 'sync_akeneo',\n entityType: 'products',\n mapping: productsMapping,\n }),\n }),\n apiCall('/api/data_sync/mappings', {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({\n integrationId: 'sync_akeneo',\n entityType: 'categories',\n mapping: categoriesMapping,\n }),\n }),\n apiCall('/api/data_sync/mappings', {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({\n integrationId: 'sync_akeneo',\n entityType: 'attributes',\n mapping: attributesMapping,\n }),\n }),\n ])\n\n if (saves.some((result) => !result.ok)) {\n throw new Error('Failed to save one or more Akeneo mapping records')\n }\n\n if (options?.successMessage) {\n flash(options.successMessage, 'success')\n }\n }, [buildMappingPayloads])\n\n const runFirstFullImport = React.useCallback(async () => {\n firstImportTerminalNoticeRef.current = null\n setFirstImportProgress({\n phase: 'running',\n progressJobId: null,\n step: null,\n runId: null,\n runProgressJobId: null,\n progressPercent: null,\n processedCount: null,\n totalCount: null,\n errorMessage: null,\n })\n\n try {\n await persistMappings(state)\n const result = await apiCall<{ ok?: boolean; progressJobId?: string; error?: string }>('/api/sync_akeneo/first-import', {\n method: 'POST',\n })\n\n if (!result.ok) {\n if (result.status === 409) {\n await loadFirstImportStatus()\n return\n }\n throw new Error(\n (result.result as { error?: string } | null)?.error\n ?? t('sync_akeneo.firstImport.errors.start', 'Failed to start the sync run.'),\n )\n }\n\n setFirstImportProgress((current) => ({\n ...current,\n progressJobId: result.result?.progressJobId ?? current.progressJobId,\n }))\n } catch (error) {\n if (!mountedRef.current) return\n const message = error instanceof Error\n ? error.message\n : t('sync_akeneo.firstImport.errors.generic', 'The first full Akeneo import could not be completed.')\n setFirstImportProgress((current) => ({\n ...current,\n phase: 'failed',\n errorMessage: message,\n }))\n flash(message, 'error')\n }\n }, [loadFirstImportStatus, persistMappings, state, t])\n\n const load = React.useCallback(async (refresh = false) => {\n setIsLoading(true)\n try {\n const [discoveryCall, productsCall, categoriesCall, attributesCall, customFieldsCall, firstImportStatusCall] = await Promise.all([\n apiCall<AkeneoDiscoveryResponse>(`/api/sync_akeneo/discovery${refresh ? '?refresh=true' : ''}`),\n apiCall<MappingRecordResponse>('/api/data_sync/mappings?integrationId=sync_akeneo&entityType=products&page=1&pageSize=1'),\n apiCall<MappingRecordResponse>('/api/data_sync/mappings?integrationId=sync_akeneo&entityType=categories&page=1&pageSize=1'),\n apiCall<MappingRecordResponse>('/api/data_sync/mappings?integrationId=sync_akeneo&entityType=attributes&page=1&pageSize=1'),\n apiCall<CustomFieldStatusResponse>('/api/sync_akeneo/custom-fields'),\n apiCall<FirstImportSequenceResponse>('/api/sync_akeneo/first-import').catch(() => null),\n ])\n\n let nextState = mergeMappingsIntoState(\n buildInitialState(),\n productsCall.result?.items?.[0]?.mapping,\n categoriesCall.result?.items?.[0]?.mapping,\n attributesCall.result?.items?.[0]?.mapping,\n )\n nextState = applyDiscoveryDefaults(nextState, discoveryCall.result ?? null)\n\n const hasSavedMappings = Boolean(productsCall.result?.items?.[0] || categoriesCall.result?.items?.[0] || attributesCall.result?.items?.[0])\n if (!hasSavedMappings && discoveryCall.result?.ok) {\n try {\n await persistMappings(nextState)\n } catch (error) {\n const message = error instanceof Error ? error.message : 'Failed to save discovered Akeneo mappings'\n flash(message, 'error')\n }\n }\n\n setState(nextState)\n setDiscovery(discoveryCall.result ?? null)\n setCustomFieldStatus(customFieldsCall.result ?? null)\n syncFirstImportStatus(firstImportStatusCall?.result ?? null)\n } catch (error) {\n const message = error instanceof Error ? error.message : 'Failed to load Akeneo configuration'\n flash(message, 'error')\n } finally {\n setIsLoading(false)\n }\n }, [persistMappings, syncFirstImportStatus])\n\n const applyFirstImportProgressEvent = React.useCallback((payload: ProgressEventPayload) => {\n const meta = payload.meta && typeof payload.meta === 'object' ? payload.meta : null\n const workflow = readProgressMetaString(meta, 'workflow')\n const integrationId = readProgressMetaString(meta, 'integrationId')\n const isFirstImportEvent = payload.jobType === 'sync_akeneo.first_import'\n || (workflow === 'first_import' && integrationId === 'sync_akeneo')\n\n if (!isFirstImportEvent || !payload.jobId) return\n\n const currentStep = readProgressMetaString(meta, 'currentStep')\n const nextPhase = payload.status === 'failed'\n ? 'failed'\n : payload.status === 'pending' || payload.status === 'running'\n ? 'running'\n : payload.status === 'completed'\n ? 'completed'\n : 'idle'\n\n setFirstImportProgress({\n phase: nextPhase,\n progressJobId: payload.jobId,\n step: currentStep === 'categories' || currentStep === 'attributes' || currentStep === 'products'\n ? currentStep\n : null,\n runId: readProgressMetaString(meta, 'currentRunId'),\n runProgressJobId: readProgressMetaString(meta, 'currentRunProgressJobId'),\n progressPercent: readProgressMetaNumber(meta, 'currentRunProgressPercent'),\n processedCount: readProgressMetaNumber(meta, 'currentRunProcessedCount'),\n totalCount: readProgressMetaNumber(meta, 'currentRunTotalCount'),\n errorMessage: typeof payload.errorMessage === 'string' ? payload.errorMessage : null,\n })\n\n if (nextPhase === 'running') {\n firstImportTerminalNoticeRef.current = null\n return\n }\n\n const terminalNoticeKey = `${payload.jobId}:${payload.status ?? 'unknown'}`\n if (firstImportTerminalNoticeRef.current === terminalNoticeKey) return\n firstImportTerminalNoticeRef.current = terminalNoticeKey\n\n if (nextPhase === 'completed') {\n setHasCompletedProductImport(true)\n flash(t('sync_akeneo.firstImport.completed', 'The first full Akeneo import finished successfully.'), 'success')\n void load(false)\n return\n }\n\n if (nextPhase === 'failed') {\n flash(\n typeof payload.errorMessage === 'string' && payload.errorMessage.trim().length > 0\n ? payload.errorMessage\n : t('sync_akeneo.firstImport.errors.failed', 'The sync run failed.'),\n 'error',\n )\n void loadFirstImportStatus().catch(() => undefined)\n return\n }\n\n if (payload.status === 'cancelled') {\n flash(t('sync_akeneo.firstImport.errors.cancelled', 'The first full Akeneo import was cancelled.'), 'error')\n void loadFirstImportStatus().catch(() => undefined)\n }\n }, [load, loadFirstImportStatus, t])\n\n const applyFirstImportChildRunProgressEvent = React.useCallback((payload: ProgressEventPayload) => {\n const jobId = typeof payload.jobId === 'string' ? payload.jobId : null\n if (!jobId) return\n\n setFirstImportProgress((current) => {\n if (!current.runProgressJobId || current.runProgressJobId !== jobId) {\n return current\n }\n\n return {\n ...current,\n phase: payload.status === 'failed' || payload.status === 'cancelled'\n ? 'failed'\n : current.phase === 'idle'\n ? 'running'\n : current.phase,\n progressPercent: typeof payload.progressPercent === 'number'\n ? payload.progressPercent\n : current.progressPercent,\n processedCount: typeof payload.processedCount === 'number'\n ? payload.processedCount\n : current.processedCount,\n totalCount: typeof payload.totalCount === 'number'\n ? payload.totalCount\n : current.totalCount,\n errorMessage: typeof payload.errorMessage === 'string'\n ? payload.errorMessage\n : current.errorMessage,\n }\n })\n }, [])\n\n const applyDeleteImportedProductsEvent = React.useCallback((payload: ProgressEventPayload) => {\n if (!deleteImportedProductsJobId || payload.jobId !== deleteImportedProductsJobId) return\n\n const nextJob: DeleteImportedProductsJobResponse = {\n id: payload.jobId,\n status: payload.status === 'pending'\n || payload.status === 'running'\n || payload.status === 'completed'\n || payload.status === 'failed'\n || payload.status === 'cancelled'\n ? payload.status\n : 'running',\n progressPercent: typeof payload.progressPercent === 'number' ? payload.progressPercent : 0,\n processedCount: typeof payload.processedCount === 'number' ? payload.processedCount : 0,\n totalCount: typeof payload.totalCount === 'number' ? payload.totalCount : null,\n resultSummary: payload.resultSummary ?? null,\n errorMessage: typeof payload.errorMessage === 'string' ? payload.errorMessage : null,\n }\n\n setDeleteImportedProductsJob(nextJob)\n\n if (nextJob.status === 'completed') {\n setDeleteImportedProductsJobId(null)\n setDeleteImportedProductsJob(null)\n flash(\n readDeleteImportedProductsSummaryMessage(nextJob.resultSummary)\n ?? t('sync_akeneo.deleteImportedProducts.completed', 'Imported Akeneo product deletion completed.'),\n 'success',\n )\n void load(false)\n return\n }\n\n if (nextJob.status === 'failed') {\n setDeleteImportedProductsJobId(null)\n setDeleteImportedProductsJob(null)\n flash(\n nextJob.errorMessage\n ?? t('sync_akeneo.deleteImportedProducts.failed', 'Imported Akeneo product deletion failed.'),\n 'error',\n )\n return\n }\n\n if (nextJob.status === 'cancelled') {\n setDeleteImportedProductsJobId(null)\n setDeleteImportedProductsJob(null)\n flash(\n t('sync_akeneo.deleteImportedProducts.cancelled', 'Imported Akeneo product deletion was cancelled.'),\n 'warning',\n )\n }\n }, [deleteImportedProductsJobId, load, t])\n\n React.useEffect(() => {\n void load(false)\n }, [load])\n\n useAppEvent('progress.job.created', (event) => {\n const payload = event.payload as ProgressEventPayload\n applyFirstImportProgressEvent(payload)\n applyFirstImportChildRunProgressEvent(payload)\n applyDeleteImportedProductsEvent(payload)\n }, [applyDeleteImportedProductsEvent, applyFirstImportChildRunProgressEvent, applyFirstImportProgressEvent])\n\n useAppEvent('progress.job.started', (event) => {\n const payload = event.payload as ProgressEventPayload\n applyFirstImportProgressEvent(payload)\n applyFirstImportChildRunProgressEvent(payload)\n applyDeleteImportedProductsEvent(payload)\n }, [applyDeleteImportedProductsEvent, applyFirstImportChildRunProgressEvent, applyFirstImportProgressEvent])\n\n useAppEvent('progress.job.updated', (event) => {\n const payload = event.payload as ProgressEventPayload\n applyFirstImportProgressEvent(payload)\n applyFirstImportChildRunProgressEvent(payload)\n applyDeleteImportedProductsEvent(payload)\n }, [applyDeleteImportedProductsEvent, applyFirstImportChildRunProgressEvent, applyFirstImportProgressEvent])\n\n useAppEvent('progress.job.completed', (event) => {\n const payload = event.payload as ProgressEventPayload\n applyFirstImportProgressEvent(payload)\n applyFirstImportChildRunProgressEvent(payload)\n applyDeleteImportedProductsEvent(payload)\n }, [applyDeleteImportedProductsEvent, applyFirstImportChildRunProgressEvent, applyFirstImportProgressEvent])\n\n useAppEvent('progress.job.failed', (event) => {\n const payload = event.payload as ProgressEventPayload\n applyFirstImportProgressEvent(payload)\n applyFirstImportChildRunProgressEvent(payload)\n applyDeleteImportedProductsEvent(payload)\n }, [applyDeleteImportedProductsEvent, applyFirstImportChildRunProgressEvent, applyFirstImportProgressEvent])\n\n useAppEvent('progress.job.cancelled', (event) => {\n const payload = event.payload as ProgressEventPayload\n applyFirstImportProgressEvent(payload)\n applyFirstImportChildRunProgressEvent(payload)\n applyDeleteImportedProductsEvent(payload)\n }, [applyDeleteImportedProductsEvent, applyFirstImportChildRunProgressEvent, applyFirstImportProgressEvent])\n\n useAppEvent('om:bridge:reconnected', () => {\n void loadFirstImportStatus().catch(() => undefined)\n }, [loadFirstImportStatus])\n\n const attributeCodes = React.useMemo(\n () => (discovery?.attributes ?? []).map((attribute) => attribute.code).sort(),\n [discovery],\n )\n const customFieldRows = React.useMemo(\n () => parseCustomFieldRows(state.customFieldMappings),\n [state.customFieldMappings],\n )\n const priceMappingRows = React.useMemo(\n () => parsePriceMappingRows(state.priceMappings),\n [state.priceMappings],\n )\n const mediaMappingRows = React.useMemo(\n () => parseMediaMappingRows(state.mediaMappings),\n [state.mediaMappings],\n )\n const fieldsetMappingRows = React.useMemo(\n () => parseFieldsetMappingRows(state.fieldsetMappings),\n [state.fieldsetMappings],\n )\n const discoveredAkeneoChannelCodes = React.useMemo(\n () => (discovery?.channels ?? []).map((channel) => channel.code),\n [discovery],\n )\n const selectedAkeneoChannelSet = React.useMemo(\n () => new Set(state.productChannels),\n [state.productChannels],\n )\n const discoveredLocalChannelCodes = React.useMemo(\n () => (discovery?.localChannels ?? []).map((channel) => channel.code),\n [discovery],\n )\n const deleteImportedProductsBusy = isStartingDeleteImportedProducts\n || deleteImportedProductsJob?.status === 'pending'\n || deleteImportedProductsJob?.status === 'running'\n const firstImportBusy = firstImportProgress.phase === 'running'\n const firstImportReady = Boolean(context?.state?.isEnabled) && Boolean(data?.hasCredentials)\n const shouldShowFirstImportCallout = !isLoading && (\n firstImportBusy\n || firstImportProgress.phase === 'failed'\n || !hasCompletedProductImport\n )\n const firstImportCurrentStepLabel = firstImportProgress.step\n ? t(`sync_akeneo.firstImport.steps.${firstImportProgress.step}`, firstImportProgress.step)\n : null\n const discoveredPriceKindCodes = React.useMemo(\n () => (discovery?.priceKinds ?? []).map((priceKind) => priceKind.code),\n [discovery],\n )\n const productFieldKeys = React.useMemo(\n () => new Set(customFieldStatus?.productKeys ?? []),\n [customFieldStatus],\n )\n const variantFieldKeys = React.useMemo(\n () => new Set(customFieldStatus?.variantKeys ?? []),\n [customFieldStatus],\n )\n const missingCustomFieldCount = React.useMemo(\n () => customFieldRows.filter((row) => {\n if (row.skip) return false\n if (!row.fieldKey.trim()) return false\n return row.target === 'product'\n ? !productFieldKeys.has(row.fieldKey.trim())\n : !variantFieldKeys.has(row.fieldKey.trim())\n }).length,\n [customFieldRows, productFieldKeys, variantFieldKeys],\n )\n const editorMappedAttributeCodes = React.useMemo(\n () => new Set(customFieldEditorRows.map((row) => row.attributeCode).filter((value) => value.length > 0)),\n [customFieldEditorRows],\n )\n const suggestedCustomFieldAttributes = React.useMemo(\n () => (discovery?.attributes ?? []).filter((attribute) => !editorMappedAttributeCodes.has(attribute.code)).slice(0, 24),\n [discovery, editorMappedAttributeCodes],\n )\n const dialogMissingCustomFieldCount = React.useMemo(\n () => customFieldEditorRows.filter((row) => {\n if (row.skip) return false\n if (!row.fieldKey.trim()) return false\n return row.target === 'product'\n ? !productFieldKeys.has(row.fieldKey.trim())\n : !variantFieldKeys.has(row.fieldKey.trim())\n }).length,\n [customFieldEditorRows, productFieldKeys, variantFieldKeys],\n )\n const skippedCustomFieldCount = React.useMemo(\n () => customFieldRows.filter((row) => row.skip).length,\n [customFieldRows],\n )\n const renderCustomFieldStatusBadge = React.useCallback((exists: boolean) => (\n <Badge\n variant=\"outline\"\n className={exists\n ? 'inline-flex items-center gap-1.5 border-emerald-200 bg-emerald-50 text-emerald-700'\n : 'inline-flex items-center gap-1.5 border-amber-200 bg-amber-50 text-amber-700'}\n >\n {exists ? <CheckCircle2 className=\"size-3.5\" /> : <AlertCircle className=\"size-3.5\" />}\n <span>\n {exists\n ? t('sync_akeneo.customFields.status.ready', 'Exists')\n : t('sync_akeneo.customFields.status.missing', 'Missing')}\n </span>\n </Badge>\n ), [t])\n const renderSkippedCustomFieldBadge = React.useCallback(() => (\n <Badge\n variant=\"outline\"\n className=\"inline-flex items-center gap-1.5 border-slate-300 bg-slate-100 text-slate-700\"\n >\n <X className=\"size-3.5\" />\n <span>{t('sync_akeneo.customFields.status.skipped', 'Skipped')}</span>\n </Badge>\n ), [t])\n\n function openCustomFieldDialog() {\n setCustomFieldEditorRows(parseCustomFieldRows(state.customFieldMappings))\n setCustomFieldDialogOpen(true)\n }\n\n function toggleImportedAkeneoChannel(code: string, checked: boolean) {\n setState((current) => {\n const next = checked\n ? Array.from(new Set([...current.productChannels, code]))\n : current.productChannels.filter((entry) => entry !== code)\n const nextPrimary = next.includes(current.productChannel)\n ? current.productChannel\n : next[0] ?? ''\n return {\n ...current,\n productChannels: next,\n productChannel: nextPrimary,\n }\n })\n }\n\n async function createMissingCustomFields(sourceRows?: CustomFieldRow[]) {\n setIsCreatingCustomFields(true)\n try {\n const customFieldMappings = (sourceRows ?? parseCustomFieldRows(state.customFieldMappings))\n .filter((row) => !row.skip)\n if (customFieldMappings.length === 0) {\n flash(t('sync_akeneo.customFields.createNothing', 'There are no non-skipped custom-field mappings to create.'), 'info')\n return\n }\n const currentProductsMapping = {\n ...buildDefaultAkeneoMapping('products'),\n settings: {\n products: {\n locale: state.productLocale,\n channel: state.productChannel || null,\n channels: state.importAllProductChannels ? [] : state.productChannels,\n importAllChannels: state.importAllProductChannels,\n fieldMap: { ...state.fieldMap },\n customFieldMappings: customFieldMappings.map((row) => ({\n attributeCode: row.attributeCode.trim(),\n target: row.target,\n fieldKey: row.fieldKey.trim() || normalizeFieldKey(row.attributeCode),\n kind: row.kind || null,\n skip: false,\n })),\n priceMappings: [],\n mediaMappings: [],\n fieldsetMappings: parseFieldsetMappingRows(state.fieldsetMappings).map((row) => ({\n sourceType: row.sourceType,\n sourceCode: row.sourceCode.trim(),\n target: row.target,\n fieldsetCode: row.fieldsetCode.trim(),\n fieldsetLabel: row.fieldsetLabel.trim(),\n description: row.description.trim() || null,\n })),\n createMissingChannels: state.createMissingChannels,\n syncAssociations: state.syncAssociations,\n reconciliation: { ...state.reconciliation },\n },\n },\n }\n currentProductsMapping.fields = buildProductFieldMappings(currentProductsMapping.settings.products)\n const result = await apiCall<CustomFieldStatusResponse>('/api/sync_akeneo/custom-fields', {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({\n mapping: currentProductsMapping,\n }),\n })\n setCustomFieldStatus(result.result ?? null)\n flash(\n result.result?.message\n ?? t('sync_akeneo.customFields.created', 'Akeneo-backed custom fields created.'),\n 'success',\n )\n } catch (error) {\n const message = error instanceof Error ? error.message : 'Failed to create custom fields'\n flash(message, 'error')\n } finally {\n setIsCreatingCustomFields(false)\n }\n }\n\n function applyCustomFieldEditor() {\n setState((current) => ({\n ...current,\n customFieldMappings: serializeCustomFieldRows(customFieldEditorRows),\n }))\n setCustomFieldDialogOpen(false)\n }\n\n function updatePriceMappingRows(nextRows: PriceMappingRow[]) {\n setState((current) => ({\n ...current,\n priceMappings: serializePriceMappingRows(nextRows),\n }))\n }\n\n function updateMediaMappingRows(nextRows: MediaMappingRow[]) {\n setState((current) => ({\n ...current,\n mediaMappings: serializeMediaMappingRows(nextRows),\n }))\n }\n\n function updateFieldsetMappingRows(nextRows: FieldsetMappingRow[]) {\n setState((current) => ({\n ...current,\n fieldsetMappings: serializeFieldsetMappingRows(nextRows),\n }))\n }\n\n async function refreshDiscoveredMappings() {\n setIsSaving(true)\n try {\n const discoveryCall = await apiCall<AkeneoDiscoveryResponse>('/api/sync_akeneo/discovery?refresh=true')\n const discovered = discoveryCall.result ?? null\n if (!discovered?.ok) {\n throw new Error(discovered?.message ?? 'Failed to load Akeneo discovery metadata')\n }\n\n const nextState = applyDiscoveryDefaults({ ...state }, discovered)\n\n await persistMappings(nextState, {\n successMessage: t('sync_akeneo.discovery.rediscovered', 'Akeneo fields refreshed and missing mappings added.'),\n })\n\n setState(nextState)\n setDiscovery(discovered)\n const customFieldsCall = await apiCall<CustomFieldStatusResponse>('/api/sync_akeneo/custom-fields')\n setCustomFieldStatus(customFieldsCall.result ?? null)\n } catch (error) {\n const message = error instanceof Error ? error.message : 'Failed to refresh Akeneo mappings'\n flash(message, 'error')\n } finally {\n setIsSaving(false)\n }\n }\n\n async function saveMappings() {\n setIsSaving(true)\n try {\n await persistMappings(state, {\n successMessage: t('sync_akeneo.saved', 'Akeneo sync settings saved.'),\n })\n await load(false)\n } catch (error) {\n const message = error instanceof Error ? error.message : 'Failed to save Akeneo mapping'\n flash(message, 'error')\n } finally {\n setIsSaving(false)\n }\n }\n\n async function deleteImportedProducts() {\n const confirmed = await confirm({\n title: t('sync_akeneo.deleteImportedProducts.confirmTitle', 'Force delete all imported Akeneo products?'),\n text: t('sync_akeneo.deleteImportedProducts.confirmText', 'This will permanently delete products imported by the Akeneo integration for the current organization, together with their imported variants and related catalog data. The Akeneo product cursor will also be reset so a fresh import can start from scratch.'),\n confirmText: t('sync_akeneo.deleteImportedProducts.confirmAction', 'Force delete'),\n cancelText: t('sync_akeneo.deleteImportedProducts.cancel', 'Cancel'),\n variant: 'destructive',\n })\n if (!confirmed) return\n\n setIsStartingDeleteImportedProducts(true)\n try {\n const result = await apiCall<DeleteImportedProductsResponse>('/api/sync_akeneo/delete-products', {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ confirm: true }),\n })\n if (!result.ok || !result.result) {\n throw new Error('Failed to delete imported Akeneo products')\n }\n\n if (!result.result.progressJobId) {\n flash(result.result.message, 'success')\n await load(false)\n return\n }\n\n setDeleteImportedProductsJob({\n id: result.result.progressJobId,\n status: 'pending',\n progressPercent: 0,\n processedCount: 0,\n totalCount: null,\n })\n setDeleteImportedProductsJobId(result.result.progressJobId)\n } catch (error) {\n const message = error instanceof Error ? error.message : 'Failed to delete imported Akeneo products'\n flash(message, 'error')\n } finally {\n setIsStartingDeleteImportedProducts(false)\n }\n }\n\n return (\n <div className=\"space-y-6 rounded-lg border bg-card p-4\">\n <div className=\"space-y-3\">\n <h3 className=\"text-sm font-semibold\">\n {t('sync_akeneo.setup.heading', 'Akeneo API setup')}\n </h3>\n <Alert variant=\"info\">\n <AlertDescription>\n {t('sync_akeneo.setup.scheduleTab', 'Run once and recurring schedules now live in the dedicated Sync schedules tab, shared by all data sync integrations.')}\n </AlertDescription>\n </Alert>\n <Alert variant=\"info\">\n <AlertTitle>{t('sync_akeneo.setup.order.title', 'Recommended sync order')}</AlertTitle>\n <AlertDescription>\n {t(\n 'sync_akeneo.setup.order.message',\n 'Run category sync first, attribute sync second, and product sync last. Product import expects local categories and family-based schemas to exist already.',\n )}\n </AlertDescription>\n </Alert>\n {shouldShowFirstImportCallout ? (\n <NextStepCallout\n icon={<Sparkles className=\"h-6 w-6\" />}\n title={t('sync_akeneo.firstImport.title', 'Run the first full import')}\n description={t(\n 'sync_akeneo.firstImport.help',\n 'Launch the standard Akeneo sync sequence in the recommended order: categories first, attributes second, products last.',\n )}\n steps={FIRST_IMPORT_STEPS.map((step, stepIndex) => {\n const currentStepIndex = firstImportProgress.step\n ? FIRST_IMPORT_STEPS.findIndex((item) => item.entityType === firstImportProgress.step)\n : -1\n const isActive = firstImportProgress.step === step.entityType && firstImportProgress.phase === 'running'\n const isDone = firstImportProgress.phase === 'running' && currentStepIndex > stepIndex\n return {\n id: step.entityType,\n label: t(`sync_akeneo.firstImport.steps.${step.entityType}`, step.entityType),\n state: isActive ? 'active' : isDone ? 'completed' : 'pending',\n }\n })}\n actionLabel={firstImportBusy\n ? t('sync_akeneo.firstImport.running', 'Running full import sequence...')\n : t('sync_akeneo.firstImport.action', 'Run the first full import')}\n actionIcon={firstImportBusy ? <RefreshCw className=\"mr-2 h-4 w-4 animate-spin\" /> : <Wand2 className=\"mr-2 h-4 w-4\" />}\n onAction={() => void runFirstFullImport()}\n disabled={isLoading || isSaving || deleteImportedProductsBusy || !firstImportReady}\n busy={firstImportBusy}\n disabledMessage={!firstImportReady\n ? context?.state?.isEnabled\n ? t('sync_akeneo.firstImport.missingCredentials', 'Save valid Akeneo credentials before starting the first full import.')\n : t('sync_akeneo.firstImport.integrationDisabled', 'Enable the integration and save valid Akeneo credentials before starting the first full import.')\n : undefined}\n status={firstImportProgress.phase !== 'idle'\n ? {\n tone: firstImportProgress.phase === 'failed' ? 'danger' : 'info',\n icon: firstImportProgress.phase === 'failed'\n ? <AlertCircle className=\"h-4 w-4\" />\n : <RefreshCw className={firstImportBusy ? 'h-4 w-4 animate-spin' : 'h-4 w-4'} />,\n label: firstImportProgress.phase === 'failed'\n ? t('sync_akeneo.firstImport.status.failed', 'Full import failed')\n : t('sync_akeneo.firstImport.status.running', 'Full import sequence running'),\n badge: firstImportCurrentStepLabel ? <Badge variant=\"outline\">{firstImportCurrentStepLabel}</Badge> : null,\n progressValue: typeof firstImportProgress.progressPercent === 'number' ? firstImportProgress.progressPercent : null,\n progressDescription: firstImportBusy\n ? firstImportProgress.totalCount && firstImportProgress.totalCount > 0\n ? t(\n 'sync_akeneo.firstImport.progressCount',\n '{processed} of {total} items processed in the current run.',\n {\n processed: firstImportProgress.processedCount ?? 0,\n total: firstImportProgress.totalCount,\n },\n )\n : t('sync_akeneo.firstImport.progressUnknown', 'The current run is active. Live progress also appears in the global operations bar.')\n : undefined,\n errorMessage: firstImportProgress.errorMessage,\n }\n : null}\n />\n ) : null}\n <div className=\"grid gap-4 lg:grid-cols-2\">\n <div className=\"rounded-lg border p-4\">\n <h4 className=\"text-sm font-medium\">{t('sync_akeneo.setup.credentials.title', 'Create API credentials in Akeneo')}</h4>\n <ol className=\"mt-3 list-decimal space-y-2 pl-5 text-sm text-muted-foreground\">\n <li>{t('sync_akeneo.setup.credentials.step1', 'In Akeneo, open Settings -> Connections and create a new API connection or connected app for Open Mercato.')}</li>\n <li>{t('sync_akeneo.setup.credentials.step2', 'Copy the Akeneo base URL, client id, and client secret into the Integration credentials tab in Open Mercato.')}</li>\n <li>{t('sync_akeneo.setup.credentials.step3', 'Create a dedicated Akeneo API user, assign it to the right catalog permissions, and use that username/password in the credential form.')}</li>\n <li>{t('sync_akeneo.setup.credentials.step4', 'Grant the API user access to products, categories, attributes, families, family variants, locales, and channels. Limit write permissions if you only import.')}</li>\n </ol>\n </div>\n <div className=\"rounded-lg border p-4\">\n <h4 className=\"text-sm font-medium\">{t('sync_akeneo.setup.docs.title', 'Operational notes')}</h4>\n <ul className=\"mt-3 list-disc space-y-2 pl-5 text-sm text-muted-foreground\">\n <li>{t('sync_akeneo.setup.docs.note1', 'Akeneo authentication uses client id, client secret, username, and password. Open Mercato exchanges those for access/refresh tokens automatically.')}</li>\n <li>{t('sync_akeneo.setup.docs.note2', 'For large catalogs, keep batch sizes at 100 and prefer incremental product syncs. The importer resumes from the last processed Akeneo updated timestamp plus search_after pagination state.')}</li>\n <li>{t('sync_akeneo.setup.docs.note3', 'Simple Akeneo products still create a default Open Mercato variant. Variant Akeneo products flatten the full Akeneo product-model tree into one configurable product plus child variants.')}</li>\n <li>{t('sync_akeneo.setup.docs.note4', 'If you want channel offers and prices, create matching Sales Channels and Catalog Price Kinds in Open Mercato first, then reference their codes in the mapping blocks below.')}</li>\n </ul>\n <div className=\"mt-4 flex flex-wrap gap-2 text-sm\">\n <a className=\"underline\" href=\"https://api.akeneo.com/documentation/authentication.html\" target=\"_blank\" rel=\"noreferrer\">\n {t('sync_akeneo.links.auth', 'Akeneo authentication docs')}\n </a>\n <a className=\"underline\" href=\"https://api.akeneo.com/documentation/pagination.html\" target=\"_blank\" rel=\"noreferrer\">\n {t('sync_akeneo.links.pagination', 'Akeneo pagination docs')}\n </a>\n </div>\n </div>\n </div>\n </div>\n\n <div className=\"space-y-3\">\n <div className=\"flex items-center justify-between gap-3\">\n <div>\n <h3 className=\"text-sm font-semibold\">{t('sync_akeneo.mapping.heading', 'Field mapping')}</h3>\n <p className=\"text-sm text-muted-foreground\">\n {t('sync_akeneo.mapping.help', 'Mappings are discovered automatically from the saved Akeneo credentials. Use refresh discovery to pull the latest Akeneo metadata and add any missing mappings without deleting your existing overrides.')}\n </p>\n </div>\n <div className=\"flex flex-wrap gap-2\">\n <Button type=\"button\" variant=\"outline\" onClick={() => void refreshDiscoveredMappings()} disabled={isLoading || isSaving || deleteImportedProductsBusy || firstImportBusy}>\n <RefreshCw className=\"mr-2 h-4 w-4\" />\n {t('sync_akeneo.mapping.refresh', 'Refresh discovery')}\n </Button>\n <Button type=\"button\" variant=\"destructive\" onClick={() => void deleteImportedProducts()} disabled={isLoading || isSaving || deleteImportedProductsBusy || firstImportBusy}>\n <Trash2 className=\"mr-2 h-4 w-4\" />\n {deleteImportedProductsBusy\n ? t('sync_akeneo.deleteImportedProducts.inProgress', 'Deletion in progress...')\n : t('sync_akeneo.deleteImportedProducts.action', 'Force delete all imported products')}\n </Button>\n </div>\n </div>\n\n {deleteImportedProductsBusy && deleteImportedProductsJob ? (\n <div className=\"rounded-lg border border-destructive/30 bg-destructive/5 p-3\">\n <div className=\"flex flex-wrap items-center justify-between gap-2 text-sm\">\n <div className=\"font-medium\">\n {t('sync_akeneo.deleteImportedProducts.progressTitle', 'Deleting imported Akeneo products')}\n </div>\n <Badge variant=\"outline\">\n {deleteImportedProductsJob.totalCount && deleteImportedProductsJob.totalCount > 0\n ? t(\n 'sync_akeneo.deleteImportedProducts.progressCount',\n '{processed} / {total}',\n {\n processed: deleteImportedProductsJob.processedCount,\n total: deleteImportedProductsJob.totalCount,\n },\n )\n : t('sync_akeneo.deleteImportedProducts.preparing', 'Preparing...')}\n </Badge>\n </div>\n {deleteImportedProductsJob.totalCount && deleteImportedProductsJob.totalCount > 0 ? (\n <Progress value={deleteImportedProductsJob.progressPercent} className=\"mt-3 h-2\" />\n ) : (\n <div className=\"mt-3 h-2 rounded-full bg-secondary\" />\n )}\n <p className=\"mt-2 text-xs text-muted-foreground\">\n {deleteImportedProductsJob.status === 'pending'\n ? t('sync_akeneo.deleteImportedProducts.pending', 'The deletion job is being prepared.')\n : t(\n 'sync_akeneo.deleteImportedProducts.running',\n 'The imported product cleanup is running in the background. Progress also appears in the global progress bar.',\n )}\n </p>\n </div>\n ) : null}\n\n {discovery?.message ? (\n <Alert variant={discovery.ok ? 'info' : 'warning'}>\n <AlertDescription>{discovery.message}</AlertDescription>\n </Alert>\n ) : null}\n\n <div className=\"grid gap-6 xl:grid-cols-[1.2fr_0.8fr]\">\n <div className=\"space-y-5 rounded-lg border p-4\">\n <div className=\"grid gap-4 md:grid-cols-2\">\n <div className=\"space-y-2\">\n <Label htmlFor=\"akeneo-product-locale\">{t('sync_akeneo.mapping.productLocale', 'Product locale')}</Label>\n <select\n id=\"akeneo-product-locale\"\n value={state.productLocale}\n onChange={(event) => setState((current) => ({ ...current, productLocale: event.target.value }))}\n disabled={isLoading || isSaving || (discovery?.locales?.length ?? 0) === 0}\n className=\"flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background\"\n >\n {(discovery?.locales ?? []).map((locale) => (\n <option key={locale.code} value={locale.code}>\n {locale.code}\n </option>\n ))}\n </select>\n <p className=\"text-xs text-muted-foreground\">\n {t('sync_akeneo.mapping.productLocale.help', 'Only this Akeneo locale is imported into the base Open Mercato fields for now. Other locales are ignored until translation import is added.')}\n </p>\n </div>\n <div className=\"space-y-2\">\n <Label htmlFor=\"akeneo-product-channel\">{t('sync_akeneo.mapping.productChannel', 'Primary content channel')}</Label>\n <select\n id=\"akeneo-product-channel\"\n value={state.productChannel}\n onChange={(event) => setState((current) => {\n const nextChannel = event.target.value\n return {\n ...current,\n productChannel: nextChannel,\n productChannels: current.importAllProductChannels || !nextChannel || current.productChannels.includes(nextChannel)\n ? current.productChannels\n : [...current.productChannels, nextChannel],\n }\n })}\n disabled={isLoading || isSaving || (discovery?.channels?.length ?? 0) === 0}\n className=\"h-10 w-full appearance-auto rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background\"\n >\n <option value=\"\">{t('sync_akeneo.mapping.channelPlaceholder', 'Optional')}</option>\n {(discovery?.channels ?? []).map((channel) => (\n <option key={channel.code} value={channel.code}>\n {channel.code}\n </option>\n ))}\n </select>\n <p className=\"text-xs text-muted-foreground\">\n {t('sync_akeneo.mapping.productChannel.help', 'This single Akeneo channel is used for base product content, custom fields, media, and variant labels when attributes are channel-scoped.')}\n </p>\n </div>\n </div>\n\n <div className=\"space-y-3 rounded-lg border p-3\">\n <div className=\"space-y-1\">\n <Label>{t('sync_akeneo.mapping.importChannels', 'Imported Akeneo channels')}</Label>\n <p className=\"text-xs text-muted-foreground\">\n {t('sync_akeneo.mapping.importChannels.help', 'Choose which Akeneo channels should be imported for channel-scoped data like offers and prices. Locale stays single-select.')}\n </p>\n </div>\n <label className=\"flex items-center gap-2 text-sm\">\n <input\n type=\"checkbox\"\n checked={state.importAllProductChannels}\n onChange={(event) => setState((current) => ({\n ...current,\n importAllProductChannels: event.target.checked,\n productChannels: event.target.checked\n ? current.productChannels\n : (current.productChannels.length > 0\n ? current.productChannels\n : current.productChannel\n ? [current.productChannel]\n : []),\n }))}\n disabled={isLoading || isSaving}\n />\n <span>{t('sync_akeneo.mapping.importChannels.all', 'Import all Akeneo channels')}</span>\n </label>\n {!state.importAllProductChannels ? (\n <div className=\"grid gap-2 md:grid-cols-2\">\n {(discovery?.channels ?? []).map((channel) => (\n <label key={channel.code} className=\"flex items-center gap-2 rounded border px-3 py-2 text-sm\">\n <input\n type=\"checkbox\"\n checked={selectedAkeneoChannelSet.has(channel.code)}\n onChange={(event) => toggleImportedAkeneoChannel(channel.code, event.target.checked)}\n disabled={isLoading || isSaving}\n />\n <span>{channel.code}</span>\n </label>\n ))}\n </div>\n ) : null}\n </div>\n\n <div className=\"grid gap-4 md:grid-cols-2\">\n {PRODUCT_FIELD_KEYS.map((field) => (\n <div key={field.key} className=\"space-y-2\">\n <Label htmlFor={`akeneo-${field.key}`}>{t(`sync_akeneo.mapping.${field.key}`, field.label)}</Label>\n <Input\n id={`akeneo-${field.key}`}\n list=\"akeneo-attributes\"\n value={state.fieldMap[field.key]}\n onChange={(event) => {\n const value = event.target.value\n setState((current) => ({\n ...current,\n fieldMap: {\n ...current.fieldMap,\n [field.key]: value,\n },\n }))\n }}\n disabled={isLoading || isSaving}\n />\n <p className=\"text-xs text-muted-foreground\">{t(`sync_akeneo.mapping.${field.key}.help`, field.help)}</p>\n </div>\n ))}\n </div>\n\n <div className=\"grid gap-4 md:grid-cols-2\">\n <div className=\"space-y-2\">\n <Label htmlFor=\"akeneo-category-locale\">{t('sync_akeneo.mapping.categoryLocale', 'Category label locale')}</Label>\n <select\n id=\"akeneo-category-locale\"\n value={state.categoryLocale}\n onChange={(event) => setState((current) => ({ ...current, categoryLocale: event.target.value }))}\n disabled={isLoading || isSaving || (discovery?.locales?.length ?? 0) === 0}\n className=\"flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background\"\n >\n {(discovery?.locales ?? []).map((locale) => (\n <option key={locale.code} value={locale.code}>\n {locale.code}\n </option>\n ))}\n </select>\n </div>\n <div className=\"space-y-2\">\n <Label htmlFor=\"akeneo-family-filter\">{t('sync_akeneo.mapping.familyFilter', 'Attribute sync family filter')}</Label>\n <Input\n id=\"akeneo-family-filter\"\n value={state.familyCodeFilter}\n onChange={(event) => setState((current) => ({ ...current, familyCodeFilter: event.target.value }))}\n disabled={isLoading || isSaving}\n placeholder={t('sync_akeneo.mapping.familyFilterPlaceholder', 'family_a, family_b')}\n />\n <p className=\"text-xs text-muted-foreground\">\n {t('sync_akeneo.mapping.familyFilter.help', 'Leave empty to sync family-driven schemas for all Akeneo families.')}\n </p>\n </div>\n </div>\n\n <div className=\"grid gap-4\">\n <div className=\"space-y-2\">\n <div className=\"flex items-center justify-between gap-3\">\n <Label>{t('sync_akeneo.mapping.customFields', 'Custom field mappings')}</Label>\n <div className=\"flex flex-wrap items-center gap-2\">\n <Button type=\"button\" variant=\"outline\" onClick={() => openCustomFieldDialog()} disabled={isLoading || isSaving}>\n <PencilLine className=\"mr-2 h-4 w-4\" />\n {t('sync_akeneo.mapping.customFields.editor', 'Open editor')}\n </Button>\n <Button type=\"button\" variant=\"outline\" onClick={() => void createMissingCustomFields()} disabled={isLoading || isSaving || isCreatingCustomFields || customFieldRows.length === 0}>\n {isCreatingCustomFields ? <RefreshCw className=\"mr-2 h-4 w-4 animate-spin\" /> : <Wand2 className=\"mr-2 h-4 w-4\" />}\n {isCreatingCustomFields\n ? t('sync_akeneo.mapping.customFields.creating', 'Creating...')\n : t('sync_akeneo.mapping.customFields.createMissing', 'Pre-create missing fields')}\n </Button>\n </div>\n </div>\n <p className=\"text-xs text-muted-foreground\">\n {t('sync_akeneo.mapping.customFields.help', 'One mapping per line: attribute_code,target(product|variant),field_key[,kind][,skip]. After valid Akeneo credentials are saved, Open Mercato discovers mappings automatically: variant axes stay as product options, and other relevant Akeneo attributes are auto-mapped as custom fields unless you override them here. Use the editor skip checkbox when an Akeneo attribute should be ignored entirely. Product imports create or update missing Open Mercato custom field definitions automatically and store the Akeneo metadata, validation rules, and groups on those fields.')}\n </p>\n <div className=\"flex items-start gap-2 rounded-md border border-emerald-200 bg-emerald-50/70 px-3 py-2 text-xs text-emerald-800\">\n <Sparkles className=\"mt-0.5 size-3.5 shrink-0\" />\n <span>\n {t('sync_akeneo.mapping.customFields.autoCreate', 'Running the Akeneo product import also creates any missing mapped fields automatically. Use the manual action only when you want to provision them before the first import.')}\n </span>\n </div>\n {customFieldRows.length > 0 ? (\n <div className=\"overflow-x-auto rounded-lg border\">\n <table className=\"w-full min-w-[760px] text-sm\">\n <thead className=\"bg-muted/50 text-left\">\n <tr>\n <th className=\"px-3 py-2 font-medium\">{t('sync_akeneo.mapping.from', 'From')}</th>\n <th className=\"px-3 py-2 font-medium\">{t('sync_akeneo.customFields.columns.target', 'Target')}</th>\n <th className=\"px-3 py-2 font-medium\">{t('sync_akeneo.customFields.columns.key', 'Field key')}</th>\n <th className=\"px-3 py-2 font-medium\">{t('sync_akeneo.customFields.columns.kind', 'Kind')}</th>\n <th className=\"px-3 py-2 font-medium\">{t('sync_akeneo.customFields.columns.status', 'Status')}</th>\n </tr>\n </thead>\n <tbody>\n {customFieldRows.map((row, index) => {\n const exists = row.target === 'product'\n ? productFieldKeys.has(row.fieldKey.trim())\n : variantFieldKeys.has(row.fieldKey.trim())\n return (\n <tr key={`${row.attributeCode}:${row.fieldKey}:${index}`} className={`border-t ${row.skip ? 'opacity-70' : ''}`}>\n <td className=\"px-3 py-2 font-medium\">{row.attributeCode}</td>\n <td className=\"px-3 py-2\">{row.target}</td>\n <td className=\"px-3 py-2\">{row.fieldKey}</td>\n <td className=\"px-3 py-2 text-muted-foreground\">{row.kind || t('sync_akeneo.customFields.kinds.auto', 'Auto')}</td>\n <td className=\"px-3 py-2\">\n {row.skip ? renderSkippedCustomFieldBadge() : renderCustomFieldStatusBadge(exists)}\n </td>\n </tr>\n )\n })}\n </tbody>\n </table>\n </div>\n ) : (\n <Alert variant=\"info\">\n <AlertDescription>\n {t('sync_akeneo.customFields.empty', 'No Akeneo custom fields are shown yet. They are discovered and mapped automatically after credentials are saved or when you use Refresh discovery. Use the editor only if you want to review or override the automatic mapping.')}\n </AlertDescription>\n </Alert>\n )}\n {customFieldRows.length > 0 ? (\n <div className=\"flex flex-wrap gap-2 text-xs\">\n <span className=\"rounded border px-2 py-1\">\n {t('sync_akeneo.mapping.customFields.total', `${customFieldRows.length} mapped`)}\n </span>\n {skippedCustomFieldCount > 0 ? (\n <span className=\"rounded border px-2 py-1\">\n {t('sync_akeneo.mapping.customFields.skipped', `${skippedCustomFieldCount} skipped`)}\n </span>\n ) : null}\n <span className={`rounded border px-2 py-1 ${missingCustomFieldCount > 0 ? 'border-amber-300 text-amber-700' : ''}`}>\n {missingCustomFieldCount > 0\n ? t('sync_akeneo.mapping.customFields.missing', `${missingCustomFieldCount} missing locally`)\n : t('sync_akeneo.mapping.customFields.ready', 'All mapped fields already exist')}\n </span>\n </div>\n ) : null}\n </div>\n <div className=\"space-y-2\">\n <div className=\"flex items-center justify-between gap-3\">\n <Label>{t('sync_akeneo.mapping.prices', 'Price and offer mappings')}</Label>\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={() => updatePriceMappingRows([\n ...priceMappingRows,\n { attributeCode: '', priceKindCode: '', akeneoChannel: '', localChannelCode: '' },\n ])}\n disabled={isLoading || isSaving}\n >\n <Plus className=\"mr-2 h-4 w-4\" />\n {t('sync_akeneo.mapping.addRow', 'Add row')}\n </Button>\n </div>\n <p className=\"text-xs text-muted-foreground\">\n {t('sync_akeneo.mapping.prices.help', 'One mapping per line: price_attribute,price_kind_code,akeneo_channel,local_channel_code. Each distinct local channel creates or updates an offer, and each price collection entry becomes a Catalog Product Price in the matching currency.')}\n </p>\n <div className=\"overflow-x-auto rounded-lg border\">\n <table className=\"w-full min-w-[900px] text-sm\">\n <thead className=\"bg-muted/50 text-left\">\n <tr>\n <th className=\"px-3 py-2 font-medium\">{t('sync_akeneo.mapping.from', 'From')}</th>\n <th className=\"px-3 py-2 font-medium\">{t('sync_akeneo.mapping.priceKind', 'Price kind')}</th>\n <th className=\"px-3 py-2 font-medium\">{t('sync_akeneo.mapping.akeneoChannel', 'Akeneo channel')}</th>\n <th className=\"px-3 py-2 font-medium\">{t('sync_akeneo.mapping.localChannel', 'Open Mercato channel')}</th>\n <th className=\"px-3 py-2 font-medium\">{t('sync_akeneo.customFields.columns.actions', 'Actions')}</th>\n </tr>\n </thead>\n <tbody>\n {priceMappingRows.length > 0 ? priceMappingRows.map((row, index) => (\n <tr key={`price-mapping-${index}`} className=\"border-t\">\n <td className=\"px-3 py-2\">\n <Input\n list=\"akeneo-attributes\"\n value={row.attributeCode}\n onChange={(event) => {\n const nextRows = [...priceMappingRows]\n nextRows[index] = { ...row, attributeCode: event.target.value }\n updatePriceMappingRows(nextRows)\n }}\n disabled={isLoading || isSaving}\n />\n </td>\n <td className=\"px-3 py-2\">\n <select\n className=\"flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm\"\n value={row.priceKindCode}\n onChange={(event) => {\n const nextRows = [...priceMappingRows]\n nextRows[index] = { ...row, priceKindCode: event.target.value }\n updatePriceMappingRows(nextRows)\n }}\n disabled={isLoading || isSaving}\n >\n <option value=\"\">{t('sync_akeneo.mapping.priceKindPlaceholder', 'Select price kind')}</option>\n {buildSelectValues(discoveredPriceKindCodes, row.priceKindCode).map((priceKindCode) => (\n <option key={priceKindCode} value={priceKindCode}>{priceKindCode}</option>\n ))}\n </select>\n </td>\n <td className=\"px-3 py-2\">\n <select\n className=\"flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm\"\n value={row.akeneoChannel}\n onChange={(event) => {\n const nextRows = [...priceMappingRows]\n nextRows[index] = { ...row, akeneoChannel: event.target.value }\n updatePriceMappingRows(nextRows)\n }}\n disabled={isLoading || isSaving}\n >\n <option value=\"\">{t('sync_akeneo.mapping.channelPlaceholder', 'Optional')}</option>\n {buildSelectValues(discoveredAkeneoChannelCodes, row.akeneoChannel).map((channelCode) => (\n <option key={channelCode} value={channelCode}>{channelCode}</option>\n ))}\n </select>\n </td>\n <td className=\"px-3 py-2\">\n <select\n className=\"flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm\"\n value={row.localChannelCode}\n onChange={(event) => {\n const nextRows = [...priceMappingRows]\n nextRows[index] = { ...row, localChannelCode: event.target.value }\n updatePriceMappingRows(nextRows)\n }}\n disabled={isLoading || isSaving}\n >\n <option value=\"\">{t('sync_akeneo.mapping.localChannelPlaceholder', 'Select Open Mercato channel')}</option>\n {buildSelectValues(discoveredLocalChannelCodes, row.localChannelCode).map((channelCode) => (\n <option key={channelCode} value={channelCode}>{channelCode}</option>\n ))}\n </select>\n </td>\n <td className=\"px-3 py-2\">\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n onClick={() => updatePriceMappingRows(priceMappingRows.filter((_, rowIndex) => rowIndex !== index))}\n disabled={isLoading || isSaving}\n >\n <Trash2 className=\"mr-2 h-4 w-4\" />\n {t('sync_akeneo.customFields.actions.remove', 'Remove')}\n </Button>\n </td>\n </tr>\n )) : (\n <tr>\n <td colSpan={5} className=\"px-3 py-6 text-center text-sm text-muted-foreground\">\n {t('sync_akeneo.mapping.emptyPrices', 'No price mappings configured yet.')}\n </td>\n </tr>\n )}\n </tbody>\n </table>\n </div>\n </div>\n <div className=\"space-y-2\">\n <div className=\"flex items-center justify-between gap-3\">\n <Label>{t('sync_akeneo.mapping.media', 'Media and attachment mappings')}</Label>\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={() => updateMediaMappingRows([\n ...mediaMappingRows,\n { attributeCode: '', target: 'product', kind: 'image' },\n ])}\n disabled={isLoading || isSaving}\n >\n <Plus className=\"mr-2 h-4 w-4\" />\n {t('sync_akeneo.mapping.addRow', 'Add row')}\n </Button>\n </div>\n <p className=\"text-xs text-muted-foreground\">\n {t('sync_akeneo.mapping.media.help', 'One mapping per line: attribute_code,target(product|variant),kind(image|file). Image mappings are re-hosted into Open Mercato attachments and can become default media; file mappings are imported as attachments.')}\n </p>\n <div className=\"overflow-x-auto rounded-lg border\">\n <table className=\"w-full min-w-[760px] text-sm\">\n <thead className=\"bg-muted/50 text-left\">\n <tr>\n <th className=\"px-3 py-2 font-medium\">{t('sync_akeneo.mapping.from', 'From')}</th>\n <th className=\"px-3 py-2 font-medium\">{t('sync_akeneo.customFields.columns.target', 'Target')}</th>\n <th className=\"px-3 py-2 font-medium\">{t('sync_akeneo.customFields.columns.kind', 'Kind')}</th>\n <th className=\"px-3 py-2 font-medium\">{t('sync_akeneo.customFields.columns.actions', 'Actions')}</th>\n </tr>\n </thead>\n <tbody>\n {mediaMappingRows.length > 0 ? mediaMappingRows.map((row, index) => (\n <tr key={`media-mapping-${index}`} className=\"border-t\">\n <td className=\"px-3 py-2\">\n <Input\n list=\"akeneo-attributes\"\n value={row.attributeCode}\n onChange={(event) => {\n const nextRows = [...mediaMappingRows]\n nextRows[index] = { ...row, attributeCode: event.target.value }\n updateMediaMappingRows(nextRows)\n }}\n disabled={isLoading || isSaving}\n />\n </td>\n <td className=\"px-3 py-2\">\n <select\n className=\"flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm\"\n value={row.target}\n onChange={(event) => {\n const nextRows = [...mediaMappingRows]\n nextRows[index] = { ...row, target: event.target.value === 'variant' ? 'variant' : 'product' }\n updateMediaMappingRows(nextRows)\n }}\n disabled={isLoading || isSaving}\n >\n <option value=\"product\">{t('sync_akeneo.customFields.targets.product', 'Product')}</option>\n <option value=\"variant\">{t('sync_akeneo.customFields.targets.variant', 'Variant')}</option>\n </select>\n </td>\n <td className=\"px-3 py-2\">\n <select\n className=\"flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm\"\n value={row.kind}\n onChange={(event) => {\n const nextRows = [...mediaMappingRows]\n nextRows[index] = { ...row, kind: event.target.value === 'file' ? 'file' : 'image' }\n updateMediaMappingRows(nextRows)\n }}\n disabled={isLoading || isSaving}\n >\n <option value=\"image\">{t('sync_akeneo.mapping.mediaKinds.image', 'Image')}</option>\n <option value=\"file\">{t('sync_akeneo.mapping.mediaKinds.file', 'File')}</option>\n </select>\n </td>\n <td className=\"px-3 py-2\">\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n onClick={() => updateMediaMappingRows(mediaMappingRows.filter((_, rowIndex) => rowIndex !== index))}\n disabled={isLoading || isSaving}\n >\n <Trash2 className=\"mr-2 h-4 w-4\" />\n {t('sync_akeneo.customFields.actions.remove', 'Remove')}\n </Button>\n </td>\n </tr>\n )) : (\n <tr>\n <td colSpan={4} className=\"px-3 py-6 text-center text-sm text-muted-foreground\">\n {t('sync_akeneo.mapping.emptyMedia', 'No media mappings configured yet.')}\n </td>\n </tr>\n )}\n </tbody>\n </table>\n </div>\n </div>\n <div className=\"space-y-2\">\n <div className=\"flex items-center justify-between gap-3\">\n <Label>{t('sync_akeneo.mapping.fieldsets', 'Family to fieldset mappings')}</Label>\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={() => updateFieldsetMappingRows([\n ...fieldsetMappingRows,\n {\n sourceType: 'family',\n sourceCode: '',\n target: 'product',\n fieldsetCode: '',\n fieldsetLabel: '',\n description: '',\n },\n ])}\n disabled={isLoading || isSaving}\n >\n <Plus className=\"mr-2 h-4 w-4\" />\n {t('sync_akeneo.mapping.addRow', 'Add row')}\n </Button>\n </div>\n <p className=\"text-xs text-muted-foreground\">\n {t('sync_akeneo.mapping.fieldsets.help', 'Discovered Akeneo families become Open Mercato fieldsets automatically. Adjust the fieldset code, label, or description here, and add manual family-variant rows when a specific Akeneo family variant should use a different variant fieldset.')}\n </p>\n <div className=\"overflow-x-auto rounded-lg border\">\n <table className=\"w-full min-w-[1100px] text-sm\">\n <thead className=\"bg-muted/50 text-left\">\n <tr>\n <th className=\"px-3 py-2 font-medium\">{t('sync_akeneo.mapping.sourceType', 'Source type')}</th>\n <th className=\"px-3 py-2 font-medium\">{t('sync_akeneo.mapping.sourceCode', 'Akeneo code')}</th>\n <th className=\"px-3 py-2 font-medium\">{t('sync_akeneo.customFields.columns.target', 'Target')}</th>\n <th className=\"px-3 py-2 font-medium\">{t('sync_akeneo.mapping.fieldsetCode', 'Fieldset code')}</th>\n <th className=\"px-3 py-2 font-medium\">{t('sync_akeneo.mapping.fieldsetLabel', 'Fieldset label')}</th>\n <th className=\"px-3 py-2 font-medium\">{t('sync_akeneo.mapping.fieldsetDescription', 'Description')}</th>\n <th className=\"px-3 py-2 font-medium\">{t('sync_akeneo.customFields.columns.actions', 'Actions')}</th>\n </tr>\n </thead>\n <tbody>\n {fieldsetMappingRows.length > 0 ? fieldsetMappingRows.map((row, index) => (\n <tr key={`fieldset-mapping-${index}`} className=\"border-t\">\n <td className=\"px-3 py-2\">\n <select\n className=\"flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm\"\n value={row.sourceType}\n onChange={(event) => {\n const nextRows = [...fieldsetMappingRows]\n nextRows[index] = {\n ...row,\n sourceType: event.target.value === 'familyVariant' ? 'familyVariant' : 'family',\n }\n updateFieldsetMappingRows(nextRows)\n }}\n disabled={isLoading || isSaving}\n >\n <option value=\"family\">{t('sync_akeneo.mapping.sourceType.family', 'Family')}</option>\n <option value=\"familyVariant\">{t('sync_akeneo.mapping.sourceType.familyVariant', 'Family variant')}</option>\n </select>\n </td>\n <td className=\"px-3 py-2\">\n <Input\n value={row.sourceCode}\n onChange={(event) => {\n const nextRows = [...fieldsetMappingRows]\n const sourceCode = event.target.value\n nextRows[index] = {\n ...row,\n sourceCode,\n fieldsetCode: row.fieldsetCode || buildAkeneoFieldsetCode(row.target, sourceCode) || '',\n }\n updateFieldsetMappingRows(nextRows)\n }}\n disabled={isLoading || isSaving}\n list={row.sourceType === 'family' ? 'akeneo-families' : undefined}\n />\n </td>\n <td className=\"px-3 py-2\">\n <select\n className=\"flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm\"\n value={row.target}\n onChange={(event) => {\n const nextRows = [...fieldsetMappingRows]\n const target = event.target.value === 'variant' ? 'variant' : 'product'\n nextRows[index] = {\n ...row,\n target,\n fieldsetCode: buildAkeneoFieldsetCode(target, row.sourceCode) || row.fieldsetCode,\n }\n updateFieldsetMappingRows(nextRows)\n }}\n disabled={isLoading || isSaving}\n >\n <option value=\"product\">{t('sync_akeneo.customFields.targets.product', 'Product')}</option>\n <option value=\"variant\">{t('sync_akeneo.customFields.targets.variant', 'Variant')}</option>\n </select>\n </td>\n <td className=\"px-3 py-2\">\n <Input\n value={row.fieldsetCode}\n onChange={(event) => {\n const nextRows = [...fieldsetMappingRows]\n nextRows[index] = { ...row, fieldsetCode: normalizeFieldKey(event.target.value) }\n updateFieldsetMappingRows(nextRows)\n }}\n disabled={isLoading || isSaving}\n />\n </td>\n <td className=\"px-3 py-2\">\n <Input\n value={row.fieldsetLabel}\n onChange={(event) => {\n const nextRows = [...fieldsetMappingRows]\n nextRows[index] = { ...row, fieldsetLabel: event.target.value }\n updateFieldsetMappingRows(nextRows)\n }}\n disabled={isLoading || isSaving}\n />\n </td>\n <td className=\"px-3 py-2\">\n <Input\n value={row.description}\n onChange={(event) => {\n const nextRows = [...fieldsetMappingRows]\n nextRows[index] = { ...row, description: event.target.value }\n updateFieldsetMappingRows(nextRows)\n }}\n disabled={isLoading || isSaving}\n />\n </td>\n <td className=\"px-3 py-2\">\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n onClick={() => updateFieldsetMappingRows(fieldsetMappingRows.filter((_, rowIndex) => rowIndex !== index))}\n disabled={isLoading || isSaving}\n >\n <Trash2 className=\"mr-2 h-4 w-4\" />\n {t('sync_akeneo.customFields.actions.remove', 'Remove')}\n </Button>\n </td>\n </tr>\n )) : (\n <tr>\n <td colSpan={7} className=\"px-3 py-6 text-center text-sm text-muted-foreground\">\n {t('sync_akeneo.mapping.emptyFieldsets', 'No family fieldset mappings discovered yet. Save credentials and use Refresh discovery to generate them.')}\n </td>\n </tr>\n )}\n </tbody>\n </table>\n </div>\n </div>\n </div>\n\n <div className=\"flex flex-wrap gap-3\">\n <label className=\"flex items-center gap-2 text-sm\">\n <input\n type=\"checkbox\"\n checked={state.includeTextAttributes}\n onChange={(event) => setState((current) => ({ ...current, includeTextAttributes: event.target.checked }))}\n disabled={isLoading || isSaving}\n />\n <span>{t('sync_akeneo.mapping.includeText', 'Include text attributes in generated family schemas')}</span>\n </label>\n <label className=\"flex items-center gap-2 text-sm\">\n <input\n type=\"checkbox\"\n checked={state.includeNumericAttributes}\n onChange={(event) => setState((current) => ({ ...current, includeNumericAttributes: event.target.checked }))}\n disabled={isLoading || isSaving}\n />\n <span>{t('sync_akeneo.mapping.includeNumeric', 'Include numeric and metric attributes in generated family schemas')}</span>\n </label>\n <label className=\"flex items-center gap-2 text-sm\">\n <input\n type=\"checkbox\"\n checked={state.createMissingChannels}\n onChange={(event) => setState((current) => ({ ...current, createMissingChannels: event.target.checked }))}\n disabled={isLoading || isSaving}\n />\n <span>{t('sync_akeneo.mapping.createMissingChannels', 'Create missing Open Mercato sales channels from Akeneo scopes by default')}</span>\n </label>\n <label className=\"flex items-center gap-2 text-sm\">\n <input\n type=\"checkbox\"\n checked={state.syncAssociations}\n onChange={(event) => setState((current) => ({ ...current, syncAssociations: event.target.checked }))}\n disabled={isLoading || isSaving}\n />\n <span>{t('sync_akeneo.mapping.syncAssociations', 'Import Akeneo associations into product/variant relation records')}</span>\n </label>\n </div>\n\n <div className=\"space-y-3 rounded-md border p-3\">\n <div>\n <h4 className=\"text-sm font-medium\">{t('sync_akeneo.mapping.reconciliation.title', 'Reconciliation and deletions')}</h4>\n <p className=\"text-xs text-muted-foreground\">\n {t('sync_akeneo.mapping.reconciliation.help', 'These cleanup rules apply during full syncs. Incremental syncs continue to upsert changed records, while stale Akeneo-managed offers, prices, and media are reconciled per product on every product import.')}\n </p>\n </div>\n <div className=\"grid gap-2 md:grid-cols-2\">\n {[\n ['deactivateMissingCategories', 'Deactivate categories missing from Akeneo'],\n ['deactivateMissingProducts', 'Deactivate products and variants missing from Akeneo'],\n ['deactivateMissingAttributes', 'Deactivate Akeneo-managed schemas and custom fields missing from Akeneo'],\n ['deleteMissingOffers', 'Delete Akeneo-managed offers no longer produced by mapping'],\n ['deleteMissingPrices', 'Delete Akeneo-managed prices no longer produced by mapping'],\n ['deleteMissingMedia', 'Delete stale Akeneo-managed images/default media'],\n ['deleteMissingAttachments', 'Delete stale Akeneo-managed file attachments'],\n ].map(([key, label]) => (\n <label key={key} className=\"flex items-center gap-2 text-sm\">\n <input\n type=\"checkbox\"\n checked={state.reconciliation[key as keyof AkeneoReconciliationSettings]}\n onChange={(event) => setState((current) => ({\n ...current,\n reconciliation: {\n ...current.reconciliation,\n [key]: event.target.checked,\n },\n }))}\n disabled={isLoading || isSaving}\n />\n <span>{t(`sync_akeneo.mapping.reconciliation.${key}`, label)}</span>\n </label>\n ))}\n </div>\n </div>\n\n <div className=\"flex justify-end\">\n <Button type=\"button\" onClick={() => void saveMappings()} disabled={isLoading || isSaving}>\n <Save className=\"mr-2 h-4 w-4\" />\n {isSaving ? t('sync_akeneo.mapping.saving', 'Saving...') : t('sync_akeneo.mapping.save', 'Save mappings')}\n </Button>\n </div>\n </div>\n\n <div className=\"space-y-4 rounded-lg border p-4\">\n <div>\n <h4 className=\"text-sm font-medium\">{t('sync_akeneo.discovery.heading', 'Discovered Akeneo fields')}</h4>\n <p className=\"text-sm text-muted-foreground\">\n {t('sync_akeneo.discovery.help', 'These values come from the current Akeneo credentials and are safe to paste into the mapping inputs.')}\n </p>\n </div>\n <div className=\"space-y-3\">\n <div>\n <div className=\"mb-2 text-xs font-medium uppercase text-muted-foreground\">{t('sync_akeneo.discovery.locales', 'Locales')}</div>\n <div className=\"flex flex-wrap gap-2\">\n {(discovery?.locales ?? []).map((locale) => (\n <span key={locale.code} className=\"rounded border px-2 py-1 text-xs\">\n {locale.code}\n </span>\n ))}\n </div>\n </div>\n <div>\n <div className=\"mb-2 text-xs font-medium uppercase text-muted-foreground\">{t('sync_akeneo.discovery.channels', 'Channels')}</div>\n <div className=\"flex flex-wrap gap-2\">\n {(discovery?.channels ?? []).map((channel) => (\n <span key={channel.code} className=\"rounded border px-2 py-1 text-xs\">\n {channel.code}\n </span>\n ))}\n </div>\n </div>\n <div>\n <div className=\"mb-2 text-xs font-medium uppercase text-muted-foreground\">{t('sync_akeneo.discovery.families', 'Families')}</div>\n <div className=\"flex flex-wrap gap-2\">\n {(discovery?.families ?? []).slice(0, 20).map((family) => (\n <span key={family.code} className=\"rounded border px-2 py-1 text-xs\">\n {family.code}\n </span>\n ))}\n </div>\n </div>\n <div>\n <div className=\"mb-2 text-xs font-medium uppercase text-muted-foreground\">{t('sync_akeneo.discovery.localChannels', 'Open Mercato channels')}</div>\n <div className=\"flex flex-wrap gap-2\">\n {(discovery?.localChannels ?? []).map((channel) => (\n <span key={channel.code} className=\"rounded border px-2 py-1 text-xs\">\n {channel.code}\n </span>\n ))}\n </div>\n </div>\n <div>\n <div className=\"mb-2 text-xs font-medium uppercase text-muted-foreground\">{t('sync_akeneo.discovery.priceKinds', 'Catalog price kinds')}</div>\n <div className=\"flex flex-wrap gap-2\">\n {(discovery?.priceKinds ?? []).map((priceKind) => (\n <span key={priceKind.code} className=\"rounded border px-2 py-1 text-xs\">\n {priceKind.code}\n </span>\n ))}\n </div>\n </div>\n <div>\n <div className=\"mb-2 text-xs font-medium uppercase text-muted-foreground\">{t('sync_akeneo.discovery.attributes', 'Attributes')}</div>\n <div className=\"max-h-80 space-y-2 overflow-auto pr-1\">\n {(discovery?.attributes ?? []).map((attribute) => (\n <div key={attribute.code} className=\"rounded border p-2 text-xs\">\n <div className=\"font-medium\">{attribute.code}</div>\n <div className=\"text-muted-foreground\">\n {attribute.type}\n {attribute.localizable ? ' | localizable' : ''}\n {attribute.scopable ? ' | channel-scoped' : ''}\n {attribute.group ? ` | group:${attribute.group}` : ''}\n {attribute.metricFamily ? ` | metric:${attribute.metricFamily}` : ''}\n </div>\n </div>\n ))}\n </div>\n </div>\n </div>\n </div>\n </div>\n\n <datalist id=\"akeneo-attributes\">\n {attributeCodes.map((code) => (\n <option key={code} value={code} />\n ))}\n </datalist>\n <datalist id=\"akeneo-locales\">\n {(discovery?.locales ?? []).map((locale) => (\n <option key={locale.code} value={locale.code} />\n ))}\n </datalist>\n <datalist id=\"akeneo-channels\">\n {(discovery?.channels ?? []).map((channel) => (\n <option key={channel.code} value={channel.code} />\n ))}\n </datalist>\n <datalist id=\"akeneo-families\">\n {(discovery?.families ?? []).map((family) => (\n <option key={family.code} value={family.code} />\n ))}\n </datalist>\n </div>\n\n <Dialog open={customFieldDialogOpen} onOpenChange={setCustomFieldDialogOpen}>\n <DialogContent\n className=\"sm:max-w-5xl\"\n onKeyDown={(event) => {\n if ((event.metaKey || event.ctrlKey) && event.key === 'Enter') {\n event.preventDefault()\n applyCustomFieldEditor()\n }\n }}\n >\n <DialogHeader>\n <DialogTitle>{t('sync_akeneo.customFields.dialog.title', 'Akeneo custom field editor')}</DialogTitle>\n <DialogDescription>\n {t('sync_akeneo.customFields.dialog.description', 'Edit structured custom-field mappings, review which local field definitions already exist, generate missing ones immediately, or mark specific Akeneo attributes to be skipped during import.')}\n </DialogDescription>\n </DialogHeader>\n\n <div className=\"space-y-4\">\n <div className=\"flex flex-wrap items-center gap-2\">\n <span className=\"rounded border px-2 py-1 text-xs\">\n {t('sync_akeneo.customFields.dialog.summary.total', `${customFieldEditorRows.length} mapping rows`)}\n </span>\n <span className={`rounded border px-2 py-1 text-xs ${dialogMissingCustomFieldCount > 0 ? 'border-amber-300 text-amber-700' : ''}`}>\n {dialogMissingCustomFieldCount > 0\n ? t('sync_akeneo.customFields.dialog.summary.missing', `${dialogMissingCustomFieldCount} rows missing local fields`)\n : t('sync_akeneo.customFields.dialog.summary.ready', 'Everything in this mapping already exists locally')}\n </span>\n </div>\n\n <div className=\"overflow-x-auto rounded-lg border\">\n <table className=\"w-full min-w-[780px] text-sm\">\n <thead className=\"bg-muted/50 text-left\">\n <tr>\n <th className=\"px-3 py-2 font-medium\">{t('sync_akeneo.customFields.columns.attribute', 'Akeneo attribute')}</th>\n <th className=\"px-3 py-2 font-medium\">{t('sync_akeneo.customFields.columns.skip', 'Skip import')}</th>\n <th className=\"px-3 py-2 font-medium\">{t('sync_akeneo.customFields.columns.target', 'Target')}</th>\n <th className=\"px-3 py-2 font-medium\">{t('sync_akeneo.customFields.columns.key', 'Field key')}</th>\n <th className=\"px-3 py-2 font-medium\">{t('sync_akeneo.customFields.columns.kind', 'Kind')}</th>\n <th className=\"px-3 py-2 font-medium\">{t('sync_akeneo.customFields.columns.status', 'Status')}</th>\n <th className=\"px-3 py-2 font-medium\">{t('sync_akeneo.customFields.columns.actions', 'Actions')}</th>\n </tr>\n </thead>\n <tbody>\n {customFieldEditorRows.length > 0 ? customFieldEditorRows.map((row, index) => {\n const exists = row.target === 'product'\n ? productFieldKeys.has(row.fieldKey.trim())\n : variantFieldKeys.has(row.fieldKey.trim())\n return (\n <tr key={`${row.attributeCode}:${row.fieldKey}:${index}`} className={`border-t ${row.skip ? 'opacity-70' : ''}`}>\n <td className=\"px-3 py-2\">\n <Input\n list=\"akeneo-attributes\"\n value={row.attributeCode}\n onChange={(event) => {\n const nextRows = [...customFieldEditorRows]\n nextRows[index] = { ...row, attributeCode: event.target.value }\n setCustomFieldEditorRows(nextRows)\n }}\n disabled={isLoading || isSaving || isCreatingCustomFields}\n />\n </td>\n <td className=\"px-3 py-2\">\n <label className=\"flex items-center justify-center\">\n <input\n type=\"checkbox\"\n checked={row.skip}\n onChange={(event) => {\n const nextRows = [...customFieldEditorRows]\n nextRows[index] = {\n ...row,\n skip: event.target.checked,\n fieldKey: row.fieldKey || normalizeFieldKey(row.attributeCode),\n }\n setCustomFieldEditorRows(nextRows)\n }}\n disabled={isLoading || isSaving || isCreatingCustomFields}\n />\n </label>\n </td>\n <td className=\"px-3 py-2\">\n <select\n className=\"flex h-10 w-full rounded-md border border-input bg-background px-3 py-2\"\n value={row.target}\n onChange={(event) => {\n const nextRows = [...customFieldEditorRows]\n nextRows[index] = { ...row, target: event.target.value === 'variant' ? 'variant' : 'product' }\n setCustomFieldEditorRows(nextRows)\n }}\n disabled={isLoading || isSaving || isCreatingCustomFields}\n >\n <option value=\"product\">{t('sync_akeneo.customFields.targets.product', 'Product')}</option>\n <option value=\"variant\">{t('sync_akeneo.customFields.targets.variant', 'Variant')}</option>\n </select>\n </td>\n <td className=\"px-3 py-2\">\n <Input\n value={row.fieldKey}\n onChange={(event) => {\n const nextRows = [...customFieldEditorRows]\n nextRows[index] = { ...row, fieldKey: normalizeFieldKey(event.target.value) }\n setCustomFieldEditorRows(nextRows)\n }}\n disabled={isLoading || isSaving || isCreatingCustomFields}\n />\n </td>\n <td className=\"px-3 py-2\">\n <select\n className=\"flex h-10 w-full rounded-md border border-input bg-background px-3 py-2\"\n value={row.kind}\n onChange={(event) => {\n const nextRows = [...customFieldEditorRows]\n nextRows[index] = {\n ...row,\n kind: event.target.value === ''\n ? ''\n : event.target.value as CustomFieldRow['kind'],\n }\n setCustomFieldEditorRows(nextRows)\n }}\n disabled={isLoading || isSaving || isCreatingCustomFields}\n >\n <option value=\"\">{t('sync_akeneo.customFields.kinds.auto', 'Auto')}</option>\n <option value=\"text\">text</option>\n <option value=\"multiline\">multiline</option>\n <option value=\"integer\">integer</option>\n <option value=\"float\">float</option>\n <option value=\"boolean\">boolean</option>\n <option value=\"select\">select</option>\n </select>\n </td>\n <td className=\"px-3 py-2\">\n {row.skip ? renderSkippedCustomFieldBadge() : renderCustomFieldStatusBadge(exists)}\n </td>\n <td className=\"px-3 py-2\">\n <Button\n type=\"button\"\n variant=\"ghost\"\n onClick={() => {\n const nextRows = customFieldEditorRows.filter((_, rowIndex) => rowIndex !== index)\n setCustomFieldEditorRows(nextRows)\n }}\n disabled={isLoading || isSaving || isCreatingCustomFields}\n >\n <Trash2 className=\"mr-2 h-4 w-4\" />\n {t('sync_akeneo.customFields.actions.remove', 'Remove')}\n </Button>\n </td>\n </tr>\n )\n }) : (\n <tr>\n <td colSpan={7} className=\"px-3 py-6 text-center text-sm text-muted-foreground\">\n {t('sync_akeneo.customFields.empty', 'No Akeneo custom fields are mapped yet. Use the suggestions below or add a row manually.')}\n </td>\n </tr>\n )}\n </tbody>\n </table>\n </div>\n\n <div className=\"flex flex-wrap gap-2\">\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={() => setCustomFieldEditorRows([\n ...customFieldEditorRows,\n { attributeCode: '', target: 'product', fieldKey: '', kind: '', skip: false },\n ])}\n disabled={isLoading || isSaving || isCreatingCustomFields}\n >\n <Plus className=\"mr-2 h-4 w-4\" />\n {t('sync_akeneo.customFields.actions.add', 'Add row')}\n </Button>\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={() => void createMissingCustomFields(customFieldEditorRows)}\n disabled={isLoading || isSaving || isCreatingCustomFields || customFieldEditorRows.length === 0}\n >\n {isCreatingCustomFields ? <RefreshCw className=\"mr-2 h-4 w-4 animate-spin\" /> : <Sparkles className=\"mr-2 h-4 w-4\" />}\n {isCreatingCustomFields\n ? t('sync_akeneo.customFields.actions.creating', 'Creating...')\n : t('sync_akeneo.customFields.actions.createMissing', 'Pre-create missing fields now')}\n </Button>\n </div>\n\n <div className=\"rounded-lg border p-4\">\n <div className=\"mb-3\">\n <h4 className=\"text-sm font-medium\">{t('sync_akeneo.customFields.suggestions.title', 'Suggested Akeneo attributes')}</h4>\n <p className=\"text-xs text-muted-foreground\">\n {t('sync_akeneo.customFields.suggestions.help', 'Quick-add discovered attributes that are not yet part of the Akeneo custom-field mapping.')}\n </p>\n </div>\n <div className=\"flex flex-wrap gap-2\">\n {suggestedCustomFieldAttributes.map((attribute) => (\n <Button\n key={attribute.code}\n type=\"button\"\n variant=\"outline\"\n onClick={() => {\n setCustomFieldEditorRows([\n ...customFieldEditorRows,\n {\n attributeCode: attribute.code,\n target: 'product',\n fieldKey: normalizeFieldKey(`akeneo_${attribute.code}`),\n kind: inferCustomFieldKind(attribute.type),\n skip: false,\n },\n ])\n }}\n disabled={isLoading || isSaving || isCreatingCustomFields}\n >\n <Plus className=\"mr-2 h-4 w-4\" />\n {attribute.code}\n </Button>\n ))}\n </div>\n </div>\n </div>\n\n <DialogFooter>\n <Button\n type=\"button\"\n onClick={() => applyCustomFieldEditor()}\n disabled={isCreatingCustomFields}\n >\n <Save className=\"mr-2 h-4 w-4\" />\n {t('sync_akeneo.customFields.dialog.apply', 'Apply')}\n </Button>\n <Button type=\"button\" variant=\"outline\" onClick={() => setCustomFieldDialogOpen(false)} disabled={isCreatingCustomFields}>\n <X className=\"mr-2 h-4 w-4\" />\n {t('sync_akeneo.customFields.dialog.close', 'Close')}\n </Button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n {ConfirmDialogElement}\n </div>\n )\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@open-mercato/sync-akeneo",
|
|
3
|
-
"version": "0.5.1-develop.
|
|
3
|
+
"version": "0.5.1-develop.2683.4878a05b8e",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -52,18 +52,18 @@
|
|
|
52
52
|
}
|
|
53
53
|
},
|
|
54
54
|
"dependencies": {
|
|
55
|
-
"@open-mercato/core": "0.5.1-develop.
|
|
56
|
-
"@open-mercato/ui": "0.5.1-develop.
|
|
55
|
+
"@open-mercato/core": "0.5.1-develop.2683.4878a05b8e",
|
|
56
|
+
"@open-mercato/ui": "0.5.1-develop.2683.4878a05b8e",
|
|
57
57
|
"node-html-markdown": "^2.0.0"
|
|
58
58
|
},
|
|
59
59
|
"peerDependencies": {
|
|
60
60
|
"@mikro-orm/postgresql": "^6.6.10",
|
|
61
|
-
"@open-mercato/shared": "0.5.1-develop.
|
|
61
|
+
"@open-mercato/shared": "0.5.1-develop.2683.4878a05b8e",
|
|
62
62
|
"react": "^19.0.0",
|
|
63
63
|
"react-dom": "^19.0.0"
|
|
64
64
|
},
|
|
65
65
|
"devDependencies": {
|
|
66
|
-
"@open-mercato/shared": "0.5.1-develop.
|
|
66
|
+
"@open-mercato/shared": "0.5.1-develop.2683.4878a05b8e",
|
|
67
67
|
"@types/jest": "^30.0.0",
|
|
68
68
|
"esbuild": "^0.28.0",
|
|
69
69
|
"glob": "^13.0.6",
|
|
@@ -8,7 +8,7 @@ import { apiCall } from '@open-mercato/ui/backend/utils/apiCall'
|
|
|
8
8
|
import { useConfirmDialog } from '@open-mercato/ui/backend/confirm-dialog'
|
|
9
9
|
import { flash } from '@open-mercato/ui/backend/FlashMessages'
|
|
10
10
|
import { NextStepCallout } from '@open-mercato/ui/backend/NextStepCallout'
|
|
11
|
-
import {
|
|
11
|
+
import { Alert, AlertDescription, AlertTitle } from '@open-mercato/ui/primitives/alert'
|
|
12
12
|
import { Badge } from '@open-mercato/ui/primitives/badge'
|
|
13
13
|
import { Button } from '@open-mercato/ui/primitives/button'
|
|
14
14
|
import { Progress } from '@open-mercato/ui/primitives/progress'
|
|
@@ -1452,17 +1452,20 @@ export default function AkeneoConfigWidget({ context, data }: InjectionWidgetCom
|
|
|
1452
1452
|
<h3 className="text-sm font-semibold">
|
|
1453
1453
|
{t('sync_akeneo.setup.heading', 'Akeneo API setup')}
|
|
1454
1454
|
</h3>
|
|
1455
|
-
<
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1455
|
+
<Alert variant="info">
|
|
1456
|
+
<AlertDescription>
|
|
1457
|
+
{t('sync_akeneo.setup.scheduleTab', 'Run once and recurring schedules now live in the dedicated Sync schedules tab, shared by all data sync integrations.')}
|
|
1458
|
+
</AlertDescription>
|
|
1459
|
+
</Alert>
|
|
1460
|
+
<Alert variant="info">
|
|
1461
|
+
<AlertTitle>{t('sync_akeneo.setup.order.title', 'Recommended sync order')}</AlertTitle>
|
|
1462
|
+
<AlertDescription>
|
|
1463
|
+
{t(
|
|
1464
|
+
'sync_akeneo.setup.order.message',
|
|
1465
|
+
'Run category sync first, attribute sync second, and product sync last. Product import expects local categories and family-based schemas to exist already.',
|
|
1466
|
+
)}
|
|
1467
|
+
</AlertDescription>
|
|
1468
|
+
</Alert>
|
|
1466
1469
|
{shouldShowFirstImportCallout ? (
|
|
1467
1470
|
<NextStepCallout
|
|
1468
1471
|
icon={<Sparkles className="h-6 w-6" />}
|
|
@@ -1611,9 +1614,9 @@ export default function AkeneoConfigWidget({ context, data }: InjectionWidgetCom
|
|
|
1611
1614
|
) : null}
|
|
1612
1615
|
|
|
1613
1616
|
{discovery?.message ? (
|
|
1614
|
-
<
|
|
1615
|
-
{discovery.message}
|
|
1616
|
-
</
|
|
1617
|
+
<Alert variant={discovery.ok ? 'info' : 'warning'}>
|
|
1618
|
+
<AlertDescription>{discovery.message}</AlertDescription>
|
|
1619
|
+
</Alert>
|
|
1617
1620
|
) : null}
|
|
1618
1621
|
|
|
1619
1622
|
<div className="grid gap-6 xl:grid-cols-[1.2fr_0.8fr]">
|
|
@@ -1828,9 +1831,11 @@ export default function AkeneoConfigWidget({ context, data }: InjectionWidgetCom
|
|
|
1828
1831
|
</table>
|
|
1829
1832
|
</div>
|
|
1830
1833
|
) : (
|
|
1831
|
-
<
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
+
<Alert variant="info">
|
|
1835
|
+
<AlertDescription>
|
|
1836
|
+
{t('sync_akeneo.customFields.empty', 'No Akeneo custom fields are shown yet. They are discovered and mapped automatically after credentials are saved or when you use Refresh discovery. Use the editor only if you want to review or override the automatic mapping.')}
|
|
1837
|
+
</AlertDescription>
|
|
1838
|
+
</Alert>
|
|
1834
1839
|
)}
|
|
1835
1840
|
{customFieldRows.length > 0 ? (
|
|
1836
1841
|
<div className="flex flex-wrap gap-2 text-xs">
|