@dainamite/cpq 0.2.2 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +44 -0
- package/MIGRATION.md +31 -1
- package/README.md +17 -12
- package/dist/modules/cpq/api/product-attributes/route.js +28 -53
- package/dist/modules/cpq/api/product-attributes/route.js.map +2 -2
- package/dist/modules/cpq/api/product-charges/route.js +12 -2
- package/dist/modules/cpq/api/product-charges/route.js.map +2 -2
- package/dist/modules/cpq/api/product-offerings/route.js +2 -0
- package/dist/modules/cpq/api/product-offerings/route.js.map +2 -2
- package/dist/modules/cpq/backend/cpq/offerings/[id]/page.js +128 -59
- package/dist/modules/cpq/backend/cpq/offerings/[id]/page.js.map +2 -2
- package/dist/modules/cpq/backend/cpq/pricing/[id]/EntriesEditor.js +11 -11
- package/dist/modules/cpq/backend/cpq/pricing/[id]/EntriesEditor.js.map +2 -2
- package/dist/modules/cpq/backend/cpq/specifications/[id]/page.js +55 -1
- package/dist/modules/cpq/backend/cpq/specifications/[id]/page.js.map +2 -2
- package/dist/modules/cpq/cli.js +58 -4
- package/dist/modules/cpq/cli.js.map +3 -3
- package/dist/modules/cpq/data/charge-pricing.js +12 -0
- package/dist/modules/cpq/data/charge-pricing.js.map +7 -0
- package/dist/modules/cpq/data/entities.js +3 -0
- package/dist/modules/cpq/data/entities.js.map +2 -2
- package/dist/modules/cpq/data/validators.js +36 -15
- package/dist/modules/cpq/data/validators.js.map +2 -2
- package/dist/modules/cpq/events.js +7 -0
- package/dist/modules/cpq/events.js.map +2 -2
- package/dist/modules/cpq/lib/seeds/demo.js +103 -0
- package/dist/modules/cpq/lib/seeds/demo.js.map +7 -0
- package/dist/modules/cpq/migrations/Migration20260602000000_cpq_charge_model_split.js +28 -0
- package/dist/modules/cpq/migrations/Migration20260602000000_cpq_charge_model_split.js.map +7 -0
- package/dist/modules/cpq/services/cpqOrderService.js +130 -76
- package/dist/modules/cpq/services/cpqOrderService.js.map +2 -2
- package/dist/modules/cpq/services/cpqPricingService.js +53 -29
- package/dist/modules/cpq/services/cpqPricingService.js.map +3 -3
- package/dist/modules/cpq/services/types.js.map +2 -2
- package/package.json +4 -2
- package/src/modules/cpq/__integration__/TC-CPQ-012.spec.ts +34 -4
- package/src/modules/cpq/__tests__/package-isolation.test.ts +8 -3
- package/src/modules/cpq/api/product-attributes/__tests__/serializeAttribute.test.ts +62 -0
- package/src/modules/cpq/api/product-attributes/route.ts +34 -52
- package/src/modules/cpq/api/product-charges/route.ts +23 -2
- package/src/modules/cpq/api/product-offerings/route.ts +2 -0
- package/src/modules/cpq/backend/cpq/offerings/[id]/page.tsx +151 -62
- package/src/modules/cpq/backend/cpq/pricing/[id]/EntriesEditor.tsx +24 -22
- package/src/modules/cpq/backend/cpq/specifications/[id]/page.tsx +73 -1
- package/src/modules/cpq/cli.ts +83 -4
- package/src/modules/cpq/data/__tests__/charge-pricing.test.ts +49 -0
- package/src/modules/cpq/data/__tests__/validators.test.ts +60 -5
- package/src/modules/cpq/data/charge-pricing.ts +48 -0
- package/src/modules/cpq/data/entities.ts +10 -0
- package/src/modules/cpq/data/validators.ts +56 -26
- package/src/modules/cpq/events.ts +11 -3
- package/src/modules/cpq/lib/seeds/__tests__/demo.test.ts +78 -0
- package/src/modules/cpq/lib/seeds/demo.ts +145 -0
- package/src/modules/cpq/migrations/.snapshot-open-mercato.json +16 -0
- package/src/modules/cpq/migrations/Migration20260602000000_cpq_charge_model_split.ts +57 -0
- package/src/modules/cpq/services/__tests__/cpqPricingService.test.ts +172 -1
- package/src/modules/cpq/services/cpqOrderService.ts +214 -103
- package/src/modules/cpq/services/cpqPricingService.ts +82 -34
- package/src/modules/cpq/services/types.ts +4 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../../../src/modules/cpq/backend/cpq/specifications/%5Bid%5D/page.tsx"],
|
|
4
|
-
"sourcesContent": ["\"use client\"\nimport * as React from 'react'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { useParams, useRouter } from 'next/navigation'\nimport { Tag } from '@open-mercato/ui/primitives/tag'\nimport { Alert } from '@open-mercato/ui/primitives/alert'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { NumberInput } from '../../../../components/NumberInput'\nimport {\n formatStatusLabel,\n lifecycleStatusMap,\n specificationLifecycleStatusMap,\n type LifecycleStatus,\n type SpecificationLifecycleStatus,\n} from '../../../../components/statusMaps'\nimport { DependsOnRulesEditor } from './DependsOnRulesEditor'\n\n// \u2500\u2500\u2500 Types \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n// Attribute \u2192 attribute dependency contract. The validator\n// (`cpqValidationService.validateAttributes`) reads `attributeCode` to look\n// up the parent value and walks `rules[].when` to decide what happens to\n// this attribute. `effect` controls the interpretation of `rules[].then`:\n//\n// - `filter_options`: `then` is a comma-separated list of allowed values\n// that this attribute may take when the parent matches `when`.\n// - `set_value`: `then` is a single value to assign to this attribute\n// when the parent matches `when`.\n// - `toggle_required`: `then` is a boolean \u2014 `true` makes this attribute\n// required when the parent matches `when`, `false` makes it optional.\n//\n// Storage stays generic (`{ when: string; then: unknown }`) so we don't\n// have to migrate older configs when the surface grows.\nexport type DependsOnEffect = 'filter_options' | 'set_value' | 'toggle_required'\n\nexport type DependsOnRule = {\n when: string\n then: unknown\n}\n\nexport type AttributeDependsOn = {\n attributeCode: string\n effect: DependsOnEffect\n rules: DependsOnRule[]\n}\n\ntype Specification = {\n id: string\n productId: string\n code: string\n name: string\n description: string | null\n specType: string\n isAssetizable: boolean\n lifecycleStatus: string\n version: number\n effectiveFrom: string | null\n effectiveTo: string | null\n metadata: Record<string, unknown> | null\n isActive: boolean\n}\n\ntype Attribute = {\n id: string\n code: string\n name: string\n attributeType: string\n resolutionTime: string\n options: Array<{ value: string; label: string }> | null\n constraints: Record<string, unknown> | null\n referenceEntity: string | null\n referenceFilter: Record<string, unknown> | null\n dependsOn: AttributeDependsOn | null\n defaultValue: unknown | null\n helpText: string | null\n sortOrder: number\n isRequired: boolean\n isActive: boolean\n}\n\ntype Offering = {\n id: string\n code: string\n name: string\n description: string | null\n offeringType: string\n designTimeValues: Record<string, unknown>\n lifecycleStatus: string\n isActive: boolean\n}\n\ntype BundleSlot = {\n id: string\n specId: string\n targetSpecId: string\n targetSpec: { id: string; code: string; name: string; specType: string } | null\n componentGroup: string\n name: string\n description: string | null\n cardinalityMin: number\n cardinalityMax: number | null\n sortOrder: number\n isActive: boolean\n}\n\ntype EditingSlot = {\n id?: string\n targetSpecId: string\n componentGroup: string\n name: string\n description: string\n cardinalityMin: number\n cardinalityMax: number | null\n sortOrder: number\n}\n\ntype Relationship = {\n id: string\n sourceSpecId: string\n targetSpecId: string\n relationshipType: string\n cardinalityMin: number\n cardinalityMax: number | null\n condition: Record<string, unknown> | null\n isActive: boolean\n}\n\ntype Charge = {\n id: string\n code: string\n name: string\n description: string | null\n chargeType: string\n pricingMethod: string\n pricingTableId: string | null\n priceColumnKey: string | null\n fixedPrice: string | null\n currencyCode: string | null\n quantityAttributeCode: string | null\n applicabilityCondition: Record<string, unknown> | null\n sortOrder: number\n isActive: boolean\n}\n\ntype PricingTableRef = { id: string; code: string; name: string; dimensions: Array<{ key: string; label: string }>; priceColumns: Array<{ key: string; label: string }> }\n\ntype EditingAttribute = Omit<Attribute, 'id'> & { id?: string }\ntype EditingOffering = Omit<Offering, 'id'> & { id?: string }\ntype EditingRelationship = Omit<Relationship, 'id'> & { id?: string }\ntype EditingCharge = Omit<Charge, 'id'> & { id?: string }\n\n// \u2500\u2500\u2500 Defaults \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nconst EMPTY_SPEC = {\n code: '',\n name: '',\n description: '',\n specType: 'simple' as string,\n isAssetizable: false,\n lifecycleStatus: 'draft',\n version: 1,\n effectiveFrom: null as string | null,\n effectiveTo: null as string | null,\n isActive: true,\n}\n\nconst EMPTY_SLOT: EditingSlot = {\n targetSpecId: '',\n componentGroup: '',\n name: '',\n description: '',\n cardinalityMin: 0,\n cardinalityMax: null,\n sortOrder: 0,\n}\n\nconst EMPTY_ATTRIBUTE: EditingAttribute = {\n code: '',\n name: '',\n attributeType: 'text',\n resolutionTime: 'run_time',\n options: null,\n constraints: null,\n referenceEntity: null,\n referenceFilter: null,\n dependsOn: null,\n defaultValue: null,\n helpText: null,\n sortOrder: 0,\n isRequired: true,\n isActive: true,\n}\n\nconst EMPTY_OFFERING: EditingOffering = {\n code: '',\n name: '',\n description: null,\n offeringType: 'simple',\n designTimeValues: {},\n lifecycleStatus: 'draft',\n isActive: true,\n}\n\nconst EMPTY_CHARGE: EditingCharge = {\n code: '',\n name: '',\n description: null,\n chargeType: 'mrc',\n pricingMethod: 'flat',\n pricingTableId: null,\n priceColumnKey: null,\n fixedPrice: null,\n currencyCode: null,\n quantityAttributeCode: null,\n applicabilityCondition: null,\n sortOrder: 0,\n isActive: true,\n}\n\nconst EMPTY_RELATIONSHIP: EditingRelationship = {\n sourceSpecId: '',\n targetSpecId: '',\n relationshipType: 'requires',\n cardinalityMin: 0,\n cardinalityMax: null,\n condition: null,\n isActive: true,\n}\n\n// \u2500\u2500\u2500 Component \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport default function SpecificationDetailPage(props: { params?: { id?: string } }) {\n const t = useT()\n const router = useRouter()\n const urlParams = useParams()\n const specId = (props.params?.id ?? urlParams?.id) as string\n const isNew = specId === 'new'\n\n // \u2500\u2500\u2500 State \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n const [tab, setTab] = React.useState<'general' | 'attributes' | 'offerings' | 'relationships' | 'slots'>('general')\n const [form, setForm] = React.useState(EMPTY_SPEC)\n const [attributes, setAttributes] = React.useState<Attribute[]>([])\n const [offerings, setOfferings] = React.useState<Offering[]>([])\n const [relationships, setRelationships] = React.useState<Relationship[]>([])\n const [bundleSlots, setBundleSlots] = React.useState<BundleSlot[]>([])\n const [allSpecs, setAllSpecs] = React.useState<Array<{ id: string; code: string; name: string; specType?: string }>>([])\n\n const [loading, setLoading] = React.useState(!isNew)\n const [saving, setSaving] = React.useState(false)\n const [error, setError] = React.useState<string | null>(null)\n\n const [editingAttr, setEditingAttr] = React.useState<EditingAttribute | null>(null)\n const [editingOffering, setEditingOffering] = React.useState<EditingOffering | null>(null)\n const [editingRel, setEditingRel] = React.useState<EditingRelationship | null>(null)\n const [editingSlot, setEditingSlot] = React.useState<EditingSlot | null>(null)\n const [editingOptions, setEditingOptions] = React.useState<Array<{ value: string; label: string }>>([])\n const [editingDtValues, setEditingDtValues] = React.useState<Record<string, unknown>>({})\n const [selectedOfferingIds, setSelectedOfferingIds] = React.useState<Set<string>>(new Set())\n const [offeringCharges, setOfferingCharges] = React.useState<Record<string, Charge[]>>({})\n const [chargeFormOpen, setChargeFormOpen] = React.useState(false)\n const [chargeForm, setChargeForm] = React.useState({ code: '', name: '', description: '', chargeType: 'mrc', pricingMethod: 'flat' })\n const [chargePrices, setChargePrices] = React.useState<Record<string, string>>({})\n const [chargePricingTableId, setChargePricingTableId] = React.useState<string | null>(null)\n const [chargePriceColumnKey, setChargePriceColumnKey] = React.useState<string | null>(null)\n const [chargeCurrency, setChargeCurrency] = React.useState('USD')\n const [pricingTables, setPricingTables] = React.useState<PricingTableRef[]>([])\n const [conditionJson, setConditionJson] = React.useState('null')\n const [dependsOnAttrCode, setDependsOnAttrCode] = React.useState('')\n const [dependsOnEffect, setDependsOnEffect] = React.useState<DependsOnEffect>('filter_options')\n const [dependsOnEnabled, setDependsOnEnabled] = React.useState(false)\n const [dependsOnRules, setDependsOnRules] = React.useState<DependsOnRule[]>([])\n // OM-standard detail page contract: existing records open in read-only\n // \"view\" mode and require an explicit Edit click to allow editing. New\n // records (`/specifications/new`) skip view mode since there's nothing\n // to display yet.\n const [generalMode, setGeneralMode] = React.useState<'view' | 'edit'>(isNew ? 'edit' : 'view')\n // Snapshot of the form taken when entering edit mode \u2014 used by Cancel to\n // revert local changes without re-fetching.\n const [formSnapshot, setFormSnapshot] = React.useState<typeof EMPTY_SPEC | null>(null)\n\n // \u2500\u2500\u2500 Load data \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n React.useEffect(() => {\n let cancelled = false\n\n async function load() {\n try {\n if (isNew) {\n return\n }\n\n // Load all specs for relationship target selector\n const specsRes = await fetch('/api/cpq/product-specifications?pageSize=200')\n if (specsRes.ok) {\n const d = await specsRes.json()\n if (!cancelled) setAllSpecs(d.items ?? [])\n }\n\n // Load spec detail with nested data\n const res = await fetch(`/api/cpq/product-specifications?id=${encodeURIComponent(specId)}`)\n if (!res.ok) {\n if (!cancelled) setError('Failed to load specification')\n return\n }\n\n const spec = await res.json()\n if (!cancelled) {\n setForm({\n code: spec.code,\n name: spec.name,\n description: spec.description ?? '',\n specType: spec.specType ?? 'simple',\n isAssetizable: spec.isAssetizable ?? false,\n lifecycleStatus: spec.lifecycleStatus,\n version: spec.version,\n effectiveFrom: spec.effectiveFrom,\n effectiveTo: spec.effectiveTo,\n isActive: spec.isActive,\n })\n setAttributes(spec.attributes ?? [])\n setOfferings(spec.offerings ?? [])\n setRelationships(spec.relationships ?? [])\n setBundleSlots(spec.slots ?? [])\n }\n } catch (err) {\n console.error('Failed to load', err)\n if (!cancelled) setError('Failed to load')\n } finally {\n if (!cancelled) setLoading(false)\n }\n }\n\n load()\n return () => { cancelled = true }\n }, [specId, isNew])\n\n // \u2500\u2500\u2500 Save specification \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n const saveSpec = async () => {\n setSaving(true)\n setError(null)\n try {\n const { ...formData } = form\n const payload = isNew\n ? { ...formData, description: formData.description || null }\n : { id: specId, ...formData, description: formData.description || null }\n\n const res = await fetch('/api/cpq/product-specifications', {\n method: isNew ? 'POST' : 'PUT',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(payload),\n })\n\n if (!res.ok) {\n const d = await res.json()\n setError(d.error ?? 'Failed to save')\n return\n }\n\n const saved = await res.json()\n if (isNew) {\n router.push(`/backend/cpq/specifications/${saved.id}`)\n } else {\n setForm({\n code: saved.code,\n name: saved.name,\n description: saved.description ?? '',\n specType: saved.specType ?? form.specType,\n isAssetizable: saved.isAssetizable ?? form.isAssetizable,\n lifecycleStatus: saved.lifecycleStatus,\n version: saved.version,\n effectiveFrom: saved.effectiveFrom,\n effectiveTo: saved.effectiveTo,\n isActive: saved.isActive,\n })\n // Save succeeded \u2014 drop the snapshot and flip back to read-only.\n setFormSnapshot(null)\n setGeneralMode('view')\n }\n } catch {\n setError('Failed to save')\n } finally {\n setSaving(false)\n }\n }\n\n const deleteSpec = async () => {\n if (!confirm(t('cpq.specifications.confirmDelete', 'Delete this specification and all its offerings, attributes and relationships?'))) return\n try {\n const res = await fetch('/api/cpq/product-specifications', {\n method: 'DELETE',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ id: specId }),\n })\n if (res.ok) {\n router.push('/backend/cpq/specifications')\n } else {\n const d = await res.json()\n setError(d.error ?? 'Failed to delete')\n }\n } catch {\n setError('Failed to delete')\n }\n }\n\n // \u2500\u2500\u2500 Attribute CRUD \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n const saveAttribute = async () => {\n if (!editingAttr) return\n setSaving(true)\n setError(null)\n try {\n const options = (editingAttr.attributeType === 'select' || editingAttr.attributeType === 'multi-select')\n ? editingOptions.filter((o) => o.value.trim() !== '')\n : null\n\n const dependsOn: AttributeDependsOn | null =\n dependsOnEnabled && dependsOnAttrCode\n ? {\n attributeCode: dependsOnAttrCode,\n effect: dependsOnEffect,\n rules: dependsOnRules.filter((r) => r.when.trim().length > 0),\n }\n : null\n\n const isEdit = !!editingAttr.id\n const payload = {\n ...editingAttr,\n options,\n dependsOn,\n specId,\n }\n const res = await fetch('/api/cpq/product-attributes', {\n method: isEdit ? 'PUT' : 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(payload),\n })\n if (!res.ok) {\n const d = await res.json()\n setError(d.error ?? 'Failed to save attribute')\n return\n }\n const saved = await res.json()\n if (isEdit) {\n setAttributes((prev) => prev.map((a) => (a.id === saved.id ? saved : a)))\n } else {\n setAttributes((prev) => [...prev, saved])\n }\n setEditingAttr(null)\n } catch {\n setError('Failed to save attribute')\n } finally {\n setSaving(false)\n }\n }\n\n const deleteAttribute = async (attrId: string) => {\n if (!confirm('Delete this attribute?')) return\n try {\n const res = await fetch('/api/cpq/product-attributes', {\n method: 'DELETE',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ id: attrId }),\n })\n if (res.ok) setAttributes((prev) => prev.filter((a) => a.id !== attrId))\n } catch {\n setError('Failed to delete attribute')\n }\n }\n\n const startEditAttr = (attr?: Attribute) => {\n const editing = attr ? { ...attr } : { ...EMPTY_ATTRIBUTE }\n // Normalize legacy 'enum' type to 'select' for the editor\n if (editing.attributeType === 'enum') editing.attributeType = 'select'\n setEditingAttr(editing)\n setEditingOptions(editing.options ? [...editing.options] : [])\n const dep = editing.dependsOn\n setDependsOnEnabled(!!dep)\n setDependsOnAttrCode(dep?.attributeCode ?? '')\n setDependsOnEffect((dep?.effect as DependsOnEffect) ?? 'filter_options')\n setDependsOnRules(Array.isArray(dep?.rules) ? dep.rules : [])\n }\n\n // \u2500\u2500\u2500 Offering CRUD \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n const saveOffering = async () => {\n if (!editingOffering) return\n setSaving(true)\n setError(null)\n try {\n const isEdit = !!editingOffering.id\n const payload = {\n ...editingOffering,\n designTimeValues: editingDtValues,\n specId,\n }\n const res = await fetch('/api/cpq/product-offerings', {\n method: isEdit ? 'PUT' : 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(payload),\n })\n if (!res.ok) {\n const d = await res.json()\n setError(d.error ?? 'Failed to save offering')\n return\n }\n const saved = await res.json()\n if (isEdit) {\n setOfferings((prev) => prev.map((o) => (o.id === saved.id ? saved : o)))\n } else {\n setOfferings((prev) => [...prev, saved])\n }\n setEditingOffering(null)\n } catch {\n setError('Failed to save offering')\n } finally {\n setSaving(false)\n }\n }\n\n const deleteOffering = async (offeringId: string) => {\n if (!confirm('Delete this offering?')) return\n try {\n const res = await fetch('/api/cpq/product-offerings', {\n method: 'DELETE',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ id: offeringId }),\n })\n if (res.ok) setOfferings((prev) => prev.filter((o) => o.id !== offeringId))\n } catch {\n setError('Failed to delete offering')\n }\n }\n\n const startEditOffering = (offering?: Offering) => {\n const editing = offering ? { ...offering } : { ...EMPTY_OFFERING }\n setEditingOffering(editing)\n setEditingDtValues(editing.designTimeValues ? { ...editing.designTimeValues } : {})\n }\n\n // \u2500\u2500\u2500 Charge management (multi-offering) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n const loadAllOfferingCharges = async () => {\n try {\n const results = await Promise.all(\n offerings.map((o) => fetch(`/api/cpq/product-offerings?id=${encodeURIComponent(o.id)}`).then((r) => r.ok ? r.json() : null))\n )\n const chargeMap: Record<string, Charge[]> = {}\n results.forEach((data, idx) => {\n if (data) chargeMap[offerings[idx].id] = data.charges ?? []\n })\n setOfferingCharges(chargeMap)\n } catch {\n console.error('Failed to load charges')\n }\n }\n\n const loadPricingTables = async () => {\n if (pricingTables.length > 0) return\n const res = await fetch('/api/cpq/pricing-tables?pageSize=200')\n if (res.ok) {\n const data = await res.json()\n setPricingTables(data.items ?? [])\n }\n }\n\n const toggleOfferingSelection = (id: string) => {\n setSelectedOfferingIds((prev) => {\n const next = new Set(prev)\n if (next.has(id)) next.delete(id); else next.add(id)\n return next\n })\n }\n\n const toggleAllOfferings = () => {\n if (selectedOfferingIds.size === offerings.length) {\n setSelectedOfferingIds(new Set())\n } else {\n setSelectedOfferingIds(new Set(offerings.map((o) => o.id)))\n }\n }\n\n const openChargeForm = () => {\n setChargeForm({ code: '', name: '', description: '', chargeType: 'mrc', pricingMethod: 'flat' })\n setChargePrices({})\n setChargePricingTableId(null)\n setChargePriceColumnKey(null)\n setChargeCurrency('USD')\n setChargeFormOpen(true)\n loadPricingTables()\n }\n\n const saveChargesForSelected = async () => {\n const targets = offerings.filter((o) => selectedOfferingIds.has(o.id))\n if (!targets.length || !chargeForm.code || !chargeForm.name) return\n setSaving(true)\n setError(null)\n try {\n for (const offering of targets) {\n const chargeCode = targets.length > 1 ? `${offering.code}--${chargeForm.code}` : chargeForm.code\n const payload: Record<string, unknown> = {\n offeringId: offering.id,\n code: chargeCode,\n name: chargeForm.name,\n description: chargeForm.description || null,\n chargeType: chargeForm.chargeType,\n pricingMethod: chargeForm.pricingMethod === 'flat' ? 'flat' : chargeForm.pricingMethod,\n isActive: true,\n sortOrder: 0,\n }\n if (chargeForm.pricingMethod === 'flat') {\n payload.fixedPrice = chargePrices[offering.id] || null\n payload.currencyCode = chargeCurrency\n } else {\n payload.pricingTableId = chargePricingTableId\n payload.priceColumnKey = chargePriceColumnKey\n }\n const res = await fetch('/api/cpq/product-charges', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(payload),\n })\n if (!res.ok) {\n const d = await res.json()\n setError(d.error ?? `Failed to save charge for ${offering.name}`)\n break\n }\n }\n setChargeFormOpen(false)\n await loadAllOfferingCharges()\n } catch {\n setError('Failed to save charges')\n } finally {\n setSaving(false)\n }\n }\n\n const deleteCharge = async (offeringId: string, chargeId: string) => {\n if (!confirm('Delete this charge?')) return\n try {\n const res = await fetch('/api/cpq/product-charges', {\n method: 'DELETE',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ id: chargeId }),\n })\n if (res.ok) {\n setOfferingCharges((prev) => ({\n ...prev,\n [offeringId]: (prev[offeringId] ?? []).filter((c) => c.id !== chargeId),\n }))\n }\n } catch {\n setError('Failed to delete charge')\n }\n }\n\n const selectedPricingTableRef = chargePricingTableId\n ? pricingTables.find((pt) => pt.id === chargePricingTableId)\n : null\n\n // \u2500\u2500\u2500 Relationship CRUD \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n const saveRelationship = async () => {\n if (!editingRel) return\n setSaving(true)\n setError(null)\n try {\n let parsedCondition = editingRel.condition\n try { parsedCondition = conditionJson === 'null' ? null : JSON.parse(conditionJson) } catch { /* keep */ }\n\n const isEdit = !!editingRel.id\n const payload = {\n ...editingRel,\n condition: parsedCondition,\n sourceSpecId: editingRel.sourceSpecId || specId,\n }\n const res = await fetch('/api/cpq/product-relationships', {\n method: isEdit ? 'PUT' : 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(payload),\n })\n if (!res.ok) {\n const d = await res.json()\n setError(d.error ?? 'Failed to save relationship')\n return\n }\n const saved = await res.json()\n if (isEdit) {\n setRelationships((prev) => prev.map((r) => (r.id === saved.id ? saved : r)))\n } else {\n setRelationships((prev) => [...prev, saved])\n }\n setEditingRel(null)\n } catch {\n setError('Failed to save relationship')\n } finally {\n setSaving(false)\n }\n }\n\n const deleteRelationship = async (relId: string) => {\n if (!confirm('Delete this relationship?')) return\n try {\n const res = await fetch('/api/cpq/product-relationships', {\n method: 'DELETE',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ id: relId }),\n })\n if (res.ok) setRelationships((prev) => prev.filter((r) => r.id !== relId))\n } catch {\n setError('Failed to delete relationship')\n }\n }\n\n const startEditRel = (rel?: Relationship) => {\n const editing = rel ? { ...rel } : { ...EMPTY_RELATIONSHIP, sourceSpecId: specId }\n setEditingRel(editing)\n setConditionJson(editing.condition ? JSON.stringify(editing.condition, null, 2) : 'null')\n }\n\n // \u2500\u2500\u2500 Helpers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n const getSpecName = (id: string) => allSpecs.find((s) => s.id === id)?.name ?? id.slice(0, 8)\n\n // \u2500\u2500\u2500 Render \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n if (loading) {\n return <div className=\"text-sm text-muted-foreground\">{t('common.loading', 'Loading...')}</div>\n }\n\n const designTimeAttrs = attributes.filter((a) => a.resolutionTime === 'design_time')\n\n return (\n <div className=\"space-y-6\">\n {/* Header */}\n <div className=\"flex items-center justify-between\">\n <div className=\"flex items-center gap-3\">\n <button\n onClick={() => router.push('/backend/cpq/specifications')}\n className=\"text-sm text-muted-foreground hover:text-foreground\"\n >\n \u2190 {t('common.back', 'Back')}\n </button>\n <h1 className=\"text-2xl font-bold\">\n {isNew ? t('cpq.specifications.new', 'New Specification') : form.name}\n </h1>\n {!isNew && (\n <Tag variant={specificationLifecycleStatusMap[form.lifecycleStatus as SpecificationLifecycleStatus] ?? 'neutral'} dot>\n {formatStatusLabel(form.lifecycleStatus)}\n </Tag>\n )}\n </div>\n {!isNew && (\n <div className=\"flex items-center gap-2\">\n {/* Edit lives in the page header next to Delete (OM standard\n detail-page layout). The inline Edit button inside the\n General card is removed in favour of this one. */}\n {generalMode === 'view' && tab === 'general' && (\n <Button\n type=\"button\"\n onClick={() => {\n setFormSnapshot(form)\n setGeneralMode('edit')\n }}\n >\n {t('common.edit', 'Edit')}\n </Button>\n )}\n <Button type=\"button\" variant=\"destructive\" onClick={deleteSpec}>\n {t('common.delete', 'Delete')}\n </Button>\n </div>\n )}\n </div>\n\n {error && (\n <Alert variant=\"destructive\">{error}</Alert>\n )}\n\n {/* Tabs */}\n {!isNew && (\n <div className=\"flex gap-1 border-b\">\n {([\n 'general',\n 'attributes',\n 'offerings',\n 'relationships',\n ...(form.specType === 'bundle' ? ['slots' as const] : []),\n ] as const).map((t_) => (\n <button\n key={t_}\n onClick={() => { setTab(t_ as typeof tab); if (t_ === 'offerings' && offerings.length > 0 && Object.keys(offeringCharges).length === 0) loadAllOfferingCharges() }}\n className={`px-4 py-2 text-sm font-medium border-b-2 transition-colors ${\n tab === t_ ? 'border-primary text-primary' : 'border-transparent text-muted-foreground hover:text-foreground'\n }`}\n >\n {t_ === 'general' && 'General'}\n {t_ === 'attributes' && `Attributes (${attributes.length})`}\n {t_ === 'offerings' && `Offerings (${offerings.length})`}\n {t_ === 'relationships' && `Relationships (${relationships.length})`}\n {t_ === 'slots' && `Bundle Slots (${bundleSlots.length})`}\n </button>\n ))}\n </div>\n )}\n\n {/* \u2500\u2500\u2500 General Tab / New Form \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */}\n {(isNew || tab === 'general') && (() => {\n const isViewing = generalMode === 'view' && !isNew\n // Spec type can never be changed once anything depends on it. We\n // still surface the constraint in the read-only view so a user\n // doesn't toggle into edit mode and find a disabled field.\n const specTypeLocked = !isNew && (offerings.length > 0 || bundleSlots.length > 0)\n return (\n <div className=\"rounded-lg border bg-card p-6 space-y-4\">\n <div className=\"grid grid-cols-2 gap-4\">\n <div>\n <label className=\"block text-sm font-medium mb-1\">{t('cpq.specifications.code', 'Code')}</label>\n {isViewing ? (\n <p className=\"text-sm font-mono py-2\">{form.code || '\u2014'}</p>\n ) : (\n <input\n type=\"text\"\n value={form.code}\n onChange={(e) => setForm({ ...form, code: e.target.value })}\n placeholder=\"e.g. gix-access-port\"\n className=\"w-full rounded-md border px-3 py-2 text-sm\"\n />\n )}\n </div>\n <div>\n <label className=\"block text-sm font-medium mb-1\">{t('cpq.specifications.name', 'Name')}</label>\n {isViewing ? (\n <p className=\"text-sm py-2\">{form.name || '\u2014'}</p>\n ) : (\n <input\n type=\"text\"\n value={form.name}\n onChange={(e) => setForm({ ...form, name: e.target.value })}\n className=\"w-full rounded-md border px-3 py-2 text-sm\"\n />\n )}\n </div>\n <div>\n <label className=\"block text-sm font-medium mb-1\">{t('cpq.specifications.lifecycleStatus', 'Lifecycle Status')}</label>\n {isViewing ? (\n <div className=\"py-2\">\n <Tag variant={specificationLifecycleStatusMap[form.lifecycleStatus as SpecificationLifecycleStatus] ?? 'neutral'} dot>\n {formatStatusLabel(form.lifecycleStatus)}\n </Tag>\n </div>\n ) : (\n <select\n value={form.lifecycleStatus}\n onChange={(e) => setForm({ ...form, lifecycleStatus: e.target.value })}\n className=\"w-full rounded-md border px-3 py-2 text-sm\"\n >\n <option value=\"draft\">Draft</option>\n <option value=\"active\">Active</option>\n <option value=\"deprecated\">Deprecated</option>\n </select>\n )}\n </div>\n <div>\n <label className=\"block text-sm font-medium mb-1\">{t('cpq.specifications.isActive', 'Is Active?')}</label>\n <div className=\"flex items-center h-[38px]\">\n {isViewing ? (\n <Tag variant={form.isActive ? 'success' : 'neutral'} dot>\n {form.isActive ? t('common.yes', 'Yes') : t('common.no', 'No')}\n </Tag>\n ) : (\n <input\n type=\"checkbox\"\n checked={form.isActive}\n onChange={(e) => setForm({ ...form, isActive: e.target.checked })}\n className=\"rounded border\"\n />\n )}\n </div>\n </div>\n <div>\n <label className=\"block text-sm font-medium mb-1\">Spec Type</label>\n {isViewing ? (\n <p className=\"text-sm py-2\">{form.specType === 'bundle' ? 'Bundle' : 'Simple'}</p>\n ) : (\n <>\n <select\n value={form.specType}\n onChange={(e) => setForm({ ...form, specType: e.target.value })}\n disabled={specTypeLocked}\n className=\"w-full rounded-md border px-3 py-2 text-sm disabled:opacity-50\"\n >\n <option value=\"simple\">Simple</option>\n <option value=\"bundle\">Bundle</option>\n </select>\n {specTypeLocked && (\n <p className=\"text-xs text-muted-foreground mt-1\">Cannot change after offerings or slots exist</p>\n )}\n </>\n )}\n </div>\n <div>\n <label className=\"block text-sm font-medium mb-1\">Is Assetizable?</label>\n <div className=\"flex items-center h-[38px]\">\n {isViewing ? (\n <Tag variant={form.isAssetizable ? 'warning' : 'neutral'} dot>\n {form.isAssetizable ? t('common.yes', 'Yes') : t('common.no', 'No')}\n </Tag>\n ) : (\n <>\n <input\n type=\"checkbox\"\n checked={form.isAssetizable}\n onChange={(e) => setForm({ ...form, isAssetizable: e.target.checked })}\n className=\"rounded border\"\n />\n <span className=\"ml-2 text-xs text-muted-foreground\">Creates asset records during fulfilment</span>\n </>\n )}\n </div>\n </div>\n </div>\n <div>\n <label className=\"block text-sm font-medium mb-1\">{t('cpq.specifications.description', 'Description')}</label>\n {isViewing ? (\n <p className=\"text-sm text-muted-foreground py-2 whitespace-pre-wrap\">{form.description || '\u2014'}</p>\n ) : (\n <textarea\n value={form.description ?? ''}\n onChange={(e) => setForm({ ...form, description: e.target.value })}\n rows={3}\n className=\"w-full rounded-md border px-3 py-2 text-sm\"\n />\n )}\n </div>\n {!isNew && (\n <span className=\"text-xs text-muted-foreground\">Version {form.version}</span>\n )}\n {/* In view mode the Edit button lives in the page header next to\n Delete (OM standard). Here we only render the Save/Cancel\n pair when actually editing. */}\n {!isViewing && (\n <div className=\"flex gap-3\">\n <Button\n type=\"button\"\n onClick={saveSpec}\n disabled={saving || !form.code || !form.name}\n >\n {saving ? t('common.saving', 'Saving...') : t('common.save', 'Save')}\n </Button>\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={() => {\n if (isNew) {\n router.push('/backend/cpq/specifications')\n return\n }\n // Revert any in-flight edits and go back to read-only.\n if (formSnapshot) setForm(formSnapshot)\n setFormSnapshot(null)\n setGeneralMode('view')\n }}\n >\n {t('common.cancel', 'Cancel')}\n </Button>\n </div>\n )}\n </div>\n )\n })()}\n\n {/* \u2500\u2500\u2500 Attributes Tab \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */}\n {tab === 'attributes' && !isNew && (\n <div className=\"space-y-4\">\n <div className=\"flex justify-end\">\n <button\n onClick={() => startEditAttr()}\n className=\"inline-flex items-center justify-center rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground hover:bg-primary/90\"\n >\n {t('cpq.specifications.addAttribute', 'Add Attribute')}\n </button>\n </div>\n\n {editingAttr && (\n <div className=\"rounded-lg border bg-card p-4 space-y-3\">\n <h3 className=\"font-medium text-sm\">\n {editingAttr.id ? 'Edit Attribute' : 'New Attribute'}\n </h3>\n <div className=\"grid grid-cols-3 gap-3\">\n <div>\n <label className=\"block text-xs font-medium mb-1\">Code</label>\n <input type=\"text\" value={editingAttr.code} onChange={(e) => setEditingAttr({ ...editingAttr, code: e.target.value })} className=\"w-full rounded-md border px-2 py-1.5 text-sm\" />\n </div>\n <div>\n <label className=\"block text-xs font-medium mb-1\">Name</label>\n <input type=\"text\" value={editingAttr.name} onChange={(e) => setEditingAttr({ ...editingAttr, name: e.target.value })} className=\"w-full rounded-md border px-2 py-1.5 text-sm\" />\n </div>\n <div>\n <label className=\"block text-xs font-medium mb-1\">Type</label>\n <select value={editingAttr.attributeType} onChange={(e) => setEditingAttr({ ...editingAttr, attributeType: e.target.value })} className=\"w-full rounded-md border px-2 py-1.5 text-sm\">\n <option value=\"text\">Text</option>\n <option value=\"number\">Number</option>\n <option value=\"boolean\">Boolean</option>\n <option value=\"select\">Select</option>\n <option value=\"multi-select\">Multi-Select</option>\n <option value=\"reference\">Reference</option>\n </select>\n </div>\n <div>\n <label className=\"block text-xs font-medium mb-1\">Resolution Time</label>\n <select value={editingAttr.resolutionTime} onChange={(e) => setEditingAttr({ ...editingAttr, resolutionTime: e.target.value })} className=\"w-full rounded-md border px-2 py-1.5 text-sm\">\n <option value=\"run_time\">Run-time (quoting)</option>\n <option value=\"design_time\">Design-time (offering)</option>\n </select>\n </div>\n <div>\n <label className=\"block text-xs font-medium mb-1\">Sort Order</label>\n <NumberInput\n integer\n value={editingAttr.sortOrder}\n onChange={(n) => setEditingAttr({ ...editingAttr, sortOrder: n ?? 0 })}\n />\n </div>\n <div>\n <label className=\"block text-xs font-medium mb-1\">Help Text</label>\n <input type=\"text\" value={editingAttr.helpText ?? ''} onChange={(e) => setEditingAttr({ ...editingAttr, helpText: e.target.value || null })} className=\"w-full rounded-md border px-2 py-1.5 text-sm\" />\n </div>\n {editingAttr.attributeType === 'reference' && (\n <>\n <div>\n <label className=\"block text-xs font-medium mb-1\">Reference Entity</label>\n <input type=\"text\" value={editingAttr.referenceEntity ?? ''} onChange={(e) => setEditingAttr({ ...editingAttr, referenceEntity: e.target.value || null })} placeholder=\"e.g. CatalogProduct\" className=\"w-full rounded-md border px-2 py-1.5 text-sm\" />\n </div>\n </>\n )}\n {(editingAttr.attributeType === 'select' || editingAttr.attributeType === 'multi-select') && (\n <div className=\"col-span-3 space-y-2\">\n <div className=\"flex items-center justify-between\">\n <label className=\"block text-xs font-medium\">Options</label>\n <button\n type=\"button\"\n onClick={() => setEditingOptions([...editingOptions, { value: '', label: '' }])}\n className=\"text-xs text-primary hover:underline\"\n >\n + Add option\n </button>\n </div>\n {editingOptions.length === 0 ? (\n <div className=\"text-xs text-muted-foreground py-2\">No options defined. Click "Add option" to start.</div>\n ) : (\n <div className=\"space-y-1.5\">\n {editingOptions.map((opt, idx) => (\n <div key={idx} className=\"flex items-center gap-2\">\n <input\n type=\"text\"\n value={opt.value}\n onChange={(e) => {\n const next = [...editingOptions]\n next[idx] = { ...next[idx], value: e.target.value }\n setEditingOptions(next)\n }}\n placeholder=\"Value (e.g. aws)\"\n className=\"flex-1 rounded-md border px-2 py-1.5 text-sm\"\n />\n <input\n type=\"text\"\n value={opt.label}\n onChange={(e) => {\n const next = [...editingOptions]\n next[idx] = { ...next[idx], label: e.target.value }\n setEditingOptions(next)\n }}\n placeholder=\"Label (e.g. Amazon Web Services)\"\n className=\"flex-1 rounded-md border px-2 py-1.5 text-sm\"\n />\n <button\n type=\"button\"\n onClick={() => setEditingOptions(editingOptions.filter((_, i) => i !== idx))}\n className=\"text-destructive hover:text-destructive/80 text-sm px-1\"\n title=\"Remove\"\n >\n \u00D7\n </button>\n </div>\n ))}\n </div>\n )}\n </div>\n )}\n <div className=\"col-span-3 space-y-2\">\n <label className=\"flex items-center gap-1.5 text-xs font-medium\">\n <input\n type=\"checkbox\"\n checked={dependsOnEnabled}\n onChange={(e) => setDependsOnEnabled(e.target.checked)}\n className=\"rounded border\"\n />\n Depends on another attribute\n </label>\n {dependsOnEnabled && (() => {\n const parentAttr = attributes.find((a) => a.code === dependsOnAttrCode)\n return (\n <div className=\"space-y-3\">\n <div className=\"grid grid-cols-2 gap-3\">\n <div>\n <label className=\"block text-xs font-medium mb-1\">Parent Attribute Code</label>\n <select\n value={dependsOnAttrCode}\n onChange={(e) => {\n setDependsOnAttrCode(e.target.value)\n // Parent changed \u2014 `when` values that referenced the old\n // parent's options no longer make sense, but clearing them\n // would silently destroy user work. Leave them as text; the\n // RuleRow will fall back to free-text input when the new\n // parent doesn't have enumerated options.\n }}\n className=\"w-full rounded-md border px-2 py-1.5 text-sm\"\n >\n <option value=\"\">Select attribute...</option>\n {attributes.filter((a) => editingAttr && a.code !== editingAttr.code).map((a) => (\n <option key={a.code} value={a.code}>{a.name} ({a.code})</option>\n ))}\n </select>\n </div>\n <div>\n <label className=\"block text-xs font-medium mb-1\">Effect</label>\n <select\n value={dependsOnEffect}\n onChange={(e) => {\n const next = e.target.value as DependsOnEffect\n setDependsOnEffect(next)\n // `then` shape differs per effect \u2014 drop existing rules so\n // we never persist a mis-typed payload.\n setDependsOnRules([])\n }}\n className=\"w-full rounded-md border px-2 py-1.5 text-sm\"\n >\n <option value=\"filter_options\">Filter options</option>\n <option value=\"set_value\">Set value</option>\n <option value=\"toggle_required\">Toggle required</option>\n </select>\n </div>\n </div>\n <div>\n <label className=\"block text-xs font-medium mb-2\">Rules</label>\n <DependsOnRulesEditor\n effect={dependsOnEffect}\n rules={dependsOnRules}\n onChange={setDependsOnRules}\n parentOptions={parentAttr?.options ?? null}\n childOptions={editingOptions.length > 0 ? editingOptions : null}\n />\n </div>\n </div>\n )\n })()}\n </div>\n <div className=\"flex items-end gap-4\">\n <label className=\"flex items-center gap-1.5 text-sm\">\n <input type=\"checkbox\" checked={editingAttr.isRequired} onChange={(e) => setEditingAttr({ ...editingAttr, isRequired: e.target.checked })} className=\"rounded border\" />\n Required\n </label>\n <label className=\"flex items-center gap-1.5 text-sm\">\n <input type=\"checkbox\" checked={editingAttr.isActive} onChange={(e) => setEditingAttr({ ...editingAttr, isActive: e.target.checked })} className=\"rounded border\" />\n Active\n </label>\n </div>\n </div>\n <div className=\"flex gap-2\">\n <button onClick={saveAttribute} disabled={saving} className=\"inline-flex items-center rounded-md bg-primary px-3 py-1.5 text-sm font-medium text-primary-foreground hover:bg-primary/90 disabled:opacity-50\">\n {saving ? 'Saving...' : 'Save'}\n </button>\n <button onClick={() => setEditingAttr(null)} className=\"inline-flex items-center rounded-md border px-3 py-1.5 text-sm font-medium hover:bg-muted\">Cancel</button>\n </div>\n </div>\n )}\n\n {attributes.length === 0 ? (\n <div className=\"rounded-lg border bg-card p-6 text-center text-sm text-muted-foreground\">\n No attributes defined. Add design-time and run-time attributes for this specification.\n </div>\n ) : (\n <div className=\"rounded-lg border\">\n <table className=\"w-full text-sm\">\n <thead>\n <tr className=\"border-b bg-muted/50\">\n <th className=\"px-4 py-3 text-left font-medium\">Code</th>\n <th className=\"px-4 py-3 text-left font-medium\">Name</th>\n <th className=\"px-4 py-3 text-left font-medium\">Type</th>\n <th className=\"px-4 py-3 text-left font-medium\">Resolution</th>\n <th className=\"px-4 py-3 text-left font-medium\">Options</th>\n <th className=\"px-4 py-3 text-left font-medium\">Required</th>\n <th className=\"px-4 py-3 text-right font-medium\">Actions</th>\n </tr>\n </thead>\n <tbody>\n {attributes.map((attr) => (\n <tr key={attr.id} className=\"border-b\">\n <td className=\"px-4 py-3 font-mono text-xs\">{attr.code}</td>\n <td className=\"px-4 py-3\">{attr.name}</td>\n <td className=\"px-4 py-3\">{attr.attributeType}</td>\n <td className=\"px-4 py-3\">\n <Tag variant={attr.resolutionTime === 'design_time' ? 'info' : 'neutral'} className=\"px-2 text-xs\">\n {attr.resolutionTime === 'design_time' ? 'design' : 'run'}\n </Tag>\n </td>\n <td className=\"px-4 py-3 text-muted-foreground\">{attr.options ? `${attr.options.length} options` : '\u2014'}</td>\n <td className=\"px-4 py-3\">{attr.isRequired ? 'Yes' : 'No'}</td>\n <td className=\"px-4 py-3 text-right\">\n <button onClick={() => startEditAttr(attr)} className=\"text-xs text-primary hover:underline mr-2\">Edit</button>\n <button onClick={() => deleteAttribute(attr.id)} className=\"text-xs text-destructive hover:underline\">Delete</button>\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n )}\n </div>\n )}\n\n {/* \u2500\u2500\u2500 Offerings Tab \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */}\n {tab === 'offerings' && !isNew && (\n <div className=\"space-y-4\">\n <div className=\"flex justify-end\">\n <button\n onClick={() => startEditOffering()}\n className=\"inline-flex items-center justify-center rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground hover:bg-primary/90\"\n >\n {t('cpq.specifications.addOffering', 'Add Offering')}\n </button>\n </div>\n\n {editingOffering && (\n <div className=\"rounded-lg border bg-card p-4 space-y-3\">\n <h3 className=\"font-medium text-sm\">\n {editingOffering.id ? 'Edit Offering' : 'New Offering'}\n </h3>\n <div className=\"grid grid-cols-4 gap-3\">\n <div>\n <label className=\"block text-xs font-medium mb-1\">Code</label>\n <input type=\"text\" value={editingOffering.code} onChange={(e) => setEditingOffering({ ...editingOffering, code: e.target.value })} placeholder=\"e.g. gix-cloud-connect-aws\" className=\"w-full rounded-md border px-2 py-1.5 text-sm\" />\n </div>\n <div>\n <label className=\"block text-xs font-medium mb-1\">Name</label>\n <input type=\"text\" value={editingOffering.name} onChange={(e) => setEditingOffering({ ...editingOffering, name: e.target.value })} className=\"w-full rounded-md border px-2 py-1.5 text-sm\" />\n </div>\n <div>\n <label className=\"block text-xs font-medium mb-1\">Lifecycle Status</label>\n <select value={editingOffering.lifecycleStatus} onChange={(e) => setEditingOffering({ ...editingOffering, lifecycleStatus: e.target.value })} className=\"w-full rounded-md border px-2 py-1.5 text-sm\">\n <option value=\"draft\">Draft</option>\n <option value=\"active\">Active</option>\n <option value=\"deprecated\">Deprecated</option>\n </select>\n </div>\n <div>\n <label className=\"block text-xs font-medium mb-1\">Is Active?</label>\n <div className=\"flex items-center h-[30px]\">\n <input type=\"checkbox\" checked={editingOffering.isActive} onChange={(e) => setEditingOffering({ ...editingOffering, isActive: e.target.checked })} className=\"rounded border\" />\n </div>\n </div>\n </div>\n <div>\n <label className=\"block text-xs font-medium mb-1\">Description</label>\n <input type=\"text\" value={editingOffering.description ?? ''} onChange={(e) => setEditingOffering({ ...editingOffering, description: e.target.value || null })} className=\"w-full rounded-md border px-2 py-1.5 text-sm\" />\n </div>\n {designTimeAttrs.length > 0 ? (\n <div className=\"space-y-3\">\n <label className=\"block text-xs font-medium\">Design-Time Values</label>\n <div className=\"grid grid-cols-2 gap-3\">\n {designTimeAttrs.map((attr) => (\n <div key={attr.code}>\n <label className=\"block text-xs font-medium mb-1\">\n {attr.name}\n {attr.isRequired && <span className=\"text-destructive ml-0.5\">*</span>}\n </label>\n {(attr.attributeType === 'select' || attr.attributeType === 'enum') && attr.options ? (\n <select\n value={String(editingDtValues[attr.code] ?? '')}\n onChange={(e) => setEditingDtValues({ ...editingDtValues, [attr.code]: e.target.value || null })}\n className=\"w-full rounded-md border px-2 py-1.5 text-sm\"\n >\n <option value=\"\">Select {attr.name}...</option>\n {attr.options.map((opt) => (\n <option key={opt.value} value={opt.value}>{opt.label}</option>\n ))}\n </select>\n ) : attr.attributeType === 'number' ? (\n <NumberInput\n value={typeof editingDtValues[attr.code] === 'number' ? (editingDtValues[attr.code] as number) : null}\n onChange={(n) => setEditingDtValues({ ...editingDtValues, [attr.code]: n })}\n />\n ) : attr.attributeType === 'boolean' ? (\n <div className=\"pt-1\">\n <label className=\"flex items-center gap-1.5 text-sm\">\n <input\n type=\"checkbox\"\n checked={!!editingDtValues[attr.code]}\n onChange={(e) => setEditingDtValues({ ...editingDtValues, [attr.code]: e.target.checked })}\n className=\"rounded border\"\n />\n {attr.name}\n </label>\n </div>\n ) : (\n <input\n type=\"text\"\n value={String(editingDtValues[attr.code] ?? '')}\n onChange={(e) => setEditingDtValues({ ...editingDtValues, [attr.code]: e.target.value || null })}\n className=\"w-full rounded-md border px-2 py-1.5 text-sm\"\n placeholder={attr.helpText ?? undefined}\n />\n )}\n {attr.helpText && <p className=\"text-xs text-muted-foreground mt-0.5\">{attr.helpText}</p>}\n </div>\n ))}\n </div>\n </div>\n ) : (\n <div className=\"text-xs text-muted-foreground py-1\">\n No design-time attributes defined on this specification. All attributes are run-time.\n </div>\n )}\n <div className=\"flex gap-2\">\n <button onClick={saveOffering} disabled={saving} className=\"inline-flex items-center rounded-md bg-primary px-3 py-1.5 text-sm font-medium text-primary-foreground hover:bg-primary/90 disabled:opacity-50\">\n {saving ? 'Saving...' : 'Save'}\n </button>\n <button onClick={() => setEditingOffering(null)} className=\"inline-flex items-center rounded-md border px-3 py-1.5 text-sm font-medium hover:bg-muted\">Cancel</button>\n </div>\n </div>\n )}\n\n {offerings.length === 0 ? (\n <div className=\"rounded-lg border bg-card p-6 text-center text-sm text-muted-foreground\">\n No offerings created. An offering is a sellable instance of this specification with fixed design-time values and attached charges.\n </div>\n ) : (\n <div className=\"rounded-lg border\">\n <table className=\"w-full text-sm\">\n <thead>\n <tr className=\"border-b bg-muted/50\">\n <th className=\"px-3 py-3 text-left font-medium\">Code</th>\n <th className=\"px-3 py-3 text-left font-medium\">Name</th>\n <th className=\"px-3 py-3 text-left font-medium\">Status</th>\n <th className=\"px-3 py-3 text-left font-medium\">Design-Time Values</th>\n <th className=\"px-3 py-3 text-right font-medium\">Actions</th>\n </tr>\n </thead>\n <tbody>\n {offerings.map((o) => (\n <tr\n key={o.id}\n onClick={() => router.push(`/backend/cpq/offerings/${o.id}`)}\n className=\"border-b cursor-pointer hover:bg-muted/30 transition-colors\"\n >\n <td className=\"px-3 py-3 font-mono text-xs\">{o.code}</td>\n <td className=\"px-3 py-3 font-medium\">{o.name}</td>\n <td className=\"px-3 py-3\">\n <Tag variant={lifecycleStatusMap[o.lifecycleStatus as LifecycleStatus] ?? 'neutral'} dot>\n {formatStatusLabel(o.lifecycleStatus)}\n </Tag>\n </td>\n <td className=\"px-3 py-3 text-muted-foreground text-xs\">\n {Object.keys(o.designTimeValues).length > 0\n ? Object.entries(o.designTimeValues).map(([k, v]) => `${k}=${v}`).join(', ')\n : '\u2014'}\n </td>\n <td className=\"px-3 py-3 text-right\">\n <button onClick={(e) => { e.stopPropagation(); startEditOffering(o) }} className=\"text-xs text-primary hover:underline mr-2\">Edit</button>\n <button onClick={(e) => { e.stopPropagation(); deleteOffering(o.id) }} className=\"text-xs text-destructive hover:underline\">Delete</button>\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n )}\n </div>\n )}\n\n {/* \u2500\u2500\u2500 Relationships Tab \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */}\n {tab === 'relationships' && !isNew && (\n <div className=\"space-y-4\">\n <div className=\"flex justify-end\">\n <button\n onClick={() => startEditRel()}\n className=\"inline-flex items-center justify-center rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground hover:bg-primary/90\"\n >\n {t('cpq.specifications.addRelationship', 'Add Relationship')}\n </button>\n </div>\n\n {editingRel && (\n <div className=\"rounded-lg border bg-card p-4 space-y-3\">\n <h3 className=\"font-medium text-sm\">\n {editingRel.id ? 'Edit Relationship' : 'New Relationship'}\n </h3>\n <div className=\"grid grid-cols-3 gap-3\">\n <div>\n <label className=\"block text-xs font-medium mb-1\">Type</label>\n <select value={editingRel.relationshipType} onChange={(e) => setEditingRel({ ...editingRel, relationshipType: e.target.value })} className=\"w-full rounded-md border px-2 py-1.5 text-sm\">\n <option value=\"parent_child\">Parent / Child</option>\n <option value=\"requires\">Requires</option>\n <option value=\"excludes\">Excludes</option>\n </select>\n </div>\n <div>\n <label className=\"block text-xs font-medium mb-1\">Target Specification</label>\n <select value={editingRel.targetSpecId} onChange={(e) => setEditingRel({ ...editingRel, targetSpecId: e.target.value })} className=\"w-full rounded-md border px-2 py-1.5 text-sm\">\n <option value=\"\">Select...</option>\n {allSpecs.filter((s) => s.id !== specId).map((s) => (\n <option key={s.id} value={s.id}>{s.name} ({s.code})</option>\n ))}\n </select>\n </div>\n <div className=\"grid grid-cols-2 gap-2\">\n <div>\n <label className=\"block text-xs font-medium mb-1\">Min</label>\n <NumberInput\n integer\n min={0}\n value={editingRel.cardinalityMin}\n onChange={(n) => setEditingRel({ ...editingRel, cardinalityMin: n ?? 0 })}\n />\n </div>\n <div>\n <label className=\"block text-xs font-medium mb-1\">Max</label>\n <NumberInput\n integer\n min={0}\n value={editingRel.cardinalityMax}\n onChange={(n) => setEditingRel({ ...editingRel, cardinalityMax: n })}\n placeholder=\"\u221E\"\n />\n </div>\n </div>\n </div>\n <div>\n <label className=\"block text-xs font-medium mb-1\">Condition (JSON)</label>\n <textarea value={conditionJson} onChange={(e) => setConditionJson(e.target.value)} rows={3} className=\"w-full rounded-md border px-2 py-1.5 text-sm font-mono\" placeholder='null or {\"attribute\":\"direction\",\"operator\":\"in\",\"value\":[\"inbound\"]}' />\n </div>\n <div className=\"flex gap-2\">\n <button onClick={saveRelationship} disabled={saving} className=\"inline-flex items-center rounded-md bg-primary px-3 py-1.5 text-sm font-medium text-primary-foreground hover:bg-primary/90 disabled:opacity-50\">\n {saving ? 'Saving...' : 'Save'}\n </button>\n <button onClick={() => setEditingRel(null)} className=\"inline-flex items-center rounded-md border px-3 py-1.5 text-sm font-medium hover:bg-muted\">Cancel</button>\n </div>\n </div>\n )}\n\n {relationships.length === 0 ? (\n <div className=\"rounded-lg border bg-card p-6 text-center text-sm text-muted-foreground\">\n No relationships defined. Declare parent/child, requires, or excludes relationships with other specifications.\n </div>\n ) : (\n <div className=\"rounded-lg border\">\n <table className=\"w-full text-sm\">\n <thead>\n <tr className=\"border-b bg-muted/50\">\n <th className=\"px-4 py-3 text-left font-medium\">Type</th>\n <th className=\"px-4 py-3 text-left font-medium\">Source</th>\n <th className=\"px-4 py-3 text-left font-medium\">Target</th>\n <th className=\"px-4 py-3 text-left font-medium\">Cardinality</th>\n <th className=\"px-4 py-3 text-left font-medium\">Condition</th>\n <th className=\"px-4 py-3 text-right font-medium\">Actions</th>\n </tr>\n </thead>\n <tbody>\n {relationships.map((rel) => (\n <tr key={rel.id} className=\"border-b\">\n <td className=\"px-4 py-3\">\n <Tag\n variant={\n rel.relationshipType === 'parent_child' ? 'brand' :\n rel.relationshipType === 'requires' ? 'info' :\n 'error'\n }\n >\n {rel.relationshipType}\n </Tag>\n </td>\n <td className=\"px-4 py-3 text-sm\">{getSpecName(rel.sourceSpecId)}</td>\n <td className=\"px-4 py-3 text-sm\">{getSpecName(rel.targetSpecId)}</td>\n <td className=\"px-4 py-3 text-muted-foreground\">{rel.cardinalityMin}..{rel.cardinalityMax ?? '\u221E'}</td>\n <td className=\"px-4 py-3 text-muted-foreground text-xs\">{rel.condition ? JSON.stringify(rel.condition) : '\u2014'}</td>\n <td className=\"px-4 py-3 text-right\">\n <button onClick={() => startEditRel(rel)} className=\"text-xs text-primary hover:underline mr-2\">Edit</button>\n <button onClick={() => deleteRelationship(rel.id)} className=\"text-xs text-destructive hover:underline\">Delete</button>\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n )}\n </div>\n )}\n\n {/* \u2500\u2500\u2500 Bundle Slots Tab \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */}\n {tab === 'slots' && !isNew && form.specType === 'bundle' && (\n <div className=\"space-y-4\">\n <div className=\"flex justify-end\">\n <button\n onClick={() => setEditingSlot({ ...EMPTY_SLOT })}\n className=\"inline-flex items-center justify-center rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground hover:bg-primary/90\"\n >\n + Add Slot\n </button>\n </div>\n\n {editingSlot && (\n <div className=\"rounded-lg border bg-card p-6 space-y-4\">\n <h3 className=\"text-sm font-semibold\">{editingSlot.id ? 'Edit Bundle Slot' : 'New Bundle Slot'}</h3>\n <div className=\"grid grid-cols-2 gap-4\">\n <div>\n <label className=\"block text-sm font-medium mb-1\">Name</label>\n <input\n type=\"text\"\n value={editingSlot.name}\n onChange={(e) => setEditingSlot({ ...editingSlot, name: e.target.value })}\n placeholder=\"e.g. Internet Component\"\n className=\"w-full rounded-md border px-3 py-2 text-sm\"\n />\n </div>\n <div>\n <label className=\"block text-sm font-medium mb-1\">Component Group</label>\n <input\n type=\"text\"\n value={editingSlot.componentGroup}\n onChange={(e) => setEditingSlot({ ...editingSlot, componentGroup: e.target.value })}\n placeholder=\"e.g. internet, tv, phone\"\n className=\"w-full rounded-md border px-3 py-2 text-sm\"\n />\n </div>\n <div>\n <label className=\"block text-sm font-medium mb-1\">Target Specification</label>\n <select\n value={editingSlot.targetSpecId}\n onChange={(e) => setEditingSlot({ ...editingSlot, targetSpecId: e.target.value })}\n className=\"w-full rounded-md border px-3 py-2 text-sm\"\n >\n <option value=\"\">\u2014 Select specification \u2014</option>\n {allSpecs.filter((s) => s.id !== specId).map((s) => (\n <option key={s.id} value={s.id}>{s.name} ({s.code})</option>\n ))}\n </select>\n </div>\n <div>\n <label className=\"block text-sm font-medium mb-1\">Sort Order</label>\n <NumberInput\n integer\n value={editingSlot.sortOrder}\n onChange={(n) => setEditingSlot({ ...editingSlot, sortOrder: n ?? 0 })}\n />\n </div>\n <div>\n <label className=\"block text-sm font-medium mb-1\">Cardinality Min</label>\n <NumberInput\n integer\n min={0}\n value={editingSlot.cardinalityMin}\n onChange={(n) => setEditingSlot({ ...editingSlot, cardinalityMin: n ?? 0 })}\n />\n </div>\n <div>\n <label className=\"block text-sm font-medium mb-1\">Cardinality Max</label>\n <NumberInput\n integer\n min={0}\n placeholder=\"\u221E (unlimited)\"\n value={editingSlot.cardinalityMax}\n onChange={(n) => setEditingSlot({ ...editingSlot, cardinalityMax: n })}\n />\n </div>\n </div>\n <div>\n <label className=\"block text-sm font-medium mb-1\">Description</label>\n <textarea\n value={editingSlot.description ?? ''}\n onChange={(e) => setEditingSlot({ ...editingSlot, description: e.target.value })}\n rows={2}\n className=\"w-full rounded-md border px-3 py-2 text-sm\"\n />\n </div>\n <div className=\"flex gap-3\">\n <button\n onClick={async () => {\n setSaving(true)\n setError(null)\n try {\n const isEdit = !!editingSlot.id\n const payload = isEdit\n ? { id: editingSlot.id, ...editingSlot, description: editingSlot.description || null }\n : { specId, ...editingSlot, description: editingSlot.description || null }\n const res = await fetch('/api/cpq/bundle-slots', {\n method: isEdit ? 'PUT' : 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(payload),\n })\n if (!res.ok) {\n const d = await res.json()\n setError(d.error ?? 'Failed to save slot')\n return\n }\n setEditingSlot(null)\n const slotsRes = await fetch(`/api/cpq/bundle-slots?specId=${specId}`)\n if (slotsRes.ok) {\n const d = await slotsRes.json()\n setBundleSlots(d.items ?? [])\n }\n } catch {\n setError('Failed to save slot')\n } finally {\n setSaving(false)\n }\n }}\n disabled={saving || !editingSlot.name || !editingSlot.componentGroup || !editingSlot.targetSpecId}\n className=\"inline-flex items-center justify-center rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground hover:bg-primary/90 disabled:opacity-50\"\n >\n {saving ? 'Saving...' : (editingSlot.id ? 'Update' : 'Create')}\n </button>\n <button\n onClick={() => setEditingSlot(null)}\n className=\"inline-flex items-center justify-center rounded-md border px-4 py-2 text-sm font-medium hover:bg-muted\"\n >\n Cancel\n </button>\n </div>\n </div>\n )}\n\n {bundleSlots.length === 0 && !editingSlot ? (\n <div className=\"rounded-lg border bg-card p-6 text-center text-sm text-muted-foreground\">\n No bundle slots defined yet. Add slots to define what component specifications can fill this bundle.\n </div>\n ) : bundleSlots.length > 0 && (\n <div className=\"rounded-lg border overflow-hidden\">\n <table className=\"w-full text-sm\">\n <thead>\n <tr className=\"border-b bg-muted/50\">\n <th className=\"px-4 py-3 text-left font-medium\">Name</th>\n <th className=\"px-4 py-3 text-left font-medium\">Group</th>\n <th className=\"px-4 py-3 text-left font-medium\">Target Spec</th>\n <th className=\"px-4 py-3 text-left font-medium\">Cardinality</th>\n <th className=\"px-4 py-3 text-left font-medium\">Order</th>\n <th className=\"px-4 py-3 text-right font-medium\">Actions</th>\n </tr>\n </thead>\n <tbody>\n {bundleSlots.map((slot) => (\n <tr key={slot.id} className=\"border-b\">\n <td className=\"px-4 py-3 font-medium\">{slot.name}</td>\n <td className=\"px-4 py-3\">\n <Tag variant=\"info\">{slot.componentGroup}</Tag>\n </td>\n <td className=\"px-4 py-3 text-sm\">\n {slot.targetSpec ? (\n <span>\n {slot.targetSpec.name}\n {slot.targetSpec.specType === 'bundle' && (\n <Tag variant=\"brand\" className=\"ml-1 px-1.5 text-[10px]\">bundle</Tag>\n )}\n </span>\n ) : (\n <span className=\"text-muted-foreground\">Unknown</span>\n )}\n </td>\n <td className=\"px-4 py-3 text-muted-foreground\">{slot.cardinalityMin}..{slot.cardinalityMax ?? '\u221E'}</td>\n <td className=\"px-4 py-3 text-muted-foreground\">{slot.sortOrder}</td>\n <td className=\"px-4 py-3 text-right\">\n <button\n onClick={() => setEditingSlot({\n id: slot.id,\n targetSpecId: slot.targetSpecId,\n componentGroup: slot.componentGroup,\n name: slot.name,\n description: slot.description ?? '',\n cardinalityMin: slot.cardinalityMin,\n cardinalityMax: slot.cardinalityMax,\n sortOrder: slot.sortOrder,\n })}\n className=\"text-xs text-primary hover:underline mr-2\"\n >\n Edit\n </button>\n <button\n onClick={async () => {\n if (!confirm('Delete this bundle slot?')) return\n try {\n const res = await fetch('/api/cpq/bundle-slots', {\n method: 'DELETE',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ id: slot.id }),\n })\n if (res.ok) {\n setBundleSlots((prev) => prev.filter((s) => s.id !== slot.id))\n } else {\n const d = await res.json()\n setError(d.error ?? 'Failed to delete slot')\n }\n } catch {\n setError('Failed to delete slot')\n }\n }}\n className=\"text-xs text-destructive hover:underline\"\n >\n Delete\n </button>\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n )}\n </div>\n )}\n </div>\n )\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["\"use client\"\nimport * as React from 'react'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { useParams, useRouter } from 'next/navigation'\nimport { Tag } from '@open-mercato/ui/primitives/tag'\nimport { Alert } from '@open-mercato/ui/primitives/alert'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { NumberInput } from '../../../../components/NumberInput'\nimport {\n formatStatusLabel,\n lifecycleStatusMap,\n specificationLifecycleStatusMap,\n type LifecycleStatus,\n type SpecificationLifecycleStatus,\n} from '../../../../components/statusMaps'\nimport { DependsOnRulesEditor } from './DependsOnRulesEditor'\n\n// \u2500\u2500\u2500 Types \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n// Attribute \u2192 attribute dependency contract. The validator\n// (`cpqValidationService.validateAttributes`) reads `attributeCode` to look\n// up the parent value and walks `rules[].when` to decide what happens to\n// this attribute. `effect` controls the interpretation of `rules[].then`:\n//\n// - `filter_options`: `then` is a comma-separated list of allowed values\n// that this attribute may take when the parent matches `when`.\n// - `set_value`: `then` is a single value to assign to this attribute\n// when the parent matches `when`.\n// - `toggle_required`: `then` is a boolean \u2014 `true` makes this attribute\n// required when the parent matches `when`, `false` makes it optional.\n//\n// Storage stays generic (`{ when: string; then: unknown }`) so we don't\n// have to migrate older configs when the surface grows.\nexport type DependsOnEffect = 'filter_options' | 'set_value' | 'toggle_required'\n\nexport type DependsOnRule = {\n when: string\n then: unknown\n}\n\nexport type AttributeDependsOn = {\n attributeCode: string\n effect: DependsOnEffect\n rules: DependsOnRule[]\n}\n\ntype Specification = {\n id: string\n productId: string\n code: string\n name: string\n description: string | null\n specType: string\n isAssetizable: boolean\n lifecycleStatus: string\n version: number\n effectiveFrom: string | null\n effectiveTo: string | null\n metadata: Record<string, unknown> | null\n isActive: boolean\n}\n\ntype Attribute = {\n id: string\n code: string\n name: string\n attributeType: string\n resolutionTime: string\n options: Array<{ value: string; label: string }> | null\n constraints: Record<string, unknown> | null\n referenceEntity: string | null\n referenceFilter: Record<string, unknown> | null\n dependsOn: AttributeDependsOn | null\n defaultValue: unknown | null\n helpText: string | null\n sortOrder: number\n isRequired: boolean\n isActive: boolean\n}\n\ntype Offering = {\n id: string\n code: string\n name: string\n description: string | null\n offeringType: string\n designTimeValues: Record<string, unknown>\n lifecycleStatus: string\n isActive: boolean\n}\n\ntype BundleSlot = {\n id: string\n specId: string\n targetSpecId: string\n targetSpec: { id: string; code: string; name: string; specType: string } | null\n componentGroup: string\n name: string\n description: string | null\n cardinalityMin: number\n cardinalityMax: number | null\n sortOrder: number\n isActive: boolean\n}\n\ntype EditingSlot = {\n id?: string\n targetSpecId: string\n componentGroup: string\n name: string\n description: string\n cardinalityMin: number\n cardinalityMax: number | null\n sortOrder: number\n}\n\ntype Relationship = {\n id: string\n sourceSpecId: string\n targetSpecId: string\n relationshipType: string\n cardinalityMin: number\n cardinalityMax: number | null\n condition: Record<string, unknown> | null\n isActive: boolean\n}\n\ntype Charge = {\n id: string\n code: string\n name: string\n description: string | null\n chargeType: string\n pricingMethod: string\n pricingTableId: string | null\n priceColumnKey: string | null\n fixedPrice: string | null\n currencyCode: string | null\n quantityAttributeCode: string | null\n applicabilityCondition: Record<string, unknown> | null\n sortOrder: number\n isActive: boolean\n}\n\ntype PricingTableRef = { id: string; code: string; name: string; dimensions: Array<{ key: string; label: string }>; priceColumns: Array<{ key: string; label: string }> }\n\ntype EditingAttribute = Omit<Attribute, 'id'> & { id?: string }\ntype EditingOffering = Omit<Offering, 'id'> & { id?: string }\ntype EditingRelationship = Omit<Relationship, 'id'> & { id?: string }\ntype EditingCharge = Omit<Charge, 'id'> & { id?: string }\n\n// \u2500\u2500\u2500 Defaults \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nconst EMPTY_SPEC = {\n code: '',\n name: '',\n description: '',\n specType: 'simple' as string,\n isAssetizable: false,\n lifecycleStatus: 'draft',\n version: 1,\n effectiveFrom: null as string | null,\n effectiveTo: null as string | null,\n isActive: true,\n}\n\nconst EMPTY_SLOT: EditingSlot = {\n targetSpecId: '',\n componentGroup: '',\n name: '',\n description: '',\n cardinalityMin: 0,\n cardinalityMax: null,\n sortOrder: 0,\n}\n\nconst EMPTY_ATTRIBUTE: EditingAttribute = {\n code: '',\n name: '',\n attributeType: 'text',\n resolutionTime: 'run_time',\n options: null,\n constraints: null,\n referenceEntity: null,\n referenceFilter: null,\n dependsOn: null,\n defaultValue: null,\n helpText: null,\n sortOrder: 0,\n isRequired: true,\n isActive: true,\n}\n\nconst EMPTY_OFFERING: EditingOffering = {\n code: '',\n name: '',\n description: null,\n offeringType: 'simple',\n designTimeValues: {},\n lifecycleStatus: 'draft',\n isActive: true,\n}\n\nconst EMPTY_CHARGE: EditingCharge = {\n code: '',\n name: '',\n description: null,\n chargeType: 'mrc',\n pricingMethod: 'flat',\n pricingTableId: null,\n priceColumnKey: null,\n fixedPrice: null,\n currencyCode: null,\n quantityAttributeCode: null,\n applicabilityCondition: null,\n sortOrder: 0,\n isActive: true,\n}\n\nconst EMPTY_RELATIONSHIP: EditingRelationship = {\n sourceSpecId: '',\n targetSpecId: '',\n relationshipType: 'requires',\n cardinalityMin: 0,\n cardinalityMax: null,\n condition: null,\n isActive: true,\n}\n\n// \u2500\u2500\u2500 Component \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport default function SpecificationDetailPage(props: { params?: { id?: string } }) {\n const t = useT()\n const router = useRouter()\n const urlParams = useParams()\n const specId = (props.params?.id ?? urlParams?.id) as string\n const isNew = specId === 'new'\n\n // \u2500\u2500\u2500 State \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n const [tab, setTab] = React.useState<'general' | 'attributes' | 'offerings' | 'relationships' | 'slots'>('general')\n const [form, setForm] = React.useState(EMPTY_SPEC)\n const [attributes, setAttributes] = React.useState<Attribute[]>([])\n const [offerings, setOfferings] = React.useState<Offering[]>([])\n const [relationships, setRelationships] = React.useState<Relationship[]>([])\n const [bundleSlots, setBundleSlots] = React.useState<BundleSlot[]>([])\n const [allSpecs, setAllSpecs] = React.useState<Array<{ id: string; code: string; name: string; specType?: string }>>([])\n\n const [loading, setLoading] = React.useState(!isNew)\n const [saving, setSaving] = React.useState(false)\n const [error, setError] = React.useState<string | null>(null)\n\n const [editingAttr, setEditingAttr] = React.useState<EditingAttribute | null>(null)\n const [editingOffering, setEditingOffering] = React.useState<EditingOffering | null>(null)\n const [editingRel, setEditingRel] = React.useState<EditingRelationship | null>(null)\n const [editingSlot, setEditingSlot] = React.useState<EditingSlot | null>(null)\n const [editingOptions, setEditingOptions] = React.useState<Array<{ value: string; label: string }>>([])\n const [editingDtValues, setEditingDtValues] = React.useState<Record<string, unknown>>({})\n const [selectedOfferingIds, setSelectedOfferingIds] = React.useState<Set<string>>(new Set())\n const [offeringCharges, setOfferingCharges] = React.useState<Record<string, Charge[]>>({})\n const [chargeFormOpen, setChargeFormOpen] = React.useState(false)\n const [chargeForm, setChargeForm] = React.useState({ code: '', name: '', description: '', chargeType: 'mrc', pricingMethod: 'flat' })\n const [chargePrices, setChargePrices] = React.useState<Record<string, string>>({})\n const [chargePricingTableId, setChargePricingTableId] = React.useState<string | null>(null)\n const [chargePriceColumnKey, setChargePriceColumnKey] = React.useState<string | null>(null)\n const [chargeCurrency, setChargeCurrency] = React.useState('USD')\n const [pricingTables, setPricingTables] = React.useState<PricingTableRef[]>([])\n const [conditionJson, setConditionJson] = React.useState('null')\n const [dependsOnAttrCode, setDependsOnAttrCode] = React.useState('')\n const [dependsOnEffect, setDependsOnEffect] = React.useState<DependsOnEffect>('filter_options')\n const [dependsOnEnabled, setDependsOnEnabled] = React.useState(false)\n const [dependsOnRules, setDependsOnRules] = React.useState<DependsOnRule[]>([])\n // OM-standard detail page contract: existing records open in read-only\n // \"view\" mode and require an explicit Edit click to allow editing. New\n // records (`/specifications/new`) skip view mode since there's nothing\n // to display yet.\n const [generalMode, setGeneralMode] = React.useState<'view' | 'edit'>(isNew ? 'edit' : 'view')\n // Snapshot of the form taken when entering edit mode \u2014 used by Cancel to\n // revert local changes without re-fetching.\n const [formSnapshot, setFormSnapshot] = React.useState<typeof EMPTY_SPEC | null>(null)\n\n // \u2500\u2500\u2500 Load data \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n React.useEffect(() => {\n let cancelled = false\n\n async function load() {\n try {\n if (isNew) {\n return\n }\n\n // Load all specs for relationship target selector\n const specsRes = await fetch('/api/cpq/product-specifications?pageSize=200')\n if (specsRes.ok) {\n const d = await specsRes.json()\n if (!cancelled) setAllSpecs(d.items ?? [])\n }\n\n // Load spec detail with nested data\n const res = await fetch(`/api/cpq/product-specifications?id=${encodeURIComponent(specId)}`)\n if (!res.ok) {\n if (!cancelled) setError('Failed to load specification')\n return\n }\n\n const spec = await res.json()\n if (!cancelled) {\n setForm({\n code: spec.code,\n name: spec.name,\n description: spec.description ?? '',\n specType: spec.specType ?? 'simple',\n isAssetizable: spec.isAssetizable ?? false,\n lifecycleStatus: spec.lifecycleStatus,\n version: spec.version,\n effectiveFrom: spec.effectiveFrom,\n effectiveTo: spec.effectiveTo,\n isActive: spec.isActive,\n })\n setAttributes(spec.attributes ?? [])\n setOfferings(spec.offerings ?? [])\n setRelationships(spec.relationships ?? [])\n setBundleSlots(spec.slots ?? [])\n }\n } catch (err) {\n console.error('Failed to load', err)\n if (!cancelled) setError('Failed to load')\n } finally {\n if (!cancelled) setLoading(false)\n }\n }\n\n load()\n return () => { cancelled = true }\n }, [specId, isNew])\n\n // \u2500\u2500\u2500 Save specification \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n const saveSpec = async () => {\n setSaving(true)\n setError(null)\n try {\n const { ...formData } = form\n const payload = isNew\n ? { ...formData, description: formData.description || null }\n : { id: specId, ...formData, description: formData.description || null }\n\n const res = await fetch('/api/cpq/product-specifications', {\n method: isNew ? 'POST' : 'PUT',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(payload),\n })\n\n if (!res.ok) {\n const d = await res.json()\n setError(d.error ?? 'Failed to save')\n return\n }\n\n const saved = await res.json()\n if (isNew) {\n router.push(`/backend/cpq/specifications/${saved.id}`)\n } else {\n setForm({\n code: saved.code,\n name: saved.name,\n description: saved.description ?? '',\n specType: saved.specType ?? form.specType,\n isAssetizable: saved.isAssetizable ?? form.isAssetizable,\n lifecycleStatus: saved.lifecycleStatus,\n version: saved.version,\n effectiveFrom: saved.effectiveFrom,\n effectiveTo: saved.effectiveTo,\n isActive: saved.isActive,\n })\n // Save succeeded \u2014 drop the snapshot and flip back to read-only.\n setFormSnapshot(null)\n setGeneralMode('view')\n }\n } catch {\n setError('Failed to save')\n } finally {\n setSaving(false)\n }\n }\n\n const deleteSpec = async () => {\n if (!confirm(t('cpq.specifications.confirmDelete', 'Delete this specification and all its offerings, attributes and relationships?'))) return\n try {\n const res = await fetch('/api/cpq/product-specifications', {\n method: 'DELETE',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ id: specId }),\n })\n if (res.ok) {\n router.push('/backend/cpq/specifications')\n } else {\n const d = await res.json()\n setError(d.error ?? 'Failed to delete')\n }\n } catch {\n setError('Failed to delete')\n }\n }\n\n // \u2500\u2500\u2500 Attribute CRUD \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n const saveAttribute = async () => {\n if (!editingAttr) return\n setSaving(true)\n setError(null)\n try {\n const options = (editingAttr.attributeType === 'select' || editingAttr.attributeType === 'multi-select')\n ? editingOptions.filter((o) => o.value.trim() !== '')\n : null\n\n const dependsOn: AttributeDependsOn | null =\n dependsOnEnabled && dependsOnAttrCode\n ? {\n attributeCode: dependsOnAttrCode,\n effect: dependsOnEffect,\n rules: dependsOnRules.filter((r) => r.when.trim().length > 0),\n }\n : null\n\n const isEdit = !!editingAttr.id\n const payload = {\n ...editingAttr,\n options,\n dependsOn,\n specId,\n }\n const res = await fetch('/api/cpq/product-attributes', {\n method: isEdit ? 'PUT' : 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(payload),\n })\n if (!res.ok) {\n const d = await res.json()\n setError(d.error ?? 'Failed to save attribute')\n return\n }\n const saved = await res.json()\n if (isEdit) {\n setAttributes((prev) => prev.map((a) => (a.id === saved.id ? saved : a)))\n } else {\n setAttributes((prev) => [...prev, saved])\n }\n setEditingAttr(null)\n } catch {\n setError('Failed to save attribute')\n } finally {\n setSaving(false)\n }\n }\n\n const deleteAttribute = async (attrId: string) => {\n if (!confirm('Delete this attribute?')) return\n try {\n const res = await fetch('/api/cpq/product-attributes', {\n method: 'DELETE',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ id: attrId }),\n })\n if (res.ok) setAttributes((prev) => prev.filter((a) => a.id !== attrId))\n } catch {\n setError('Failed to delete attribute')\n }\n }\n\n const startEditAttr = (attr?: Attribute) => {\n const editing = attr ? { ...attr } : { ...EMPTY_ATTRIBUTE }\n // Normalize legacy 'enum' type to 'select' for the editor\n if (editing.attributeType === 'enum') editing.attributeType = 'select'\n setEditingAttr(editing)\n setEditingOptions(editing.options ? [...editing.options] : [])\n const dep = editing.dependsOn\n setDependsOnEnabled(!!dep)\n setDependsOnAttrCode(dep?.attributeCode ?? '')\n setDependsOnEffect((dep?.effect as DependsOnEffect) ?? 'filter_options')\n setDependsOnRules(Array.isArray(dep?.rules) ? dep.rules : [])\n }\n\n // \u2500\u2500\u2500 Offering CRUD \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n const saveOffering = async () => {\n if (!editingOffering) return\n setSaving(true)\n setError(null)\n try {\n const isEdit = !!editingOffering.id\n const payload = {\n ...editingOffering,\n designTimeValues: editingDtValues,\n specId,\n }\n const res = await fetch('/api/cpq/product-offerings', {\n method: isEdit ? 'PUT' : 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(payload),\n })\n if (!res.ok) {\n const d = await res.json()\n setError(d.error ?? 'Failed to save offering')\n return\n }\n const saved = await res.json()\n if (isEdit) {\n setOfferings((prev) => prev.map((o) => (o.id === saved.id ? saved : o)))\n } else {\n setOfferings((prev) => [...prev, saved])\n }\n setEditingOffering(null)\n } catch {\n setError('Failed to save offering')\n } finally {\n setSaving(false)\n }\n }\n\n const deleteOffering = async (offeringId: string) => {\n if (!confirm('Delete this offering?')) return\n try {\n const res = await fetch('/api/cpq/product-offerings', {\n method: 'DELETE',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ id: offeringId }),\n })\n if (res.ok) setOfferings((prev) => prev.filter((o) => o.id !== offeringId))\n } catch {\n setError('Failed to delete offering')\n }\n }\n\n const startEditOffering = (offering?: Offering) => {\n const editing = offering ? { ...offering } : { ...EMPTY_OFFERING }\n setEditingOffering(editing)\n setEditingDtValues(editing.designTimeValues ? { ...editing.designTimeValues } : {})\n }\n\n // \u2500\u2500\u2500 Charge management (multi-offering) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n const loadAllOfferingCharges = async () => {\n try {\n const results = await Promise.all(\n offerings.map((o) => fetch(`/api/cpq/product-offerings?id=${encodeURIComponent(o.id)}`).then((r) => r.ok ? r.json() : null))\n )\n const chargeMap: Record<string, Charge[]> = {}\n results.forEach((data, idx) => {\n if (data) chargeMap[offerings[idx].id] = data.charges ?? []\n })\n setOfferingCharges(chargeMap)\n } catch {\n console.error('Failed to load charges')\n }\n }\n\n const loadPricingTables = async () => {\n if (pricingTables.length > 0) return\n const res = await fetch('/api/cpq/pricing-tables?pageSize=200')\n if (res.ok) {\n const data = await res.json()\n setPricingTables(data.items ?? [])\n }\n }\n\n const toggleOfferingSelection = (id: string) => {\n setSelectedOfferingIds((prev) => {\n const next = new Set(prev)\n if (next.has(id)) next.delete(id); else next.add(id)\n return next\n })\n }\n\n const toggleAllOfferings = () => {\n if (selectedOfferingIds.size === offerings.length) {\n setSelectedOfferingIds(new Set())\n } else {\n setSelectedOfferingIds(new Set(offerings.map((o) => o.id)))\n }\n }\n\n const openChargeForm = () => {\n setChargeForm({ code: '', name: '', description: '', chargeType: 'mrc', pricingMethod: 'flat' })\n setChargePrices({})\n setChargePricingTableId(null)\n setChargePriceColumnKey(null)\n setChargeCurrency('USD')\n setChargeFormOpen(true)\n loadPricingTables()\n }\n\n const saveChargesForSelected = async () => {\n const targets = offerings.filter((o) => selectedOfferingIds.has(o.id))\n if (!targets.length || !chargeForm.code || !chargeForm.name) return\n setSaving(true)\n setError(null)\n try {\n for (const offering of targets) {\n const chargeCode = targets.length > 1 ? `${offering.code}--${chargeForm.code}` : chargeForm.code\n const payload: Record<string, unknown> = {\n offeringId: offering.id,\n code: chargeCode,\n name: chargeForm.name,\n description: chargeForm.description || null,\n chargeType: chargeForm.chargeType,\n pricingMethod: chargeForm.pricingMethod === 'flat' ? 'flat' : chargeForm.pricingMethod,\n isActive: true,\n sortOrder: 0,\n }\n if (chargeForm.pricingMethod === 'flat') {\n payload.fixedPrice = chargePrices[offering.id] || null\n payload.currencyCode = chargeCurrency\n } else {\n payload.pricingTableId = chargePricingTableId\n payload.priceColumnKey = chargePriceColumnKey\n }\n const res = await fetch('/api/cpq/product-charges', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(payload),\n })\n if (!res.ok) {\n const d = await res.json()\n setError(d.error ?? `Failed to save charge for ${offering.name}`)\n break\n }\n }\n setChargeFormOpen(false)\n await loadAllOfferingCharges()\n } catch {\n setError('Failed to save charges')\n } finally {\n setSaving(false)\n }\n }\n\n const deleteCharge = async (offeringId: string, chargeId: string) => {\n if (!confirm('Delete this charge?')) return\n try {\n const res = await fetch('/api/cpq/product-charges', {\n method: 'DELETE',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ id: chargeId }),\n })\n if (res.ok) {\n setOfferingCharges((prev) => ({\n ...prev,\n [offeringId]: (prev[offeringId] ?? []).filter((c) => c.id !== chargeId),\n }))\n }\n } catch {\n setError('Failed to delete charge')\n }\n }\n\n const selectedPricingTableRef = chargePricingTableId\n ? pricingTables.find((pt) => pt.id === chargePricingTableId)\n : null\n\n // \u2500\u2500\u2500 Relationship CRUD \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n const saveRelationship = async () => {\n if (!editingRel) return\n setSaving(true)\n setError(null)\n try {\n let parsedCondition = editingRel.condition\n try { parsedCondition = conditionJson === 'null' ? null : JSON.parse(conditionJson) } catch { /* keep */ }\n\n const isEdit = !!editingRel.id\n const payload = {\n ...editingRel,\n condition: parsedCondition,\n sourceSpecId: editingRel.sourceSpecId || specId,\n }\n const res = await fetch('/api/cpq/product-relationships', {\n method: isEdit ? 'PUT' : 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(payload),\n })\n if (!res.ok) {\n const d = await res.json()\n setError(d.error ?? 'Failed to save relationship')\n return\n }\n const saved = await res.json()\n if (isEdit) {\n setRelationships((prev) => prev.map((r) => (r.id === saved.id ? saved : r)))\n } else {\n setRelationships((prev) => [...prev, saved])\n }\n setEditingRel(null)\n } catch {\n setError('Failed to save relationship')\n } finally {\n setSaving(false)\n }\n }\n\n const deleteRelationship = async (relId: string) => {\n if (!confirm('Delete this relationship?')) return\n try {\n const res = await fetch('/api/cpq/product-relationships', {\n method: 'DELETE',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ id: relId }),\n })\n if (res.ok) setRelationships((prev) => prev.filter((r) => r.id !== relId))\n } catch {\n setError('Failed to delete relationship')\n }\n }\n\n const startEditRel = (rel?: Relationship) => {\n const editing = rel ? { ...rel } : { ...EMPTY_RELATIONSHIP, sourceSpecId: specId }\n setEditingRel(editing)\n setConditionJson(editing.condition ? JSON.stringify(editing.condition, null, 2) : 'null')\n }\n\n // \u2500\u2500\u2500 Helpers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n const getSpecName = (id: string) => allSpecs.find((s) => s.id === id)?.name ?? id.slice(0, 8)\n\n // \u2500\u2500\u2500 Render \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n if (loading) {\n return <div className=\"text-sm text-muted-foreground\">{t('common.loading', 'Loading...')}</div>\n }\n\n const designTimeAttrs = attributes.filter((a) => a.resolutionTime === 'design_time')\n\n return (\n <div className=\"space-y-6\">\n {/* Header */}\n <div className=\"flex items-center justify-between\">\n <div className=\"flex items-center gap-3\">\n <button\n onClick={() => router.push('/backend/cpq/specifications')}\n className=\"text-sm text-muted-foreground hover:text-foreground\"\n >\n \u2190 {t('common.back', 'Back')}\n </button>\n <h1 className=\"text-2xl font-bold\">\n {isNew ? t('cpq.specifications.new', 'New Specification') : form.name}\n </h1>\n {!isNew && (\n <Tag variant={specificationLifecycleStatusMap[form.lifecycleStatus as SpecificationLifecycleStatus] ?? 'neutral'} dot>\n {formatStatusLabel(form.lifecycleStatus)}\n </Tag>\n )}\n </div>\n {!isNew && (\n <div className=\"flex items-center gap-2\">\n {/* Edit lives in the page header next to Delete (OM standard\n detail-page layout). The inline Edit button inside the\n General card is removed in favour of this one. */}\n {generalMode === 'view' && tab === 'general' && (\n <Button\n type=\"button\"\n onClick={() => {\n setFormSnapshot(form)\n setGeneralMode('edit')\n }}\n >\n {t('common.edit', 'Edit')}\n </Button>\n )}\n <Button type=\"button\" variant=\"destructive\" onClick={deleteSpec}>\n {t('common.delete', 'Delete')}\n </Button>\n </div>\n )}\n </div>\n\n {error && (\n <Alert variant=\"destructive\">{error}</Alert>\n )}\n\n {/* Tabs */}\n {!isNew && (\n <div className=\"flex gap-1 border-b\">\n {([\n 'general',\n 'attributes',\n 'offerings',\n 'relationships',\n ...(form.specType === 'bundle' ? ['slots' as const] : []),\n ] as const).map((t_) => (\n <button\n key={t_}\n onClick={() => { setTab(t_ as typeof tab); if (t_ === 'offerings' && offerings.length > 0 && Object.keys(offeringCharges).length === 0) loadAllOfferingCharges() }}\n className={`px-4 py-2 text-sm font-medium border-b-2 transition-colors ${\n tab === t_ ? 'border-primary text-primary' : 'border-transparent text-muted-foreground hover:text-foreground'\n }`}\n >\n {t_ === 'general' && 'General'}\n {t_ === 'attributes' && `Attributes (${attributes.length})`}\n {t_ === 'offerings' && `Offerings (${offerings.length})`}\n {t_ === 'relationships' && `Relationships (${relationships.length})`}\n {t_ === 'slots' && `Bundle Slots (${bundleSlots.length})`}\n </button>\n ))}\n </div>\n )}\n\n {/* \u2500\u2500\u2500 General Tab / New Form \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */}\n {(isNew || tab === 'general') && (() => {\n const isViewing = generalMode === 'view' && !isNew\n // Spec type can never be changed once anything depends on it. We\n // still surface the constraint in the read-only view so a user\n // doesn't toggle into edit mode and find a disabled field.\n const specTypeLocked = !isNew && (offerings.length > 0 || bundleSlots.length > 0)\n return (\n <div className=\"rounded-lg border bg-card p-6 space-y-4\">\n <div className=\"grid grid-cols-2 gap-4\">\n <div>\n <label className=\"block text-sm font-medium mb-1\">{t('cpq.specifications.code', 'Code')}</label>\n {isViewing ? (\n <p className=\"text-sm font-mono py-2\">{form.code || '\u2014'}</p>\n ) : (\n <input\n type=\"text\"\n value={form.code}\n onChange={(e) => setForm({ ...form, code: e.target.value })}\n placeholder=\"e.g. gix-access-port\"\n className=\"w-full rounded-md border px-3 py-2 text-sm\"\n />\n )}\n </div>\n <div>\n <label className=\"block text-sm font-medium mb-1\">{t('cpq.specifications.name', 'Name')}</label>\n {isViewing ? (\n <p className=\"text-sm py-2\">{form.name || '\u2014'}</p>\n ) : (\n <input\n type=\"text\"\n value={form.name}\n onChange={(e) => setForm({ ...form, name: e.target.value })}\n className=\"w-full rounded-md border px-3 py-2 text-sm\"\n />\n )}\n </div>\n <div>\n <label className=\"block text-sm font-medium mb-1\">{t('cpq.specifications.lifecycleStatus', 'Lifecycle Status')}</label>\n {isViewing ? (\n <div className=\"py-2\">\n <Tag variant={specificationLifecycleStatusMap[form.lifecycleStatus as SpecificationLifecycleStatus] ?? 'neutral'} dot>\n {formatStatusLabel(form.lifecycleStatus)}\n </Tag>\n </div>\n ) : (\n <select\n value={form.lifecycleStatus}\n onChange={(e) => setForm({ ...form, lifecycleStatus: e.target.value })}\n className=\"w-full rounded-md border px-3 py-2 text-sm\"\n >\n <option value=\"draft\">Draft</option>\n <option value=\"active\">Active</option>\n <option value=\"deprecated\">Deprecated</option>\n </select>\n )}\n </div>\n <div>\n <label className=\"block text-sm font-medium mb-1\">{t('cpq.specifications.isActive', 'Is Active?')}</label>\n <div className=\"flex items-center h-[38px]\">\n {isViewing ? (\n <Tag variant={form.isActive ? 'success' : 'neutral'} dot>\n {form.isActive ? t('common.yes', 'Yes') : t('common.no', 'No')}\n </Tag>\n ) : (\n <input\n type=\"checkbox\"\n checked={form.isActive}\n onChange={(e) => setForm({ ...form, isActive: e.target.checked })}\n className=\"rounded border\"\n />\n )}\n </div>\n </div>\n <div>\n <label className=\"block text-sm font-medium mb-1\">Spec Type</label>\n {isViewing ? (\n <p className=\"text-sm py-2\">{form.specType === 'bundle' ? 'Bundle' : 'Simple'}</p>\n ) : (\n <>\n <select\n value={form.specType}\n onChange={(e) => setForm({ ...form, specType: e.target.value })}\n disabled={specTypeLocked}\n className=\"w-full rounded-md border px-3 py-2 text-sm disabled:opacity-50\"\n >\n <option value=\"simple\">Simple</option>\n <option value=\"bundle\">Bundle</option>\n </select>\n {specTypeLocked && (\n <p className=\"text-xs text-muted-foreground mt-1\">Cannot change after offerings or slots exist</p>\n )}\n </>\n )}\n </div>\n <div>\n <label className=\"block text-sm font-medium mb-1\">Is Assetizable?</label>\n <div className=\"flex items-center h-[38px]\">\n {isViewing ? (\n <Tag variant={form.isAssetizable ? 'warning' : 'neutral'} dot>\n {form.isAssetizable ? t('common.yes', 'Yes') : t('common.no', 'No')}\n </Tag>\n ) : (\n <>\n <input\n type=\"checkbox\"\n checked={form.isAssetizable}\n onChange={(e) => setForm({ ...form, isAssetizable: e.target.checked })}\n className=\"rounded border\"\n />\n <span className=\"ml-2 text-xs text-muted-foreground\">Creates asset records during fulfilment</span>\n </>\n )}\n </div>\n </div>\n </div>\n <div>\n <label className=\"block text-sm font-medium mb-1\">{t('cpq.specifications.description', 'Description')}</label>\n {isViewing ? (\n <p className=\"text-sm text-muted-foreground py-2 whitespace-pre-wrap\">{form.description || '\u2014'}</p>\n ) : (\n <textarea\n value={form.description ?? ''}\n onChange={(e) => setForm({ ...form, description: e.target.value })}\n rows={3}\n className=\"w-full rounded-md border px-3 py-2 text-sm\"\n />\n )}\n </div>\n {!isNew && (\n <span className=\"text-xs text-muted-foreground\">Version {form.version}</span>\n )}\n {/* In view mode the Edit button lives in the page header next to\n Delete (OM standard). Here we only render the Save/Cancel\n pair when actually editing. */}\n {!isViewing && (\n <div className=\"flex gap-3\">\n <Button\n type=\"button\"\n onClick={saveSpec}\n disabled={saving || !form.code || !form.name}\n >\n {saving ? t('common.saving', 'Saving...') : t('common.save', 'Save')}\n </Button>\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={() => {\n if (isNew) {\n router.push('/backend/cpq/specifications')\n return\n }\n // Revert any in-flight edits and go back to read-only.\n if (formSnapshot) setForm(formSnapshot)\n setFormSnapshot(null)\n setGeneralMode('view')\n }}\n >\n {t('common.cancel', 'Cancel')}\n </Button>\n </div>\n )}\n </div>\n )\n })()}\n\n {/* \u2500\u2500\u2500 Attributes Tab \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */}\n {tab === 'attributes' && !isNew && (\n <div className=\"space-y-4\">\n <div className=\"flex justify-end\">\n <button\n onClick={() => startEditAttr()}\n className=\"inline-flex items-center justify-center rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground hover:bg-primary/90\"\n >\n {t('cpq.specifications.addAttribute', 'Add Attribute')}\n </button>\n </div>\n\n {editingAttr && (\n <div className=\"rounded-lg border bg-card p-4 space-y-3\">\n <h3 className=\"font-medium text-sm\">\n {editingAttr.id ? 'Edit Attribute' : 'New Attribute'}\n </h3>\n <div className=\"grid grid-cols-3 gap-3\">\n <div>\n <label className=\"block text-xs font-medium mb-1\">Code</label>\n <input type=\"text\" value={editingAttr.code} onChange={(e) => setEditingAttr({ ...editingAttr, code: e.target.value })} className=\"w-full rounded-md border px-2 py-1.5 text-sm\" />\n </div>\n <div>\n <label className=\"block text-xs font-medium mb-1\">Name</label>\n <input type=\"text\" value={editingAttr.name} onChange={(e) => setEditingAttr({ ...editingAttr, name: e.target.value })} className=\"w-full rounded-md border px-2 py-1.5 text-sm\" />\n </div>\n <div>\n <label className=\"block text-xs font-medium mb-1\">Type</label>\n {/* Reset the default when the type changes \u2014 a default kept from a\n different type (e.g. a numeric default on a now-boolean attr)\n would be invalid and confusing. */}\n <select value={editingAttr.attributeType} onChange={(e) => setEditingAttr({ ...editingAttr, attributeType: e.target.value, defaultValue: null })} className=\"w-full rounded-md border px-2 py-1.5 text-sm\">\n <option value=\"text\">Text</option>\n <option value=\"number\">Number</option>\n <option value=\"boolean\">Boolean</option>\n <option value=\"select\">Select</option>\n <option value=\"multi-select\">Multi-Select</option>\n <option value=\"reference\">Reference</option>\n </select>\n </div>\n <div>\n <label className=\"block text-xs font-medium mb-1\">Resolution Time</label>\n <select value={editingAttr.resolutionTime} onChange={(e) => setEditingAttr({ ...editingAttr, resolutionTime: e.target.value })} className=\"w-full rounded-md border px-2 py-1.5 text-sm\">\n <option value=\"run_time\">Run-time (quoting)</option>\n <option value=\"design_time\">Design-time (offering)</option>\n </select>\n </div>\n <div>\n <label className=\"block text-xs font-medium mb-1\">Sort Order</label>\n <NumberInput\n integer\n value={editingAttr.sortOrder}\n onChange={(n) => setEditingAttr({ ...editingAttr, sortOrder: n ?? 0 })}\n />\n </div>\n <div>\n <label className=\"block text-xs font-medium mb-1\">Help Text</label>\n <input type=\"text\" value={editingAttr.helpText ?? ''} onChange={(e) => setEditingAttr({ ...editingAttr, helpText: e.target.value || null })} className=\"w-full rounded-md border px-2 py-1.5 text-sm\" />\n </div>\n {/* Reference attributes resolve to an FK UUID at run-time, so a\n free-text scalar default has no sensible meaning \u2014 omit the\n field entirely for them. */}\n {editingAttr.attributeType !== 'reference' && (\n <div>\n <label className=\"block text-xs font-medium mb-1\">{t('cpq.specifications.defaultValue', 'Default Value')}</label>\n {editingAttr.attributeType === 'number' ? (\n <NumberInput\n value={typeof editingAttr.defaultValue === 'number' ? editingAttr.defaultValue : null}\n onChange={(n) => setEditingAttr({ ...editingAttr, defaultValue: n })}\n placeholder={t('cpq.specifications.noDefault', 'No default')}\n />\n ) : editingAttr.attributeType === 'boolean' ? (\n <select\n value={editingAttr.defaultValue === true ? 'true' : editingAttr.defaultValue === false ? 'false' : ''}\n onChange={(e) => setEditingAttr({ ...editingAttr, defaultValue: e.target.value === '' ? null : e.target.value === 'true' })}\n className=\"w-full rounded-md border px-2 py-1.5 text-sm\"\n >\n <option value=\"\">{t('cpq.specifications.noDefault', 'No default')}</option>\n <option value=\"true\">{t('cpq.specifications.booleanTrue', 'True')}</option>\n <option value=\"false\">{t('cpq.specifications.booleanFalse', 'False')}</option>\n </select>\n ) : (editingAttr.attributeType === 'select' || editingAttr.attributeType === 'multi-select') ? (\n <>\n <select\n multiple={editingAttr.attributeType === 'multi-select'}\n value={\n editingAttr.attributeType === 'multi-select'\n ? (Array.isArray(editingAttr.defaultValue) ? editingAttr.defaultValue.map(String) : [])\n : (editingAttr.defaultValue == null ? '' : String(editingAttr.defaultValue))\n }\n onChange={(e) => {\n if (editingAttr.attributeType === 'multi-select') {\n const vals = Array.from(e.target.selectedOptions).map((o) => o.value).filter((v) => v !== '')\n setEditingAttr({ ...editingAttr, defaultValue: vals.length ? vals : null })\n } else {\n setEditingAttr({ ...editingAttr, defaultValue: e.target.value === '' ? null : e.target.value })\n }\n }}\n className=\"w-full rounded-md border px-2 py-1.5 text-sm\"\n >\n {/* `multiple` selects can't carry a placeholder row, so only the\n single-select variant gets an explicit \"No default\" option. */}\n {editingAttr.attributeType === 'select' && <option value=\"\">{t('cpq.specifications.noDefault', 'No default')}</option>}\n {editingOptions\n .filter((o) => o.value.trim() !== '')\n .map((o) => (\n <option key={o.value} value={o.value}>\n {o.label || o.value}\n </option>\n ))}\n </select>\n {editingAttr.attributeType === 'multi-select' && (\n <p className=\"text-xs text-muted-foreground mt-1\">\n {t('cpq.specifications.multiSelectDefaultHint', 'Ctrl/Cmd-click to select several, or deselect all to clear the default.')}\n </p>\n )}\n </>\n ) : (\n <input\n type=\"text\"\n value={editingAttr.defaultValue == null ? '' : String(editingAttr.defaultValue)}\n onChange={(e) => setEditingAttr({ ...editingAttr, defaultValue: e.target.value === '' ? null : e.target.value })}\n placeholder={t('cpq.specifications.noDefault', 'No default')}\n className=\"w-full rounded-md border px-2 py-1.5 text-sm\"\n />\n )}\n </div>\n )}\n {editingAttr.attributeType === 'reference' && (\n <>\n <div>\n <label className=\"block text-xs font-medium mb-1\">Reference Entity</label>\n <input type=\"text\" value={editingAttr.referenceEntity ?? ''} onChange={(e) => setEditingAttr({ ...editingAttr, referenceEntity: e.target.value || null })} placeholder=\"e.g. CatalogProduct\" className=\"w-full rounded-md border px-2 py-1.5 text-sm\" />\n </div>\n </>\n )}\n {(editingAttr.attributeType === 'select' || editingAttr.attributeType === 'multi-select') && (\n <div className=\"col-span-3 space-y-2\">\n <div className=\"flex items-center justify-between\">\n <label className=\"block text-xs font-medium\">Options</label>\n <button\n type=\"button\"\n onClick={() => setEditingOptions([...editingOptions, { value: '', label: '' }])}\n className=\"text-xs text-primary hover:underline\"\n >\n + Add option\n </button>\n </div>\n {editingOptions.length === 0 ? (\n <div className=\"text-xs text-muted-foreground py-2\">No options defined. Click "Add option" to start.</div>\n ) : (\n <div className=\"space-y-1.5\">\n {editingOptions.map((opt, idx) => (\n <div key={idx} className=\"flex items-center gap-2\">\n <input\n type=\"text\"\n value={opt.value}\n onChange={(e) => {\n const next = [...editingOptions]\n next[idx] = { ...next[idx], value: e.target.value }\n setEditingOptions(next)\n }}\n placeholder=\"Value (e.g. aws)\"\n className=\"flex-1 rounded-md border px-2 py-1.5 text-sm\"\n />\n <input\n type=\"text\"\n value={opt.label}\n onChange={(e) => {\n const next = [...editingOptions]\n next[idx] = { ...next[idx], label: e.target.value }\n setEditingOptions(next)\n }}\n placeholder=\"Label (e.g. Amazon Web Services)\"\n className=\"flex-1 rounded-md border px-2 py-1.5 text-sm\"\n />\n <button\n type=\"button\"\n onClick={() => setEditingOptions(editingOptions.filter((_, i) => i !== idx))}\n className=\"text-destructive hover:text-destructive/80 text-sm px-1\"\n title=\"Remove\"\n >\n \u00D7\n </button>\n </div>\n ))}\n </div>\n )}\n </div>\n )}\n <div className=\"col-span-3 space-y-2\">\n <label className=\"flex items-center gap-1.5 text-xs font-medium\">\n <input\n type=\"checkbox\"\n checked={dependsOnEnabled}\n onChange={(e) => setDependsOnEnabled(e.target.checked)}\n className=\"rounded border\"\n />\n Depends on another attribute\n </label>\n {dependsOnEnabled && (() => {\n const parentAttr = attributes.find((a) => a.code === dependsOnAttrCode)\n return (\n <div className=\"space-y-3\">\n <div className=\"grid grid-cols-2 gap-3\">\n <div>\n <label className=\"block text-xs font-medium mb-1\">Parent Attribute Code</label>\n <select\n value={dependsOnAttrCode}\n onChange={(e) => {\n setDependsOnAttrCode(e.target.value)\n // Parent changed \u2014 `when` values that referenced the old\n // parent's options no longer make sense, but clearing them\n // would silently destroy user work. Leave them as text; the\n // RuleRow will fall back to free-text input when the new\n // parent doesn't have enumerated options.\n }}\n className=\"w-full rounded-md border px-2 py-1.5 text-sm\"\n >\n <option value=\"\">Select attribute...</option>\n {attributes.filter((a) => editingAttr && a.code !== editingAttr.code).map((a) => (\n <option key={a.code} value={a.code}>{a.name} ({a.code})</option>\n ))}\n </select>\n </div>\n <div>\n <label className=\"block text-xs font-medium mb-1\">Effect</label>\n <select\n value={dependsOnEffect}\n onChange={(e) => {\n const next = e.target.value as DependsOnEffect\n setDependsOnEffect(next)\n // `then` shape differs per effect \u2014 drop existing rules so\n // we never persist a mis-typed payload.\n setDependsOnRules([])\n }}\n className=\"w-full rounded-md border px-2 py-1.5 text-sm\"\n >\n <option value=\"filter_options\">Filter options</option>\n <option value=\"set_value\">Set value</option>\n <option value=\"toggle_required\">Toggle required</option>\n </select>\n </div>\n </div>\n <div>\n <label className=\"block text-xs font-medium mb-2\">Rules</label>\n <DependsOnRulesEditor\n effect={dependsOnEffect}\n rules={dependsOnRules}\n onChange={setDependsOnRules}\n parentOptions={parentAttr?.options ?? null}\n childOptions={editingOptions.length > 0 ? editingOptions : null}\n />\n </div>\n </div>\n )\n })()}\n </div>\n <div className=\"flex items-end gap-4\">\n <label className=\"flex items-center gap-1.5 text-sm\">\n <input type=\"checkbox\" checked={editingAttr.isRequired} onChange={(e) => setEditingAttr({ ...editingAttr, isRequired: e.target.checked })} className=\"rounded border\" />\n Required\n </label>\n <label className=\"flex items-center gap-1.5 text-sm\">\n <input type=\"checkbox\" checked={editingAttr.isActive} onChange={(e) => setEditingAttr({ ...editingAttr, isActive: e.target.checked })} className=\"rounded border\" />\n Active\n </label>\n </div>\n </div>\n <div className=\"flex gap-2\">\n <button onClick={saveAttribute} disabled={saving} className=\"inline-flex items-center rounded-md bg-primary px-3 py-1.5 text-sm font-medium text-primary-foreground hover:bg-primary/90 disabled:opacity-50\">\n {saving ? 'Saving...' : 'Save'}\n </button>\n <button onClick={() => setEditingAttr(null)} className=\"inline-flex items-center rounded-md border px-3 py-1.5 text-sm font-medium hover:bg-muted\">Cancel</button>\n </div>\n </div>\n )}\n\n {attributes.length === 0 ? (\n <div className=\"rounded-lg border bg-card p-6 text-center text-sm text-muted-foreground\">\n No attributes defined. Add design-time and run-time attributes for this specification.\n </div>\n ) : (\n <div className=\"rounded-lg border\">\n <table className=\"w-full text-sm\">\n <thead>\n <tr className=\"border-b bg-muted/50\">\n <th className=\"px-4 py-3 text-left font-medium\">Code</th>\n <th className=\"px-4 py-3 text-left font-medium\">Name</th>\n <th className=\"px-4 py-3 text-left font-medium\">Type</th>\n <th className=\"px-4 py-3 text-left font-medium\">Resolution</th>\n <th className=\"px-4 py-3 text-left font-medium\">Options</th>\n <th className=\"px-4 py-3 text-left font-medium\">Required</th>\n <th className=\"px-4 py-3 text-right font-medium\">Actions</th>\n </tr>\n </thead>\n <tbody>\n {attributes.map((attr) => (\n <tr key={attr.id} className=\"border-b\">\n <td className=\"px-4 py-3 font-mono text-xs\">{attr.code}</td>\n <td className=\"px-4 py-3\">{attr.name}</td>\n <td className=\"px-4 py-3\">{attr.attributeType}</td>\n <td className=\"px-4 py-3\">\n <Tag variant={attr.resolutionTime === 'design_time' ? 'info' : 'neutral'} className=\"px-2 text-xs\">\n {attr.resolutionTime === 'design_time' ? 'design' : 'run'}\n </Tag>\n </td>\n <td className=\"px-4 py-3 text-muted-foreground\">{attr.options ? `${attr.options.length} options` : '\u2014'}</td>\n <td className=\"px-4 py-3\">{attr.isRequired ? 'Yes' : 'No'}</td>\n <td className=\"px-4 py-3 text-right\">\n <button onClick={() => startEditAttr(attr)} className=\"text-xs text-primary hover:underline mr-2\">Edit</button>\n <button onClick={() => deleteAttribute(attr.id)} className=\"text-xs text-destructive hover:underline\">Delete</button>\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n )}\n </div>\n )}\n\n {/* \u2500\u2500\u2500 Offerings Tab \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */}\n {tab === 'offerings' && !isNew && (\n <div className=\"space-y-4\">\n <div className=\"flex justify-end\">\n <button\n onClick={() => startEditOffering()}\n className=\"inline-flex items-center justify-center rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground hover:bg-primary/90\"\n >\n {t('cpq.specifications.addOffering', 'Add Offering')}\n </button>\n </div>\n\n {editingOffering && (\n <div className=\"rounded-lg border bg-card p-4 space-y-3\">\n <h3 className=\"font-medium text-sm\">\n {editingOffering.id ? 'Edit Offering' : 'New Offering'}\n </h3>\n <div className=\"grid grid-cols-4 gap-3\">\n <div>\n <label className=\"block text-xs font-medium mb-1\">Code</label>\n <input type=\"text\" value={editingOffering.code} onChange={(e) => setEditingOffering({ ...editingOffering, code: e.target.value })} placeholder=\"e.g. gix-cloud-connect-aws\" className=\"w-full rounded-md border px-2 py-1.5 text-sm\" />\n </div>\n <div>\n <label className=\"block text-xs font-medium mb-1\">Name</label>\n <input type=\"text\" value={editingOffering.name} onChange={(e) => setEditingOffering({ ...editingOffering, name: e.target.value })} className=\"w-full rounded-md border px-2 py-1.5 text-sm\" />\n </div>\n <div>\n <label className=\"block text-xs font-medium mb-1\">Lifecycle Status</label>\n <select value={editingOffering.lifecycleStatus} onChange={(e) => setEditingOffering({ ...editingOffering, lifecycleStatus: e.target.value })} className=\"w-full rounded-md border px-2 py-1.5 text-sm\">\n <option value=\"draft\">Draft</option>\n <option value=\"active\">Active</option>\n <option value=\"deprecated\">Deprecated</option>\n </select>\n </div>\n <div>\n <label className=\"block text-xs font-medium mb-1\">Is Active?</label>\n <div className=\"flex items-center h-[30px]\">\n <input type=\"checkbox\" checked={editingOffering.isActive} onChange={(e) => setEditingOffering({ ...editingOffering, isActive: e.target.checked })} className=\"rounded border\" />\n </div>\n </div>\n </div>\n <div>\n <label className=\"block text-xs font-medium mb-1\">Description</label>\n <input type=\"text\" value={editingOffering.description ?? ''} onChange={(e) => setEditingOffering({ ...editingOffering, description: e.target.value || null })} className=\"w-full rounded-md border px-2 py-1.5 text-sm\" />\n </div>\n {designTimeAttrs.length > 0 ? (\n <div className=\"space-y-3\">\n <label className=\"block text-xs font-medium\">Design-Time Values</label>\n <div className=\"grid grid-cols-2 gap-3\">\n {designTimeAttrs.map((attr) => (\n <div key={attr.code}>\n <label className=\"block text-xs font-medium mb-1\">\n {attr.name}\n {attr.isRequired && <span className=\"text-destructive ml-0.5\">*</span>}\n </label>\n {(attr.attributeType === 'select' || attr.attributeType === 'enum') && attr.options ? (\n <select\n value={String(editingDtValues[attr.code] ?? '')}\n onChange={(e) => setEditingDtValues({ ...editingDtValues, [attr.code]: e.target.value || null })}\n className=\"w-full rounded-md border px-2 py-1.5 text-sm\"\n >\n <option value=\"\">Select {attr.name}...</option>\n {attr.options.map((opt) => (\n <option key={opt.value} value={opt.value}>{opt.label}</option>\n ))}\n </select>\n ) : attr.attributeType === 'number' ? (\n <NumberInput\n value={typeof editingDtValues[attr.code] === 'number' ? (editingDtValues[attr.code] as number) : null}\n onChange={(n) => setEditingDtValues({ ...editingDtValues, [attr.code]: n })}\n />\n ) : attr.attributeType === 'boolean' ? (\n <div className=\"pt-1\">\n <label className=\"flex items-center gap-1.5 text-sm\">\n <input\n type=\"checkbox\"\n checked={!!editingDtValues[attr.code]}\n onChange={(e) => setEditingDtValues({ ...editingDtValues, [attr.code]: e.target.checked })}\n className=\"rounded border\"\n />\n {attr.name}\n </label>\n </div>\n ) : (\n <input\n type=\"text\"\n value={String(editingDtValues[attr.code] ?? '')}\n onChange={(e) => setEditingDtValues({ ...editingDtValues, [attr.code]: e.target.value || null })}\n className=\"w-full rounded-md border px-2 py-1.5 text-sm\"\n placeholder={attr.helpText ?? undefined}\n />\n )}\n {attr.helpText && <p className=\"text-xs text-muted-foreground mt-0.5\">{attr.helpText}</p>}\n </div>\n ))}\n </div>\n </div>\n ) : (\n <div className=\"text-xs text-muted-foreground py-1\">\n No design-time attributes defined on this specification. All attributes are run-time.\n </div>\n )}\n <div className=\"flex gap-2\">\n <button onClick={saveOffering} disabled={saving} className=\"inline-flex items-center rounded-md bg-primary px-3 py-1.5 text-sm font-medium text-primary-foreground hover:bg-primary/90 disabled:opacity-50\">\n {saving ? 'Saving...' : 'Save'}\n </button>\n <button onClick={() => setEditingOffering(null)} className=\"inline-flex items-center rounded-md border px-3 py-1.5 text-sm font-medium hover:bg-muted\">Cancel</button>\n </div>\n </div>\n )}\n\n {offerings.length === 0 ? (\n <div className=\"rounded-lg border bg-card p-6 text-center text-sm text-muted-foreground\">\n No offerings created. An offering is a sellable instance of this specification with fixed design-time values and attached charges.\n </div>\n ) : (\n <div className=\"rounded-lg border\">\n <table className=\"w-full text-sm\">\n <thead>\n <tr className=\"border-b bg-muted/50\">\n <th className=\"px-3 py-3 text-left font-medium\">Code</th>\n <th className=\"px-3 py-3 text-left font-medium\">Name</th>\n <th className=\"px-3 py-3 text-left font-medium\">Status</th>\n <th className=\"px-3 py-3 text-left font-medium\">Design-Time Values</th>\n <th className=\"px-3 py-3 text-right font-medium\">Actions</th>\n </tr>\n </thead>\n <tbody>\n {offerings.map((o) => (\n <tr\n key={o.id}\n onClick={() => router.push(`/backend/cpq/offerings/${o.id}`)}\n className=\"border-b cursor-pointer hover:bg-muted/30 transition-colors\"\n >\n <td className=\"px-3 py-3 font-mono text-xs\">{o.code}</td>\n <td className=\"px-3 py-3 font-medium\">{o.name}</td>\n <td className=\"px-3 py-3\">\n <Tag variant={lifecycleStatusMap[o.lifecycleStatus as LifecycleStatus] ?? 'neutral'} dot>\n {formatStatusLabel(o.lifecycleStatus)}\n </Tag>\n </td>\n <td className=\"px-3 py-3 text-muted-foreground text-xs\">\n {Object.keys(o.designTimeValues).length > 0\n ? Object.entries(o.designTimeValues).map(([k, v]) => `${k}=${v}`).join(', ')\n : '\u2014'}\n </td>\n <td className=\"px-3 py-3 text-right\">\n <button onClick={(e) => { e.stopPropagation(); startEditOffering(o) }} className=\"text-xs text-primary hover:underline mr-2\">Edit</button>\n <button onClick={(e) => { e.stopPropagation(); deleteOffering(o.id) }} className=\"text-xs text-destructive hover:underline\">Delete</button>\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n )}\n </div>\n )}\n\n {/* \u2500\u2500\u2500 Relationships Tab \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */}\n {tab === 'relationships' && !isNew && (\n <div className=\"space-y-4\">\n <div className=\"flex justify-end\">\n <button\n onClick={() => startEditRel()}\n className=\"inline-flex items-center justify-center rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground hover:bg-primary/90\"\n >\n {t('cpq.specifications.addRelationship', 'Add Relationship')}\n </button>\n </div>\n\n {editingRel && (\n <div className=\"rounded-lg border bg-card p-4 space-y-3\">\n <h3 className=\"font-medium text-sm\">\n {editingRel.id ? 'Edit Relationship' : 'New Relationship'}\n </h3>\n <div className=\"grid grid-cols-3 gap-3\">\n <div>\n <label className=\"block text-xs font-medium mb-1\">Type</label>\n <select value={editingRel.relationshipType} onChange={(e) => setEditingRel({ ...editingRel, relationshipType: e.target.value })} className=\"w-full rounded-md border px-2 py-1.5 text-sm\">\n <option value=\"parent_child\">Parent / Child</option>\n <option value=\"requires\">Requires</option>\n <option value=\"excludes\">Excludes</option>\n </select>\n </div>\n <div>\n <label className=\"block text-xs font-medium mb-1\">Target Specification</label>\n <select value={editingRel.targetSpecId} onChange={(e) => setEditingRel({ ...editingRel, targetSpecId: e.target.value })} className=\"w-full rounded-md border px-2 py-1.5 text-sm\">\n <option value=\"\">Select...</option>\n {allSpecs.filter((s) => s.id !== specId).map((s) => (\n <option key={s.id} value={s.id}>{s.name} ({s.code})</option>\n ))}\n </select>\n </div>\n <div className=\"grid grid-cols-2 gap-2\">\n <div>\n <label className=\"block text-xs font-medium mb-1\">Min</label>\n <NumberInput\n integer\n min={0}\n value={editingRel.cardinalityMin}\n onChange={(n) => setEditingRel({ ...editingRel, cardinalityMin: n ?? 0 })}\n />\n </div>\n <div>\n <label className=\"block text-xs font-medium mb-1\">Max</label>\n <NumberInput\n integer\n min={0}\n value={editingRel.cardinalityMax}\n onChange={(n) => setEditingRel({ ...editingRel, cardinalityMax: n })}\n placeholder=\"\u221E\"\n />\n </div>\n </div>\n </div>\n <div>\n <label className=\"block text-xs font-medium mb-1\">Condition (JSON)</label>\n <textarea value={conditionJson} onChange={(e) => setConditionJson(e.target.value)} rows={3} className=\"w-full rounded-md border px-2 py-1.5 text-sm font-mono\" placeholder='null or {\"attribute\":\"direction\",\"operator\":\"in\",\"value\":[\"inbound\"]}' />\n </div>\n <div className=\"flex gap-2\">\n <button onClick={saveRelationship} disabled={saving} className=\"inline-flex items-center rounded-md bg-primary px-3 py-1.5 text-sm font-medium text-primary-foreground hover:bg-primary/90 disabled:opacity-50\">\n {saving ? 'Saving...' : 'Save'}\n </button>\n <button onClick={() => setEditingRel(null)} className=\"inline-flex items-center rounded-md border px-3 py-1.5 text-sm font-medium hover:bg-muted\">Cancel</button>\n </div>\n </div>\n )}\n\n {relationships.length === 0 ? (\n <div className=\"rounded-lg border bg-card p-6 text-center text-sm text-muted-foreground\">\n No relationships defined. Declare parent/child, requires, or excludes relationships with other specifications.\n </div>\n ) : (\n <div className=\"rounded-lg border\">\n <table className=\"w-full text-sm\">\n <thead>\n <tr className=\"border-b bg-muted/50\">\n <th className=\"px-4 py-3 text-left font-medium\">Type</th>\n <th className=\"px-4 py-3 text-left font-medium\">Source</th>\n <th className=\"px-4 py-3 text-left font-medium\">Target</th>\n <th className=\"px-4 py-3 text-left font-medium\">Cardinality</th>\n <th className=\"px-4 py-3 text-left font-medium\">Condition</th>\n <th className=\"px-4 py-3 text-right font-medium\">Actions</th>\n </tr>\n </thead>\n <tbody>\n {relationships.map((rel) => (\n <tr key={rel.id} className=\"border-b\">\n <td className=\"px-4 py-3\">\n <Tag\n variant={\n rel.relationshipType === 'parent_child' ? 'brand' :\n rel.relationshipType === 'requires' ? 'info' :\n 'error'\n }\n >\n {rel.relationshipType}\n </Tag>\n </td>\n <td className=\"px-4 py-3 text-sm\">{getSpecName(rel.sourceSpecId)}</td>\n <td className=\"px-4 py-3 text-sm\">{getSpecName(rel.targetSpecId)}</td>\n <td className=\"px-4 py-3 text-muted-foreground\">{rel.cardinalityMin}..{rel.cardinalityMax ?? '\u221E'}</td>\n <td className=\"px-4 py-3 text-muted-foreground text-xs\">{rel.condition ? JSON.stringify(rel.condition) : '\u2014'}</td>\n <td className=\"px-4 py-3 text-right\">\n <button onClick={() => startEditRel(rel)} className=\"text-xs text-primary hover:underline mr-2\">Edit</button>\n <button onClick={() => deleteRelationship(rel.id)} className=\"text-xs text-destructive hover:underline\">Delete</button>\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n )}\n </div>\n )}\n\n {/* \u2500\u2500\u2500 Bundle Slots Tab \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */}\n {tab === 'slots' && !isNew && form.specType === 'bundle' && (\n <div className=\"space-y-4\">\n <div className=\"flex justify-end\">\n <button\n onClick={() => setEditingSlot({ ...EMPTY_SLOT })}\n className=\"inline-flex items-center justify-center rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground hover:bg-primary/90\"\n >\n + Add Slot\n </button>\n </div>\n\n {editingSlot && (\n <div className=\"rounded-lg border bg-card p-6 space-y-4\">\n <h3 className=\"text-sm font-semibold\">{editingSlot.id ? 'Edit Bundle Slot' : 'New Bundle Slot'}</h3>\n <div className=\"grid grid-cols-2 gap-4\">\n <div>\n <label className=\"block text-sm font-medium mb-1\">Name</label>\n <input\n type=\"text\"\n value={editingSlot.name}\n onChange={(e) => setEditingSlot({ ...editingSlot, name: e.target.value })}\n placeholder=\"e.g. Internet Component\"\n className=\"w-full rounded-md border px-3 py-2 text-sm\"\n />\n </div>\n <div>\n <label className=\"block text-sm font-medium mb-1\">Component Group</label>\n <input\n type=\"text\"\n value={editingSlot.componentGroup}\n onChange={(e) => setEditingSlot({ ...editingSlot, componentGroup: e.target.value })}\n placeholder=\"e.g. internet, tv, phone\"\n className=\"w-full rounded-md border px-3 py-2 text-sm\"\n />\n </div>\n <div>\n <label className=\"block text-sm font-medium mb-1\">Target Specification</label>\n <select\n value={editingSlot.targetSpecId}\n onChange={(e) => setEditingSlot({ ...editingSlot, targetSpecId: e.target.value })}\n className=\"w-full rounded-md border px-3 py-2 text-sm\"\n >\n <option value=\"\">\u2014 Select specification \u2014</option>\n {allSpecs.filter((s) => s.id !== specId).map((s) => (\n <option key={s.id} value={s.id}>{s.name} ({s.code})</option>\n ))}\n </select>\n </div>\n <div>\n <label className=\"block text-sm font-medium mb-1\">Sort Order</label>\n <NumberInput\n integer\n value={editingSlot.sortOrder}\n onChange={(n) => setEditingSlot({ ...editingSlot, sortOrder: n ?? 0 })}\n />\n </div>\n <div>\n <label className=\"block text-sm font-medium mb-1\">Cardinality Min</label>\n <NumberInput\n integer\n min={0}\n value={editingSlot.cardinalityMin}\n onChange={(n) => setEditingSlot({ ...editingSlot, cardinalityMin: n ?? 0 })}\n />\n </div>\n <div>\n <label className=\"block text-sm font-medium mb-1\">Cardinality Max</label>\n <NumberInput\n integer\n min={0}\n placeholder=\"\u221E (unlimited)\"\n value={editingSlot.cardinalityMax}\n onChange={(n) => setEditingSlot({ ...editingSlot, cardinalityMax: n })}\n />\n </div>\n </div>\n <div>\n <label className=\"block text-sm font-medium mb-1\">Description</label>\n <textarea\n value={editingSlot.description ?? ''}\n onChange={(e) => setEditingSlot({ ...editingSlot, description: e.target.value })}\n rows={2}\n className=\"w-full rounded-md border px-3 py-2 text-sm\"\n />\n </div>\n <div className=\"flex gap-3\">\n <button\n onClick={async () => {\n setSaving(true)\n setError(null)\n try {\n const isEdit = !!editingSlot.id\n const payload = isEdit\n ? { id: editingSlot.id, ...editingSlot, description: editingSlot.description || null }\n : { specId, ...editingSlot, description: editingSlot.description || null }\n const res = await fetch('/api/cpq/bundle-slots', {\n method: isEdit ? 'PUT' : 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(payload),\n })\n if (!res.ok) {\n const d = await res.json()\n setError(d.error ?? 'Failed to save slot')\n return\n }\n setEditingSlot(null)\n const slotsRes = await fetch(`/api/cpq/bundle-slots?specId=${specId}`)\n if (slotsRes.ok) {\n const d = await slotsRes.json()\n setBundleSlots(d.items ?? [])\n }\n } catch {\n setError('Failed to save slot')\n } finally {\n setSaving(false)\n }\n }}\n disabled={saving || !editingSlot.name || !editingSlot.componentGroup || !editingSlot.targetSpecId}\n className=\"inline-flex items-center justify-center rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground hover:bg-primary/90 disabled:opacity-50\"\n >\n {saving ? 'Saving...' : (editingSlot.id ? 'Update' : 'Create')}\n </button>\n <button\n onClick={() => setEditingSlot(null)}\n className=\"inline-flex items-center justify-center rounded-md border px-4 py-2 text-sm font-medium hover:bg-muted\"\n >\n Cancel\n </button>\n </div>\n </div>\n )}\n\n {bundleSlots.length === 0 && !editingSlot ? (\n <div className=\"rounded-lg border bg-card p-6 text-center text-sm text-muted-foreground\">\n No bundle slots defined yet. Add slots to define what component specifications can fill this bundle.\n </div>\n ) : bundleSlots.length > 0 && (\n <div className=\"rounded-lg border overflow-hidden\">\n <table className=\"w-full text-sm\">\n <thead>\n <tr className=\"border-b bg-muted/50\">\n <th className=\"px-4 py-3 text-left font-medium\">Name</th>\n <th className=\"px-4 py-3 text-left font-medium\">Group</th>\n <th className=\"px-4 py-3 text-left font-medium\">Target Spec</th>\n <th className=\"px-4 py-3 text-left font-medium\">Cardinality</th>\n <th className=\"px-4 py-3 text-left font-medium\">Order</th>\n <th className=\"px-4 py-3 text-right font-medium\">Actions</th>\n </tr>\n </thead>\n <tbody>\n {bundleSlots.map((slot) => (\n <tr key={slot.id} className=\"border-b\">\n <td className=\"px-4 py-3 font-medium\">{slot.name}</td>\n <td className=\"px-4 py-3\">\n <Tag variant=\"info\">{slot.componentGroup}</Tag>\n </td>\n <td className=\"px-4 py-3 text-sm\">\n {slot.targetSpec ? (\n <span>\n {slot.targetSpec.name}\n {slot.targetSpec.specType === 'bundle' && (\n <Tag variant=\"brand\" className=\"ml-1 px-1.5 text-[10px]\">bundle</Tag>\n )}\n </span>\n ) : (\n <span className=\"text-muted-foreground\">Unknown</span>\n )}\n </td>\n <td className=\"px-4 py-3 text-muted-foreground\">{slot.cardinalityMin}..{slot.cardinalityMax ?? '\u221E'}</td>\n <td className=\"px-4 py-3 text-muted-foreground\">{slot.sortOrder}</td>\n <td className=\"px-4 py-3 text-right\">\n <button\n onClick={() => setEditingSlot({\n id: slot.id,\n targetSpecId: slot.targetSpecId,\n componentGroup: slot.componentGroup,\n name: slot.name,\n description: slot.description ?? '',\n cardinalityMin: slot.cardinalityMin,\n cardinalityMax: slot.cardinalityMax,\n sortOrder: slot.sortOrder,\n })}\n className=\"text-xs text-primary hover:underline mr-2\"\n >\n Edit\n </button>\n <button\n onClick={async () => {\n if (!confirm('Delete this bundle slot?')) return\n try {\n const res = await fetch('/api/cpq/bundle-slots', {\n method: 'DELETE',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ id: slot.id }),\n })\n if (res.ok) {\n setBundleSlots((prev) => prev.filter((s) => s.id !== slot.id))\n } else {\n const d = await res.json()\n setError(d.error ?? 'Failed to delete slot')\n }\n } catch {\n setError('Failed to delete slot')\n }\n }}\n className=\"text-xs text-destructive hover:underline\"\n >\n Delete\n </button>\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n )}\n </div>\n )}\n </div>\n )\n}\n"],
|
|
5
|
+
"mappings": ";AAwtBW,SA8JK,UA9JL,KAUD,YAVC;AAvtBX,YAAY,WAAW;AACvB,SAAS,YAAY;AACrB,SAAS,WAAW,iBAAiB;AACrC,SAAS,WAAW;AACpB,SAAS,aAAa;AACtB,SAAS,cAAc;AACvB,SAAS,mBAAmB;AAC5B;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OAGK;AACP,SAAS,4BAA4B;AA0IrC,MAAM,aAAa;AAAA,EACjB,MAAM;AAAA,EACN,MAAM;AAAA,EACN,aAAa;AAAA,EACb,UAAU;AAAA,EACV,eAAe;AAAA,EACf,iBAAiB;AAAA,EACjB,SAAS;AAAA,EACT,eAAe;AAAA,EACf,aAAa;AAAA,EACb,UAAU;AACZ;AAEA,MAAM,aAA0B;AAAA,EAC9B,cAAc;AAAA,EACd,gBAAgB;AAAA,EAChB,MAAM;AAAA,EACN,aAAa;AAAA,EACb,gBAAgB;AAAA,EAChB,gBAAgB;AAAA,EAChB,WAAW;AACb;AAEA,MAAM,kBAAoC;AAAA,EACxC,MAAM;AAAA,EACN,MAAM;AAAA,EACN,eAAe;AAAA,EACf,gBAAgB;AAAA,EAChB,SAAS;AAAA,EACT,aAAa;AAAA,EACb,iBAAiB;AAAA,EACjB,iBAAiB;AAAA,EACjB,WAAW;AAAA,EACX,cAAc;AAAA,EACd,UAAU;AAAA,EACV,WAAW;AAAA,EACX,YAAY;AAAA,EACZ,UAAU;AACZ;AAEA,MAAM,iBAAkC;AAAA,EACtC,MAAM;AAAA,EACN,MAAM;AAAA,EACN,aAAa;AAAA,EACb,cAAc;AAAA,EACd,kBAAkB,CAAC;AAAA,EACnB,iBAAiB;AAAA,EACjB,UAAU;AACZ;AAEA,MAAM,eAA8B;AAAA,EAClC,MAAM;AAAA,EACN,MAAM;AAAA,EACN,aAAa;AAAA,EACb,YAAY;AAAA,EACZ,eAAe;AAAA,EACf,gBAAgB;AAAA,EAChB,gBAAgB;AAAA,EAChB,YAAY;AAAA,EACZ,cAAc;AAAA,EACd,uBAAuB;AAAA,EACvB,wBAAwB;AAAA,EACxB,WAAW;AAAA,EACX,UAAU;AACZ;AAEA,MAAM,qBAA0C;AAAA,EAC9C,cAAc;AAAA,EACd,cAAc;AAAA,EACd,kBAAkB;AAAA,EAClB,gBAAgB;AAAA,EAChB,gBAAgB;AAAA,EAChB,WAAW;AAAA,EACX,UAAU;AACZ;AAIe,SAAR,wBAAyC,OAAqC;AACnF,QAAM,IAAI,KAAK;AACf,QAAM,SAAS,UAAU;AACzB,QAAM,YAAY,UAAU;AAC5B,QAAM,SAAU,MAAM,QAAQ,MAAM,WAAW;AAC/C,QAAM,QAAQ,WAAW;AAIzB,QAAM,CAAC,KAAK,MAAM,IAAI,MAAM,SAA6E,SAAS;AAClH,QAAM,CAAC,MAAM,OAAO,IAAI,MAAM,SAAS,UAAU;AACjD,QAAM,CAAC,YAAY,aAAa,IAAI,MAAM,SAAsB,CAAC,CAAC;AAClE,QAAM,CAAC,WAAW,YAAY,IAAI,MAAM,SAAqB,CAAC,CAAC;AAC/D,QAAM,CAAC,eAAe,gBAAgB,IAAI,MAAM,SAAyB,CAAC,CAAC;AAC3E,QAAM,CAAC,aAAa,cAAc,IAAI,MAAM,SAAuB,CAAC,CAAC;AACrE,QAAM,CAAC,UAAU,WAAW,IAAI,MAAM,SAA+E,CAAC,CAAC;AAEvH,QAAM,CAAC,SAAS,UAAU,IAAI,MAAM,SAAS,CAAC,KAAK;AACnD,QAAM,CAAC,QAAQ,SAAS,IAAI,MAAM,SAAS,KAAK;AAChD,QAAM,CAAC,OAAO,QAAQ,IAAI,MAAM,SAAwB,IAAI;AAE5D,QAAM,CAAC,aAAa,cAAc,IAAI,MAAM,SAAkC,IAAI;AAClF,QAAM,CAAC,iBAAiB,kBAAkB,IAAI,MAAM,SAAiC,IAAI;AACzF,QAAM,CAAC,YAAY,aAAa,IAAI,MAAM,SAAqC,IAAI;AACnF,QAAM,CAAC,aAAa,cAAc,IAAI,MAAM,SAA6B,IAAI;AAC7E,QAAM,CAAC,gBAAgB,iBAAiB,IAAI,MAAM,SAAkD,CAAC,CAAC;AACtG,QAAM,CAAC,iBAAiB,kBAAkB,IAAI,MAAM,SAAkC,CAAC,CAAC;AACxF,QAAM,CAAC,qBAAqB,sBAAsB,IAAI,MAAM,SAAsB,oBAAI,IAAI,CAAC;AAC3F,QAAM,CAAC,iBAAiB,kBAAkB,IAAI,MAAM,SAAmC,CAAC,CAAC;AACzF,QAAM,CAAC,gBAAgB,iBAAiB,IAAI,MAAM,SAAS,KAAK;AAChE,QAAM,CAAC,YAAY,aAAa,IAAI,MAAM,SAAS,EAAE,MAAM,IAAI,MAAM,IAAI,aAAa,IAAI,YAAY,OAAO,eAAe,OAAO,CAAC;AACpI,QAAM,CAAC,cAAc,eAAe,IAAI,MAAM,SAAiC,CAAC,CAAC;AACjF,QAAM,CAAC,sBAAsB,uBAAuB,IAAI,MAAM,SAAwB,IAAI;AAC1F,QAAM,CAAC,sBAAsB,uBAAuB,IAAI,MAAM,SAAwB,IAAI;AAC1F,QAAM,CAAC,gBAAgB,iBAAiB,IAAI,MAAM,SAAS,KAAK;AAChE,QAAM,CAAC,eAAe,gBAAgB,IAAI,MAAM,SAA4B,CAAC,CAAC;AAC9E,QAAM,CAAC,eAAe,gBAAgB,IAAI,MAAM,SAAS,MAAM;AAC/D,QAAM,CAAC,mBAAmB,oBAAoB,IAAI,MAAM,SAAS,EAAE;AACnE,QAAM,CAAC,iBAAiB,kBAAkB,IAAI,MAAM,SAA0B,gBAAgB;AAC9F,QAAM,CAAC,kBAAkB,mBAAmB,IAAI,MAAM,SAAS,KAAK;AACpE,QAAM,CAAC,gBAAgB,iBAAiB,IAAI,MAAM,SAA0B,CAAC,CAAC;AAK9E,QAAM,CAAC,aAAa,cAAc,IAAI,MAAM,SAA0B,QAAQ,SAAS,MAAM;AAG7F,QAAM,CAAC,cAAc,eAAe,IAAI,MAAM,SAAmC,IAAI;AAIrF,QAAM,UAAU,MAAM;AACpB,QAAI,YAAY;AAEhB,mBAAe,OAAO;AACpB,UAAI;AACF,YAAI,OAAO;AACT;AAAA,QACF;AAGA,cAAM,WAAW,MAAM,MAAM,8CAA8C;AAC3E,YAAI,SAAS,IAAI;AACf,gBAAM,IAAI,MAAM,SAAS,KAAK;AAC9B,cAAI,CAAC,UAAW,aAAY,EAAE,SAAS,CAAC,CAAC;AAAA,QAC3C;AAGA,cAAM,MAAM,MAAM,MAAM,sCAAsC,mBAAmB,MAAM,CAAC,EAAE;AAC1F,YAAI,CAAC,IAAI,IAAI;AACX,cAAI,CAAC,UAAW,UAAS,8BAA8B;AACvD;AAAA,QACF;AAEA,cAAM,OAAO,MAAM,IAAI,KAAK;AAC5B,YAAI,CAAC,WAAW;AACd,kBAAQ;AAAA,YACN,MAAM,KAAK;AAAA,YACX,MAAM,KAAK;AAAA,YACX,aAAa,KAAK,eAAe;AAAA,YACjC,UAAU,KAAK,YAAY;AAAA,YAC3B,eAAe,KAAK,iBAAiB;AAAA,YACrC,iBAAiB,KAAK;AAAA,YACtB,SAAS,KAAK;AAAA,YACd,eAAe,KAAK;AAAA,YACpB,aAAa,KAAK;AAAA,YAClB,UAAU,KAAK;AAAA,UACjB,CAAC;AACD,wBAAc,KAAK,cAAc,CAAC,CAAC;AACnC,uBAAa,KAAK,aAAa,CAAC,CAAC;AACjC,2BAAiB,KAAK,iBAAiB,CAAC,CAAC;AACzC,yBAAe,KAAK,SAAS,CAAC,CAAC;AAAA,QACjC;AAAA,MACF,SAAS,KAAK;AACZ,gBAAQ,MAAM,kBAAkB,GAAG;AACnC,YAAI,CAAC,UAAW,UAAS,gBAAgB;AAAA,MAC3C,UAAE;AACA,YAAI,CAAC,UAAW,YAAW,KAAK;AAAA,MAClC;AAAA,IACF;AAEA,SAAK;AACL,WAAO,MAAM;AAAE,kBAAY;AAAA,IAAK;AAAA,EAClC,GAAG,CAAC,QAAQ,KAAK,CAAC;AAIlB,QAAM,WAAW,YAAY;AAC3B,cAAU,IAAI;AACd,aAAS,IAAI;AACb,QAAI;AACF,YAAM,EAAE,GAAG,SAAS,IAAI;AACxB,YAAM,UAAU,QACZ,EAAE,GAAG,UAAU,aAAa,SAAS,eAAe,KAAK,IACzD,EAAE,IAAI,QAAQ,GAAG,UAAU,aAAa,SAAS,eAAe,KAAK;AAEzE,YAAM,MAAM,MAAM,MAAM,mCAAmC;AAAA,QACzD,QAAQ,QAAQ,SAAS;AAAA,QACzB,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,QAC9C,MAAM,KAAK,UAAU,OAAO;AAAA,MAC9B,CAAC;AAED,UAAI,CAAC,IAAI,IAAI;AACX,cAAM,IAAI,MAAM,IAAI,KAAK;AACzB,iBAAS,EAAE,SAAS,gBAAgB;AACpC;AAAA,MACF;AAEA,YAAM,QAAQ,MAAM,IAAI,KAAK;AAC7B,UAAI,OAAO;AACT,eAAO,KAAK,+BAA+B,MAAM,EAAE,EAAE;AAAA,MACvD,OAAO;AACL,gBAAQ;AAAA,UACN,MAAM,MAAM;AAAA,UACZ,MAAM,MAAM;AAAA,UACZ,aAAa,MAAM,eAAe;AAAA,UAClC,UAAU,MAAM,YAAY,KAAK;AAAA,UACjC,eAAe,MAAM,iBAAiB,KAAK;AAAA,UAC3C,iBAAiB,MAAM;AAAA,UACvB,SAAS,MAAM;AAAA,UACf,eAAe,MAAM;AAAA,UACrB,aAAa,MAAM;AAAA,UACnB,UAAU,MAAM;AAAA,QAClB,CAAC;AAED,wBAAgB,IAAI;AACpB,uBAAe,MAAM;AAAA,MACvB;AAAA,IACF,QAAQ;AACN,eAAS,gBAAgB;AAAA,IAC3B,UAAE;AACA,gBAAU,KAAK;AAAA,IACjB;AAAA,EACF;AAEA,QAAM,aAAa,YAAY;AAC7B,QAAI,CAAC,QAAQ,EAAE,oCAAoC,gFAAgF,CAAC,EAAG;AACvI,QAAI;AACF,YAAM,MAAM,MAAM,MAAM,mCAAmC;AAAA,QACzD,QAAQ;AAAA,QACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,QAC9C,MAAM,KAAK,UAAU,EAAE,IAAI,OAAO,CAAC;AAAA,MACrC,CAAC;AACD,UAAI,IAAI,IAAI;AACV,eAAO,KAAK,6BAA6B;AAAA,MAC3C,OAAO;AACL,cAAM,IAAI,MAAM,IAAI,KAAK;AACzB,iBAAS,EAAE,SAAS,kBAAkB;AAAA,MACxC;AAAA,IACF,QAAQ;AACN,eAAS,kBAAkB;AAAA,IAC7B;AAAA,EACF;AAIA,QAAM,gBAAgB,YAAY;AAChC,QAAI,CAAC,YAAa;AAClB,cAAU,IAAI;AACd,aAAS,IAAI;AACb,QAAI;AACF,YAAM,UAAW,YAAY,kBAAkB,YAAY,YAAY,kBAAkB,iBACrF,eAAe,OAAO,CAAC,MAAM,EAAE,MAAM,KAAK,MAAM,EAAE,IAClD;AAEJ,YAAM,YACJ,oBAAoB,oBAChB;AAAA,QACE,eAAe;AAAA,QACf,QAAQ;AAAA,QACR,OAAO,eAAe,OAAO,CAAC,MAAM,EAAE,KAAK,KAAK,EAAE,SAAS,CAAC;AAAA,MAC9D,IACA;AAEN,YAAM,SAAS,CAAC,CAAC,YAAY;AAC7B,YAAM,UAAU;AAAA,QACd,GAAG;AAAA,QACH;AAAA,QACA;AAAA,QACA;AAAA,MACF;AACA,YAAM,MAAM,MAAM,MAAM,+BAA+B;AAAA,QACrD,QAAQ,SAAS,QAAQ;AAAA,QACzB,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,QAC9C,MAAM,KAAK,UAAU,OAAO;AAAA,MAC9B,CAAC;AACD,UAAI,CAAC,IAAI,IAAI;AACX,cAAM,IAAI,MAAM,IAAI,KAAK;AACzB,iBAAS,EAAE,SAAS,0BAA0B;AAC9C;AAAA,MACF;AACA,YAAM,QAAQ,MAAM,IAAI,KAAK;AAC7B,UAAI,QAAQ;AACV,sBAAc,CAAC,SAAS,KAAK,IAAI,CAAC,MAAO,EAAE,OAAO,MAAM,KAAK,QAAQ,CAAE,CAAC;AAAA,MAC1E,OAAO;AACL,sBAAc,CAAC,SAAS,CAAC,GAAG,MAAM,KAAK,CAAC;AAAA,MAC1C;AACA,qBAAe,IAAI;AAAA,IACrB,QAAQ;AACN,eAAS,0BAA0B;AAAA,IACrC,UAAE;AACA,gBAAU,KAAK;AAAA,IACjB;AAAA,EACF;AAEA,QAAM,kBAAkB,OAAO,WAAmB;AAChD,QAAI,CAAC,QAAQ,wBAAwB,EAAG;AACxC,QAAI;AACF,YAAM,MAAM,MAAM,MAAM,+BAA+B;AAAA,QACrD,QAAQ;AAAA,QACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,QAC9C,MAAM,KAAK,UAAU,EAAE,IAAI,OAAO,CAAC;AAAA,MACrC,CAAC;AACD,UAAI,IAAI,GAAI,eAAc,CAAC,SAAS,KAAK,OAAO,CAAC,MAAM,EAAE,OAAO,MAAM,CAAC;AAAA,IACzE,QAAQ;AACN,eAAS,4BAA4B;AAAA,IACvC;AAAA,EACF;AAEA,QAAM,gBAAgB,CAAC,SAAqB;AAC1C,UAAM,UAAU,OAAO,EAAE,GAAG,KAAK,IAAI,EAAE,GAAG,gBAAgB;AAE1D,QAAI,QAAQ,kBAAkB,OAAQ,SAAQ,gBAAgB;AAC9D,mBAAe,OAAO;AACtB,sBAAkB,QAAQ,UAAU,CAAC,GAAG,QAAQ,OAAO,IAAI,CAAC,CAAC;AAC7D,UAAM,MAAM,QAAQ;AACpB,wBAAoB,CAAC,CAAC,GAAG;AACzB,yBAAqB,KAAK,iBAAiB,EAAE;AAC7C,uBAAoB,KAAK,UAA8B,gBAAgB;AACvE,sBAAkB,MAAM,QAAQ,KAAK,KAAK,IAAI,IAAI,QAAQ,CAAC,CAAC;AAAA,EAC9D;AAIA,QAAM,eAAe,YAAY;AAC/B,QAAI,CAAC,gBAAiB;AACtB,cAAU,IAAI;AACd,aAAS,IAAI;AACb,QAAI;AACF,YAAM,SAAS,CAAC,CAAC,gBAAgB;AACjC,YAAM,UAAU;AAAA,QACd,GAAG;AAAA,QACH,kBAAkB;AAAA,QAClB;AAAA,MACF;AACA,YAAM,MAAM,MAAM,MAAM,8BAA8B;AAAA,QACpD,QAAQ,SAAS,QAAQ;AAAA,QACzB,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,QAC9C,MAAM,KAAK,UAAU,OAAO;AAAA,MAC9B,CAAC;AACD,UAAI,CAAC,IAAI,IAAI;AACX,cAAM,IAAI,MAAM,IAAI,KAAK;AACzB,iBAAS,EAAE,SAAS,yBAAyB;AAC7C;AAAA,MACF;AACA,YAAM,QAAQ,MAAM,IAAI,KAAK;AAC7B,UAAI,QAAQ;AACV,qBAAa,CAAC,SAAS,KAAK,IAAI,CAAC,MAAO,EAAE,OAAO,MAAM,KAAK,QAAQ,CAAE,CAAC;AAAA,MACzE,OAAO;AACL,qBAAa,CAAC,SAAS,CAAC,GAAG,MAAM,KAAK,CAAC;AAAA,MACzC;AACA,yBAAmB,IAAI;AAAA,IACzB,QAAQ;AACN,eAAS,yBAAyB;AAAA,IACpC,UAAE;AACA,gBAAU,KAAK;AAAA,IACjB;AAAA,EACF;AAEA,QAAM,iBAAiB,OAAO,eAAuB;AACnD,QAAI,CAAC,QAAQ,uBAAuB,EAAG;AACvC,QAAI;AACF,YAAM,MAAM,MAAM,MAAM,8BAA8B;AAAA,QACpD,QAAQ;AAAA,QACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,QAC9C,MAAM,KAAK,UAAU,EAAE,IAAI,WAAW,CAAC;AAAA,MACzC,CAAC;AACD,UAAI,IAAI,GAAI,cAAa,CAAC,SAAS,KAAK,OAAO,CAAC,MAAM,EAAE,OAAO,UAAU,CAAC;AAAA,IAC5E,QAAQ;AACN,eAAS,2BAA2B;AAAA,IACtC;AAAA,EACF;AAEA,QAAM,oBAAoB,CAAC,aAAwB;AACjD,UAAM,UAAU,WAAW,EAAE,GAAG,SAAS,IAAI,EAAE,GAAG,eAAe;AACjE,uBAAmB,OAAO;AAC1B,uBAAmB,QAAQ,mBAAmB,EAAE,GAAG,QAAQ,iBAAiB,IAAI,CAAC,CAAC;AAAA,EACpF;AAIA,QAAM,yBAAyB,YAAY;AACzC,QAAI;AACF,YAAM,UAAU,MAAM,QAAQ;AAAA,QAC5B,UAAU,IAAI,CAAC,MAAM,MAAM,iCAAiC,mBAAmB,EAAE,EAAE,CAAC,EAAE,EAAE,KAAK,CAAC,MAAM,EAAE,KAAK,EAAE,KAAK,IAAI,IAAI,CAAC;AAAA,MAC7H;AACA,YAAM,YAAsC,CAAC;AAC7C,cAAQ,QAAQ,CAAC,MAAM,QAAQ;AAC7B,YAAI,KAAM,WAAU,UAAU,GAAG,EAAE,EAAE,IAAI,KAAK,WAAW,CAAC;AAAA,MAC5D,CAAC;AACD,yBAAmB,SAAS;AAAA,IAC9B,QAAQ;AACN,cAAQ,MAAM,wBAAwB;AAAA,IACxC;AAAA,EACF;AAEA,QAAM,oBAAoB,YAAY;AACpC,QAAI,cAAc,SAAS,EAAG;AAC9B,UAAM,MAAM,MAAM,MAAM,sCAAsC;AAC9D,QAAI,IAAI,IAAI;AACV,YAAM,OAAO,MAAM,IAAI,KAAK;AAC5B,uBAAiB,KAAK,SAAS,CAAC,CAAC;AAAA,IACnC;AAAA,EACF;AAEA,QAAM,0BAA0B,CAAC,OAAe;AAC9C,2BAAuB,CAAC,SAAS;AAC/B,YAAM,OAAO,IAAI,IAAI,IAAI;AACzB,UAAI,KAAK,IAAI,EAAE,EAAG,MAAK,OAAO,EAAE;AAAA,UAAQ,MAAK,IAAI,EAAE;AACnD,aAAO;AAAA,IACT,CAAC;AAAA,EACH;AAEA,QAAM,qBAAqB,MAAM;AAC/B,QAAI,oBAAoB,SAAS,UAAU,QAAQ;AACjD,6BAAuB,oBAAI,IAAI,CAAC;AAAA,IAClC,OAAO;AACL,6BAAuB,IAAI,IAAI,UAAU,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;AAAA,IAC5D;AAAA,EACF;AAEA,QAAM,iBAAiB,MAAM;AAC3B,kBAAc,EAAE,MAAM,IAAI,MAAM,IAAI,aAAa,IAAI,YAAY,OAAO,eAAe,OAAO,CAAC;AAC/F,oBAAgB,CAAC,CAAC;AAClB,4BAAwB,IAAI;AAC5B,4BAAwB,IAAI;AAC5B,sBAAkB,KAAK;AACvB,sBAAkB,IAAI;AACtB,sBAAkB;AAAA,EACpB;AAEA,QAAM,yBAAyB,YAAY;AACzC,UAAM,UAAU,UAAU,OAAO,CAAC,MAAM,oBAAoB,IAAI,EAAE,EAAE,CAAC;AACrE,QAAI,CAAC,QAAQ,UAAU,CAAC,WAAW,QAAQ,CAAC,WAAW,KAAM;AAC7D,cAAU,IAAI;AACd,aAAS,IAAI;AACb,QAAI;AACF,iBAAW,YAAY,SAAS;AAC9B,cAAM,aAAa,QAAQ,SAAS,IAAI,GAAG,SAAS,IAAI,KAAK,WAAW,IAAI,KAAK,WAAW;AAC5F,cAAM,UAAmC;AAAA,UACvC,YAAY,SAAS;AAAA,UACrB,MAAM;AAAA,UACN,MAAM,WAAW;AAAA,UACjB,aAAa,WAAW,eAAe;AAAA,UACvC,YAAY,WAAW;AAAA,UACvB,eAAe,WAAW,kBAAkB,SAAS,SAAS,WAAW;AAAA,UACzE,UAAU;AAAA,UACV,WAAW;AAAA,QACb;AACA,YAAI,WAAW,kBAAkB,QAAQ;AACvC,kBAAQ,aAAa,aAAa,SAAS,EAAE,KAAK;AAClD,kBAAQ,eAAe;AAAA,QACzB,OAAO;AACL,kBAAQ,iBAAiB;AACzB,kBAAQ,iBAAiB;AAAA,QAC3B;AACA,cAAM,MAAM,MAAM,MAAM,4BAA4B;AAAA,UAClD,QAAQ;AAAA,UACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,UAC9C,MAAM,KAAK,UAAU,OAAO;AAAA,QAC9B,CAAC;AACD,YAAI,CAAC,IAAI,IAAI;AACX,gBAAM,IAAI,MAAM,IAAI,KAAK;AACzB,mBAAS,EAAE,SAAS,6BAA6B,SAAS,IAAI,EAAE;AAChE;AAAA,QACF;AAAA,MACF;AACA,wBAAkB,KAAK;AACvB,YAAM,uBAAuB;AAAA,IAC/B,QAAQ;AACN,eAAS,wBAAwB;AAAA,IACnC,UAAE;AACA,gBAAU,KAAK;AAAA,IACjB;AAAA,EACF;AAEA,QAAM,eAAe,OAAO,YAAoB,aAAqB;AACnE,QAAI,CAAC,QAAQ,qBAAqB,EAAG;AACrC,QAAI;AACF,YAAM,MAAM,MAAM,MAAM,4BAA4B;AAAA,QAClD,QAAQ;AAAA,QACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,QAC9C,MAAM,KAAK,UAAU,EAAE,IAAI,SAAS,CAAC;AAAA,MACvC,CAAC;AACD,UAAI,IAAI,IAAI;AACV,2BAAmB,CAAC,UAAU;AAAA,UAC5B,GAAG;AAAA,UACH,CAAC,UAAU,IAAI,KAAK,UAAU,KAAK,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,OAAO,QAAQ;AAAA,QACxE,EAAE;AAAA,MACJ;AAAA,IACF,QAAQ;AACN,eAAS,yBAAyB;AAAA,IACpC;AAAA,EACF;AAEA,QAAM,0BAA0B,uBAC5B,cAAc,KAAK,CAAC,OAAO,GAAG,OAAO,oBAAoB,IACzD;AAIJ,QAAM,mBAAmB,YAAY;AACnC,QAAI,CAAC,WAAY;AACjB,cAAU,IAAI;AACd,aAAS,IAAI;AACb,QAAI;AACF,UAAI,kBAAkB,WAAW;AACjC,UAAI;AAAE,0BAAkB,kBAAkB,SAAS,OAAO,KAAK,MAAM,aAAa;AAAA,MAAE,QAAQ;AAAA,MAAa;AAEzG,YAAM,SAAS,CAAC,CAAC,WAAW;AAC5B,YAAM,UAAU;AAAA,QACd,GAAG;AAAA,QACH,WAAW;AAAA,QACX,cAAc,WAAW,gBAAgB;AAAA,MAC3C;AACA,YAAM,MAAM,MAAM,MAAM,kCAAkC;AAAA,QACxD,QAAQ,SAAS,QAAQ;AAAA,QACzB,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,QAC9C,MAAM,KAAK,UAAU,OAAO;AAAA,MAC9B,CAAC;AACD,UAAI,CAAC,IAAI,IAAI;AACX,cAAM,IAAI,MAAM,IAAI,KAAK;AACzB,iBAAS,EAAE,SAAS,6BAA6B;AACjD;AAAA,MACF;AACA,YAAM,QAAQ,MAAM,IAAI,KAAK;AAC7B,UAAI,QAAQ;AACV,yBAAiB,CAAC,SAAS,KAAK,IAAI,CAAC,MAAO,EAAE,OAAO,MAAM,KAAK,QAAQ,CAAE,CAAC;AAAA,MAC7E,OAAO;AACL,yBAAiB,CAAC,SAAS,CAAC,GAAG,MAAM,KAAK,CAAC;AAAA,MAC7C;AACA,oBAAc,IAAI;AAAA,IACpB,QAAQ;AACN,eAAS,6BAA6B;AAAA,IACxC,UAAE;AACA,gBAAU,KAAK;AAAA,IACjB;AAAA,EACF;AAEA,QAAM,qBAAqB,OAAO,UAAkB;AAClD,QAAI,CAAC,QAAQ,2BAA2B,EAAG;AAC3C,QAAI;AACF,YAAM,MAAM,MAAM,MAAM,kCAAkC;AAAA,QACxD,QAAQ;AAAA,QACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,QAC9C,MAAM,KAAK,UAAU,EAAE,IAAI,MAAM,CAAC;AAAA,MACpC,CAAC;AACD,UAAI,IAAI,GAAI,kBAAiB,CAAC,SAAS,KAAK,OAAO,CAAC,MAAM,EAAE,OAAO,KAAK,CAAC;AAAA,IAC3E,QAAQ;AACN,eAAS,+BAA+B;AAAA,IAC1C;AAAA,EACF;AAEA,QAAM,eAAe,CAAC,QAAuB;AAC3C,UAAM,UAAU,MAAM,EAAE,GAAG,IAAI,IAAI,EAAE,GAAG,oBAAoB,cAAc,OAAO;AACjF,kBAAc,OAAO;AACrB,qBAAiB,QAAQ,YAAY,KAAK,UAAU,QAAQ,WAAW,MAAM,CAAC,IAAI,MAAM;AAAA,EAC1F;AAIA,QAAM,cAAc,CAAC,OAAe,SAAS,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE,GAAG,QAAQ,GAAG,MAAM,GAAG,CAAC;AAI5F,MAAI,SAAS;AACX,WAAO,oBAAC,SAAI,WAAU,iCAAiC,YAAE,kBAAkB,YAAY,GAAE;AAAA,EAC3F;AAEA,QAAM,kBAAkB,WAAW,OAAO,CAAC,MAAM,EAAE,mBAAmB,aAAa;AAEnF,SACE,qBAAC,SAAI,WAAU,aAEb;AAAA,yBAAC,SAAI,WAAU,qCACb;AAAA,2BAAC,SAAI,WAAU,2BACb;AAAA;AAAA,UAAC;AAAA;AAAA,YACC,SAAS,MAAM,OAAO,KAAK,6BAA6B;AAAA,YACxD,WAAU;AAAA,YACX;AAAA;AAAA,cACI,EAAE,eAAe,MAAM;AAAA;AAAA;AAAA,QAC5B;AAAA,QACA,oBAAC,QAAG,WAAU,sBACX,kBAAQ,EAAE,0BAA0B,mBAAmB,IAAI,KAAK,MACnE;AAAA,QACC,CAAC,SACA,oBAAC,OAAI,SAAS,gCAAgC,KAAK,eAA+C,KAAK,WAAW,KAAG,MAClH,4BAAkB,KAAK,eAAe,GACzC;AAAA,SAEJ;AAAA,MACC,CAAC,SACA,qBAAC,SAAI,WAAU,2BAIZ;AAAA,wBAAgB,UAAU,QAAQ,aACjC;AAAA,UAAC;AAAA;AAAA,YACC,MAAK;AAAA,YACL,SAAS,MAAM;AACb,8BAAgB,IAAI;AACpB,6BAAe,MAAM;AAAA,YACvB;AAAA,YAEC,YAAE,eAAe,MAAM;AAAA;AAAA,QAC1B;AAAA,QAEF,oBAAC,UAAO,MAAK,UAAS,SAAQ,eAAc,SAAS,YAClD,YAAE,iBAAiB,QAAQ,GAC9B;AAAA,SACF;AAAA,OAEJ;AAAA,IAEC,SACC,oBAAC,SAAM,SAAQ,eAAe,iBAAM;AAAA,IAIrC,CAAC,SACA,oBAAC,SAAI,WAAU,uBACX;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,GAAI,KAAK,aAAa,WAAW,CAAC,OAAgB,IAAI,CAAC;AAAA,IACzD,EAAY,IAAI,CAAC,OACf;AAAA,MAAC;AAAA;AAAA,QAEC,SAAS,MAAM;AAAE,iBAAO,EAAgB;AAAG,cAAI,OAAO,eAAe,UAAU,SAAS,KAAK,OAAO,KAAK,eAAe,EAAE,WAAW,EAAG,wBAAuB;AAAA,QAAE;AAAA,QACjK,WAAW,8DACT,QAAQ,KAAK,gCAAgC,gEAC/C;AAAA,QAEC;AAAA,iBAAO,aAAa;AAAA,UACpB,OAAO,gBAAgB,eAAe,WAAW,MAAM;AAAA,UACvD,OAAO,eAAe,cAAc,UAAU,MAAM;AAAA,UACpD,OAAO,mBAAmB,kBAAkB,cAAc,MAAM;AAAA,UAChE,OAAO,WAAW,iBAAiB,YAAY,MAAM;AAAA;AAAA;AAAA,MAVjD;AAAA,IAWP,CACD,GACH;AAAA,KAIA,SAAS,QAAQ,eAAe,MAAM;AACtC,YAAM,YAAY,gBAAgB,UAAU,CAAC;AAI7C,YAAM,iBAAiB,CAAC,UAAU,UAAU,SAAS,KAAK,YAAY,SAAS;AAC/E,aACA,qBAAC,SAAI,WAAU,2CACb;AAAA,6BAAC,SAAI,WAAU,0BACb;AAAA,+BAAC,SACC;AAAA,gCAAC,WAAM,WAAU,kCAAkC,YAAE,2BAA2B,MAAM,GAAE;AAAA,YACvF,YACC,oBAAC,OAAE,WAAU,0BAA0B,eAAK,QAAQ,UAAI,IAExD;AAAA,cAAC;AAAA;AAAA,gBACC,MAAK;AAAA,gBACL,OAAO,KAAK;AAAA,gBACZ,UAAU,CAAC,MAAM,QAAQ,EAAE,GAAG,MAAM,MAAM,EAAE,OAAO,MAAM,CAAC;AAAA,gBAC1D,aAAY;AAAA,gBACZ,WAAU;AAAA;AAAA,YACZ;AAAA,aAEJ;AAAA,UACA,qBAAC,SACC;AAAA,gCAAC,WAAM,WAAU,kCAAkC,YAAE,2BAA2B,MAAM,GAAE;AAAA,YACvF,YACC,oBAAC,OAAE,WAAU,gBAAgB,eAAK,QAAQ,UAAI,IAE9C;AAAA,cAAC;AAAA;AAAA,gBACC,MAAK;AAAA,gBACL,OAAO,KAAK;AAAA,gBACZ,UAAU,CAAC,MAAM,QAAQ,EAAE,GAAG,MAAM,MAAM,EAAE,OAAO,MAAM,CAAC;AAAA,gBAC1D,WAAU;AAAA;AAAA,YACZ;AAAA,aAEJ;AAAA,UACA,qBAAC,SACC;AAAA,gCAAC,WAAM,WAAU,kCAAkC,YAAE,sCAAsC,kBAAkB,GAAE;AAAA,YAC9G,YACC,oBAAC,SAAI,WAAU,QACb,8BAAC,OAAI,SAAS,gCAAgC,KAAK,eAA+C,KAAK,WAAW,KAAG,MAClH,4BAAkB,KAAK,eAAe,GACzC,GACF,IAEA;AAAA,cAAC;AAAA;AAAA,gBACC,OAAO,KAAK;AAAA,gBACZ,UAAU,CAAC,MAAM,QAAQ,EAAE,GAAG,MAAM,iBAAiB,EAAE,OAAO,MAAM,CAAC;AAAA,gBACrE,WAAU;AAAA,gBAEV;AAAA,sCAAC,YAAO,OAAM,SAAQ,mBAAK;AAAA,kBAC3B,oBAAC,YAAO,OAAM,UAAS,oBAAM;AAAA,kBAC7B,oBAAC,YAAO,OAAM,cAAa,wBAAU;AAAA;AAAA;AAAA,YACvC;AAAA,aAEJ;AAAA,UACA,qBAAC,SACC;AAAA,gCAAC,WAAM,WAAU,kCAAkC,YAAE,+BAA+B,YAAY,GAAE;AAAA,YAClG,oBAAC,SAAI,WAAU,8BACZ,sBACC,oBAAC,OAAI,SAAS,KAAK,WAAW,YAAY,WAAW,KAAG,MACrD,eAAK,WAAW,EAAE,cAAc,KAAK,IAAI,EAAE,aAAa,IAAI,GAC/D,IAEA;AAAA,cAAC;AAAA;AAAA,gBACC,MAAK;AAAA,gBACL,SAAS,KAAK;AAAA,gBACd,UAAU,CAAC,MAAM,QAAQ,EAAE,GAAG,MAAM,UAAU,EAAE,OAAO,QAAQ,CAAC;AAAA,gBAChE,WAAU;AAAA;AAAA,YACZ,GAEJ;AAAA,aACF;AAAA,UACA,qBAAC,SACC;AAAA,gCAAC,WAAM,WAAU,kCAAiC,uBAAS;AAAA,YAC1D,YACC,oBAAC,OAAE,WAAU,gBAAgB,eAAK,aAAa,WAAW,WAAW,UAAS,IAE9E,iCACE;AAAA;AAAA,gBAAC;AAAA;AAAA,kBACC,OAAO,KAAK;AAAA,kBACZ,UAAU,CAAC,MAAM,QAAQ,EAAE,GAAG,MAAM,UAAU,EAAE,OAAO,MAAM,CAAC;AAAA,kBAC9D,UAAU;AAAA,kBACV,WAAU;AAAA,kBAEV;AAAA,wCAAC,YAAO,OAAM,UAAS,oBAAM;AAAA,oBAC7B,oBAAC,YAAO,OAAM,UAAS,oBAAM;AAAA;AAAA;AAAA,cAC/B;AAAA,cACC,kBACC,oBAAC,OAAE,WAAU,sCAAqC,0DAA4C;AAAA,eAElG;AAAA,aAEJ;AAAA,UACA,qBAAC,SACC;AAAA,gCAAC,WAAM,WAAU,kCAAiC,6BAAe;AAAA,YACjE,oBAAC,SAAI,WAAU,8BACZ,sBACC,oBAAC,OAAI,SAAS,KAAK,gBAAgB,YAAY,WAAW,KAAG,MAC1D,eAAK,gBAAgB,EAAE,cAAc,KAAK,IAAI,EAAE,aAAa,IAAI,GACpE,IAEA,iCACE;AAAA;AAAA,gBAAC;AAAA;AAAA,kBACC,MAAK;AAAA,kBACL,SAAS,KAAK;AAAA,kBACd,UAAU,CAAC,MAAM,QAAQ,EAAE,GAAG,MAAM,eAAe,EAAE,OAAO,QAAQ,CAAC;AAAA,kBACrE,WAAU;AAAA;AAAA,cACZ;AAAA,cACA,oBAAC,UAAK,WAAU,sCAAqC,qDAAuC;AAAA,eAC9F,GAEJ;AAAA,aACF;AAAA,WACF;AAAA,QACA,qBAAC,SACC;AAAA,8BAAC,WAAM,WAAU,kCAAkC,YAAE,kCAAkC,aAAa,GAAE;AAAA,UACrG,YACC,oBAAC,OAAE,WAAU,0DAA0D,eAAK,eAAe,UAAI,IAE/F;AAAA,YAAC;AAAA;AAAA,cACC,OAAO,KAAK,eAAe;AAAA,cAC3B,UAAU,CAAC,MAAM,QAAQ,EAAE,GAAG,MAAM,aAAa,EAAE,OAAO,MAAM,CAAC;AAAA,cACjE,MAAM;AAAA,cACN,WAAU;AAAA;AAAA,UACZ;AAAA,WAEJ;AAAA,QACC,CAAC,SACA,qBAAC,UAAK,WAAU,iCAAgC;AAAA;AAAA,UAAS,KAAK;AAAA,WAAQ;AAAA,QAKvE,CAAC,aACA,qBAAC,SAAI,WAAU,cACb;AAAA;AAAA,YAAC;AAAA;AAAA,cACC,MAAK;AAAA,cACL,SAAS;AAAA,cACT,UAAU,UAAU,CAAC,KAAK,QAAQ,CAAC,KAAK;AAAA,cAEvC,mBAAS,EAAE,iBAAiB,WAAW,IAAI,EAAE,eAAe,MAAM;AAAA;AAAA,UACrE;AAAA,UACA;AAAA,YAAC;AAAA;AAAA,cACC,MAAK;AAAA,cACL,SAAQ;AAAA,cACR,SAAS,MAAM;AACb,oBAAI,OAAO;AACT,yBAAO,KAAK,6BAA6B;AACzC;AAAA,gBACF;AAEA,oBAAI,aAAc,SAAQ,YAAY;AACtC,gCAAgB,IAAI;AACpB,+BAAe,MAAM;AAAA,cACvB;AAAA,cAEC,YAAE,iBAAiB,QAAQ;AAAA;AAAA,UAC9B;AAAA,WACF;AAAA,SAEJ;AAAA,IAEF,GAAG;AAAA,IAGF,QAAQ,gBAAgB,CAAC,SACxB,qBAAC,SAAI,WAAU,aACb;AAAA,0BAAC,SAAI,WAAU,oBACb;AAAA,QAAC;AAAA;AAAA,UACC,SAAS,MAAM,cAAc;AAAA,UAC7B,WAAU;AAAA,UAET,YAAE,mCAAmC,eAAe;AAAA;AAAA,MACvD,GACF;AAAA,MAEC,eACC,qBAAC,SAAI,WAAU,2CACb;AAAA,4BAAC,QAAG,WAAU,uBACX,sBAAY,KAAK,mBAAmB,iBACvC;AAAA,QACA,qBAAC,SAAI,WAAU,0BACb;AAAA,+BAAC,SACC;AAAA,gCAAC,WAAM,WAAU,kCAAiC,kBAAI;AAAA,YACtD,oBAAC,WAAM,MAAK,QAAO,OAAO,YAAY,MAAM,UAAU,CAAC,MAAM,eAAe,EAAE,GAAG,aAAa,MAAM,EAAE,OAAO,MAAM,CAAC,GAAG,WAAU,gDAA+C;AAAA,aAClL;AAAA,UACA,qBAAC,SACC;AAAA,gCAAC,WAAM,WAAU,kCAAiC,kBAAI;AAAA,YACtD,oBAAC,WAAM,MAAK,QAAO,OAAO,YAAY,MAAM,UAAU,CAAC,MAAM,eAAe,EAAE,GAAG,aAAa,MAAM,EAAE,OAAO,MAAM,CAAC,GAAG,WAAU,gDAA+C;AAAA,aAClL;AAAA,UACA,qBAAC,SACC;AAAA,gCAAC,WAAM,WAAU,kCAAiC,kBAAI;AAAA,YAItD,qBAAC,YAAO,OAAO,YAAY,eAAe,UAAU,CAAC,MAAM,eAAe,EAAE,GAAG,aAAa,eAAe,EAAE,OAAO,OAAO,cAAc,KAAK,CAAC,GAAG,WAAU,gDAC1J;AAAA,kCAAC,YAAO,OAAM,QAAO,kBAAI;AAAA,cACzB,oBAAC,YAAO,OAAM,UAAS,oBAAM;AAAA,cAC7B,oBAAC,YAAO,OAAM,WAAU,qBAAO;AAAA,cAC/B,oBAAC,YAAO,OAAM,UAAS,oBAAM;AAAA,cAC7B,oBAAC,YAAO,OAAM,gBAAe,0BAAY;AAAA,cACzC,oBAAC,YAAO,OAAM,aAAY,uBAAS;AAAA,eACrC;AAAA,aACF;AAAA,UACA,qBAAC,SACC;AAAA,gCAAC,WAAM,WAAU,kCAAiC,6BAAe;AAAA,YACjE,qBAAC,YAAO,OAAO,YAAY,gBAAgB,UAAU,CAAC,MAAM,eAAe,EAAE,GAAG,aAAa,gBAAgB,EAAE,OAAO,MAAM,CAAC,GAAG,WAAU,gDACxI;AAAA,kCAAC,YAAO,OAAM,YAAW,gCAAkB;AAAA,cAC3C,oBAAC,YAAO,OAAM,eAAc,oCAAsB;AAAA,eACpD;AAAA,aACF;AAAA,UACA,qBAAC,SACC;AAAA,gCAAC,WAAM,WAAU,kCAAiC,wBAAU;AAAA,YAC5D;AAAA,cAAC;AAAA;AAAA,gBACC,SAAO;AAAA,gBACP,OAAO,YAAY;AAAA,gBACnB,UAAU,CAAC,MAAM,eAAe,EAAE,GAAG,aAAa,WAAW,KAAK,EAAE,CAAC;AAAA;AAAA,YACvE;AAAA,aACF;AAAA,UACA,qBAAC,SACC;AAAA,gCAAC,WAAM,WAAU,kCAAiC,uBAAS;AAAA,YAC3D,oBAAC,WAAM,MAAK,QAAO,OAAO,YAAY,YAAY,IAAI,UAAU,CAAC,MAAM,eAAe,EAAE,GAAG,aAAa,UAAU,EAAE,OAAO,SAAS,KAAK,CAAC,GAAG,WAAU,gDAA+C;AAAA,aACxM;AAAA,UAIC,YAAY,kBAAkB,eAC7B,qBAAC,SACC;AAAA,gCAAC,WAAM,WAAU,kCAAkC,YAAE,mCAAmC,eAAe,GAAE;AAAA,YACxG,YAAY,kBAAkB,WAC7B;AAAA,cAAC;AAAA;AAAA,gBACC,OAAO,OAAO,YAAY,iBAAiB,WAAW,YAAY,eAAe;AAAA,gBACjF,UAAU,CAAC,MAAM,eAAe,EAAE,GAAG,aAAa,cAAc,EAAE,CAAC;AAAA,gBACnE,aAAa,EAAE,gCAAgC,YAAY;AAAA;AAAA,YAC7D,IACE,YAAY,kBAAkB,YAChC;AAAA,cAAC;AAAA;AAAA,gBACC,OAAO,YAAY,iBAAiB,OAAO,SAAS,YAAY,iBAAiB,QAAQ,UAAU;AAAA,gBACnG,UAAU,CAAC,MAAM,eAAe,EAAE,GAAG,aAAa,cAAc,EAAE,OAAO,UAAU,KAAK,OAAO,EAAE,OAAO,UAAU,OAAO,CAAC;AAAA,gBAC1H,WAAU;AAAA,gBAEV;AAAA,sCAAC,YAAO,OAAM,IAAI,YAAE,gCAAgC,YAAY,GAAE;AAAA,kBAClE,oBAAC,YAAO,OAAM,QAAQ,YAAE,kCAAkC,MAAM,GAAE;AAAA,kBAClE,oBAAC,YAAO,OAAM,SAAS,YAAE,mCAAmC,OAAO,GAAE;AAAA;AAAA;AAAA,YACvE,IACG,YAAY,kBAAkB,YAAY,YAAY,kBAAkB,iBAC3E,iCACE;AAAA;AAAA,gBAAC;AAAA;AAAA,kBACC,UAAU,YAAY,kBAAkB;AAAA,kBACxC,OACE,YAAY,kBAAkB,iBACzB,MAAM,QAAQ,YAAY,YAAY,IAAI,YAAY,aAAa,IAAI,MAAM,IAAI,CAAC,IAClF,YAAY,gBAAgB,OAAO,KAAK,OAAO,YAAY,YAAY;AAAA,kBAE9E,UAAU,CAAC,MAAM;AACf,wBAAI,YAAY,kBAAkB,gBAAgB;AAChD,4BAAM,OAAO,MAAM,KAAK,EAAE,OAAO,eAAe,EAAE,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,OAAO,CAAC,MAAM,MAAM,EAAE;AAC5F,qCAAe,EAAE,GAAG,aAAa,cAAc,KAAK,SAAS,OAAO,KAAK,CAAC;AAAA,oBAC5E,OAAO;AACL,qCAAe,EAAE,GAAG,aAAa,cAAc,EAAE,OAAO,UAAU,KAAK,OAAO,EAAE,OAAO,MAAM,CAAC;AAAA,oBAChG;AAAA,kBACF;AAAA,kBACA,WAAU;AAAA,kBAIT;AAAA,gCAAY,kBAAkB,YAAY,oBAAC,YAAO,OAAM,IAAI,YAAE,gCAAgC,YAAY,GAAE;AAAA,oBAC5G,eACE,OAAO,CAAC,MAAM,EAAE,MAAM,KAAK,MAAM,EAAE,EACnC,IAAI,CAAC,MACJ,oBAAC,YAAqB,OAAO,EAAE,OAC5B,YAAE,SAAS,EAAE,SADH,EAAE,KAEf,CACD;AAAA;AAAA;AAAA,cACL;AAAA,cACC,YAAY,kBAAkB,kBAC7B,oBAAC,OAAE,WAAU,sCACV,YAAE,6CAA6C,yEAAyE,GAC3H;AAAA,eAEJ,IAEA;AAAA,cAAC;AAAA;AAAA,gBACC,MAAK;AAAA,gBACL,OAAO,YAAY,gBAAgB,OAAO,KAAK,OAAO,YAAY,YAAY;AAAA,gBAC9E,UAAU,CAAC,MAAM,eAAe,EAAE,GAAG,aAAa,cAAc,EAAE,OAAO,UAAU,KAAK,OAAO,EAAE,OAAO,MAAM,CAAC;AAAA,gBAC/G,aAAa,EAAE,gCAAgC,YAAY;AAAA,gBAC3D,WAAU;AAAA;AAAA,YACZ;AAAA,aAEJ;AAAA,UAED,YAAY,kBAAkB,eAC7B,gCACE,+BAAC,SACC;AAAA,gCAAC,WAAM,WAAU,kCAAiC,8BAAgB;AAAA,YAClE,oBAAC,WAAM,MAAK,QAAO,OAAO,YAAY,mBAAmB,IAAI,UAAU,CAAC,MAAM,eAAe,EAAE,GAAG,aAAa,iBAAiB,EAAE,OAAO,SAAS,KAAK,CAAC,GAAG,aAAY,uBAAsB,WAAU,gDAA+C;AAAA,aACxP,GACF;AAAA,WAEA,YAAY,kBAAkB,YAAY,YAAY,kBAAkB,mBACxE,qBAAC,SAAI,WAAU,wBACb;AAAA,iCAAC,SAAI,WAAU,qCACb;AAAA,kCAAC,WAAM,WAAU,6BAA4B,qBAAO;AAAA,cACpD;AAAA,gBAAC;AAAA;AAAA,kBACC,MAAK;AAAA,kBACL,SAAS,MAAM,kBAAkB,CAAC,GAAG,gBAAgB,EAAE,OAAO,IAAI,OAAO,GAAG,CAAC,CAAC;AAAA,kBAC9E,WAAU;AAAA,kBACX;AAAA;AAAA,cAED;AAAA,eACF;AAAA,YACC,eAAe,WAAW,IACzB,oBAAC,SAAI,WAAU,sCAAqC,8DAA0D,IAE9G,oBAAC,SAAI,WAAU,eACZ,yBAAe,IAAI,CAAC,KAAK,QACxB,qBAAC,SAAc,WAAU,2BACvB;AAAA;AAAA,gBAAC;AAAA;AAAA,kBACC,MAAK;AAAA,kBACL,OAAO,IAAI;AAAA,kBACX,UAAU,CAAC,MAAM;AACf,0BAAM,OAAO,CAAC,GAAG,cAAc;AAC/B,yBAAK,GAAG,IAAI,EAAE,GAAG,KAAK,GAAG,GAAG,OAAO,EAAE,OAAO,MAAM;AAClD,sCAAkB,IAAI;AAAA,kBACxB;AAAA,kBACA,aAAY;AAAA,kBACZ,WAAU;AAAA;AAAA,cACZ;AAAA,cACA;AAAA,gBAAC;AAAA;AAAA,kBACC,MAAK;AAAA,kBACL,OAAO,IAAI;AAAA,kBACX,UAAU,CAAC,MAAM;AACf,0BAAM,OAAO,CAAC,GAAG,cAAc;AAC/B,yBAAK,GAAG,IAAI,EAAE,GAAG,KAAK,GAAG,GAAG,OAAO,EAAE,OAAO,MAAM;AAClD,sCAAkB,IAAI;AAAA,kBACxB;AAAA,kBACA,aAAY;AAAA,kBACZ,WAAU;AAAA;AAAA,cACZ;AAAA,cACA;AAAA,gBAAC;AAAA;AAAA,kBACC,MAAK;AAAA,kBACL,SAAS,MAAM,kBAAkB,eAAe,OAAO,CAAC,GAAG,MAAM,MAAM,GAAG,CAAC;AAAA,kBAC3E,WAAU;AAAA,kBACV,OAAM;AAAA,kBACP;AAAA;AAAA,cAED;AAAA,iBA9BQ,GA+BV,CACD,GACH;AAAA,aAEJ;AAAA,UAEF,qBAAC,SAAI,WAAU,wBACb;AAAA,iCAAC,WAAM,WAAU,iDACf;AAAA;AAAA,gBAAC;AAAA;AAAA,kBACC,MAAK;AAAA,kBACL,SAAS;AAAA,kBACT,UAAU,CAAC,MAAM,oBAAoB,EAAE,OAAO,OAAO;AAAA,kBACrD,WAAU;AAAA;AAAA,cACZ;AAAA,cAAE;AAAA,eAEJ;AAAA,YACC,qBAAqB,MAAM;AAC1B,oBAAM,aAAa,WAAW,KAAK,CAAC,MAAM,EAAE,SAAS,iBAAiB;AACtE,qBACE,qBAAC,SAAI,WAAU,aACb;AAAA,qCAAC,SAAI,WAAU,0BACb;AAAA,uCAAC,SACC;AAAA,wCAAC,WAAM,WAAU,kCAAiC,mCAAqB;AAAA,oBACvE;AAAA,sBAAC;AAAA;AAAA,wBACC,OAAO;AAAA,wBACP,UAAU,CAAC,MAAM;AACf,+CAAqB,EAAE,OAAO,KAAK;AAAA,wBAMrC;AAAA,wBACA,WAAU;AAAA,wBAEV;AAAA,8CAAC,YAAO,OAAM,IAAG,iCAAmB;AAAA,0BACnC,WAAW,OAAO,CAAC,MAAM,eAAe,EAAE,SAAS,YAAY,IAAI,EAAE,IAAI,CAAC,MACzE,qBAAC,YAAoB,OAAO,EAAE,MAAO;AAAA,8BAAE;AAAA,4BAAK;AAAA,4BAAG,EAAE;AAAA,4BAAK;AAAA,+BAAzC,EAAE,IAAwC,CACxD;AAAA;AAAA;AAAA,oBACH;AAAA,qBACF;AAAA,kBACA,qBAAC,SACC;AAAA,wCAAC,WAAM,WAAU,kCAAiC,oBAAM;AAAA,oBACxD;AAAA,sBAAC;AAAA;AAAA,wBACC,OAAO;AAAA,wBACP,UAAU,CAAC,MAAM;AACf,gCAAM,OAAO,EAAE,OAAO;AACtB,6CAAmB,IAAI;AAGvB,4CAAkB,CAAC,CAAC;AAAA,wBACtB;AAAA,wBACA,WAAU;AAAA,wBAEV;AAAA,8CAAC,YAAO,OAAM,kBAAiB,4BAAc;AAAA,0BAC7C,oBAAC,YAAO,OAAM,aAAY,uBAAS;AAAA,0BACnC,oBAAC,YAAO,OAAM,mBAAkB,6BAAe;AAAA;AAAA;AAAA,oBACjD;AAAA,qBACF;AAAA,mBACF;AAAA,gBACA,qBAAC,SACC;AAAA,sCAAC,WAAM,WAAU,kCAAiC,mBAAK;AAAA,kBACvD;AAAA,oBAAC;AAAA;AAAA,sBACC,QAAQ;AAAA,sBACR,OAAO;AAAA,sBACP,UAAU;AAAA,sBACV,eAAe,YAAY,WAAW;AAAA,sBACtC,cAAc,eAAe,SAAS,IAAI,iBAAiB;AAAA;AAAA,kBAC7D;AAAA,mBACF;AAAA,iBACF;AAAA,YAEJ,GAAG;AAAA,aACL;AAAA,UACA,qBAAC,SAAI,WAAU,wBACb;AAAA,iCAAC,WAAM,WAAU,qCACf;AAAA,kCAAC,WAAM,MAAK,YAAW,SAAS,YAAY,YAAY,UAAU,CAAC,MAAM,eAAe,EAAE,GAAG,aAAa,YAAY,EAAE,OAAO,QAAQ,CAAC,GAAG,WAAU,kBAAiB;AAAA,cAAE;AAAA,eAE1K;AAAA,YACA,qBAAC,WAAM,WAAU,qCACf;AAAA,kCAAC,WAAM,MAAK,YAAW,SAAS,YAAY,UAAU,UAAU,CAAC,MAAM,eAAe,EAAE,GAAG,aAAa,UAAU,EAAE,OAAO,QAAQ,CAAC,GAAG,WAAU,kBAAiB;AAAA,cAAE;AAAA,eAEtK;AAAA,aACF;AAAA,WACF;AAAA,QACA,qBAAC,SAAI,WAAU,cACb;AAAA,8BAAC,YAAO,SAAS,eAAe,UAAU,QAAQ,WAAU,kJACzD,mBAAS,cAAc,QAC1B;AAAA,UACA,oBAAC,YAAO,SAAS,MAAM,eAAe,IAAI,GAAG,WAAU,6FAA4F,oBAAM;AAAA,WAC3J;AAAA,SACF;AAAA,MAGD,WAAW,WAAW,IACrB,oBAAC,SAAI,WAAU,2EAA0E,oGAEzF,IAEA,oBAAC,SAAI,WAAU,qBACb,+BAAC,WAAM,WAAU,kBACf;AAAA,4BAAC,WACC,+BAAC,QAAG,WAAU,wBACZ;AAAA,8BAAC,QAAG,WAAU,mCAAkC,kBAAI;AAAA,UACpD,oBAAC,QAAG,WAAU,mCAAkC,kBAAI;AAAA,UACpD,oBAAC,QAAG,WAAU,mCAAkC,kBAAI;AAAA,UACpD,oBAAC,QAAG,WAAU,mCAAkC,wBAAU;AAAA,UAC1D,oBAAC,QAAG,WAAU,mCAAkC,qBAAO;AAAA,UACvD,oBAAC,QAAG,WAAU,mCAAkC,sBAAQ;AAAA,UACxD,oBAAC,QAAG,WAAU,oCAAmC,qBAAO;AAAA,WAC1D,GACF;AAAA,QACA,oBAAC,WACE,qBAAW,IAAI,CAAC,SACf,qBAAC,QAAiB,WAAU,YAC1B;AAAA,8BAAC,QAAG,WAAU,+BAA+B,eAAK,MAAK;AAAA,UACvD,oBAAC,QAAG,WAAU,aAAa,eAAK,MAAK;AAAA,UACrC,oBAAC,QAAG,WAAU,aAAa,eAAK,eAAc;AAAA,UAC9C,oBAAC,QAAG,WAAU,aACZ,8BAAC,OAAI,SAAS,KAAK,mBAAmB,gBAAgB,SAAS,WAAW,WAAU,gBACjF,eAAK,mBAAmB,gBAAgB,WAAW,OACtD,GACF;AAAA,UACA,oBAAC,QAAG,WAAU,mCAAmC,eAAK,UAAU,GAAG,KAAK,QAAQ,MAAM,aAAa,UAAI;AAAA,UACvG,oBAAC,QAAG,WAAU,aAAa,eAAK,aAAa,QAAQ,MAAK;AAAA,UAC1D,qBAAC,QAAG,WAAU,wBACZ;AAAA,gCAAC,YAAO,SAAS,MAAM,cAAc,IAAI,GAAG,WAAU,6CAA4C,kBAAI;AAAA,YACtG,oBAAC,YAAO,SAAS,MAAM,gBAAgB,KAAK,EAAE,GAAG,WAAU,4CAA2C,oBAAM;AAAA,aAC9G;AAAA,aAdO,KAAK,EAed,CACD,GACH;AAAA,SACF,GACF;AAAA,OAEJ;AAAA,IAID,QAAQ,eAAe,CAAC,SACvB,qBAAC,SAAI,WAAU,aACb;AAAA,0BAAC,SAAI,WAAU,oBACb;AAAA,QAAC;AAAA;AAAA,UACC,SAAS,MAAM,kBAAkB;AAAA,UACjC,WAAU;AAAA,UAET,YAAE,kCAAkC,cAAc;AAAA;AAAA,MACrD,GACF;AAAA,MAEC,mBACC,qBAAC,SAAI,WAAU,2CACb;AAAA,4BAAC,QAAG,WAAU,uBACX,0BAAgB,KAAK,kBAAkB,gBAC1C;AAAA,QACA,qBAAC,SAAI,WAAU,0BACb;AAAA,+BAAC,SACC;AAAA,gCAAC,WAAM,WAAU,kCAAiC,kBAAI;AAAA,YACtD,oBAAC,WAAM,MAAK,QAAO,OAAO,gBAAgB,MAAM,UAAU,CAAC,MAAM,mBAAmB,EAAE,GAAG,iBAAiB,MAAM,EAAE,OAAO,MAAM,CAAC,GAAG,aAAY,8BAA6B,WAAU,gDAA+C;AAAA,aACvO;AAAA,UACA,qBAAC,SACC;AAAA,gCAAC,WAAM,WAAU,kCAAiC,kBAAI;AAAA,YACtD,oBAAC,WAAM,MAAK,QAAO,OAAO,gBAAgB,MAAM,UAAU,CAAC,MAAM,mBAAmB,EAAE,GAAG,iBAAiB,MAAM,EAAE,OAAO,MAAM,CAAC,GAAG,WAAU,gDAA+C;AAAA,aAC9L;AAAA,UACA,qBAAC,SACC;AAAA,gCAAC,WAAM,WAAU,kCAAiC,8BAAgB;AAAA,YAClE,qBAAC,YAAO,OAAO,gBAAgB,iBAAiB,UAAU,CAAC,MAAM,mBAAmB,EAAE,GAAG,iBAAiB,iBAAiB,EAAE,OAAO,MAAM,CAAC,GAAG,WAAU,gDACtJ;AAAA,kCAAC,YAAO,OAAM,SAAQ,mBAAK;AAAA,cAC3B,oBAAC,YAAO,OAAM,UAAS,oBAAM;AAAA,cAC7B,oBAAC,YAAO,OAAM,cAAa,wBAAU;AAAA,eACvC;AAAA,aACF;AAAA,UACA,qBAAC,SACC;AAAA,gCAAC,WAAM,WAAU,kCAAiC,wBAAU;AAAA,YAC5D,oBAAC,SAAI,WAAU,8BACb,8BAAC,WAAM,MAAK,YAAW,SAAS,gBAAgB,UAAU,UAAU,CAAC,MAAM,mBAAmB,EAAE,GAAG,iBAAiB,UAAU,EAAE,OAAO,QAAQ,CAAC,GAAG,WAAU,kBAAiB,GAChL;AAAA,aACF;AAAA,WACF;AAAA,QACA,qBAAC,SACC;AAAA,8BAAC,WAAM,WAAU,kCAAiC,yBAAW;AAAA,UAC7D,oBAAC,WAAM,MAAK,QAAO,OAAO,gBAAgB,eAAe,IAAI,UAAU,CAAC,MAAM,mBAAmB,EAAE,GAAG,iBAAiB,aAAa,EAAE,OAAO,SAAS,KAAK,CAAC,GAAG,WAAU,gDAA+C;AAAA,WAC1N;AAAA,QACC,gBAAgB,SAAS,IACxB,qBAAC,SAAI,WAAU,aACb;AAAA,8BAAC,WAAM,WAAU,6BAA4B,gCAAkB;AAAA,UAC/D,oBAAC,SAAI,WAAU,0BACZ,0BAAgB,IAAI,CAAC,SACpB,qBAAC,SACC;AAAA,iCAAC,WAAM,WAAU,kCACd;AAAA,mBAAK;AAAA,cACL,KAAK,cAAc,oBAAC,UAAK,WAAU,2BAA0B,eAAC;AAAA,eACjE;AAAA,aACE,KAAK,kBAAkB,YAAY,KAAK,kBAAkB,WAAW,KAAK,UAC1E;AAAA,cAAC;AAAA;AAAA,gBACC,OAAO,OAAO,gBAAgB,KAAK,IAAI,KAAK,EAAE;AAAA,gBAC9C,UAAU,CAAC,MAAM,mBAAmB,EAAE,GAAG,iBAAiB,CAAC,KAAK,IAAI,GAAG,EAAE,OAAO,SAAS,KAAK,CAAC;AAAA,gBAC/F,WAAU;AAAA,gBAEV;AAAA,uCAAC,YAAO,OAAM,IAAG;AAAA;AAAA,oBAAQ,KAAK;AAAA,oBAAK;AAAA,qBAAG;AAAA,kBACrC,KAAK,QAAQ,IAAI,CAAC,QACjB,oBAAC,YAAuB,OAAO,IAAI,OAAQ,cAAI,SAAlC,IAAI,KAAoC,CACtD;AAAA;AAAA;AAAA,YACH,IACE,KAAK,kBAAkB,WACzB;AAAA,cAAC;AAAA;AAAA,gBACC,OAAO,OAAO,gBAAgB,KAAK,IAAI,MAAM,WAAY,gBAAgB,KAAK,IAAI,IAAe;AAAA,gBACjG,UAAU,CAAC,MAAM,mBAAmB,EAAE,GAAG,iBAAiB,CAAC,KAAK,IAAI,GAAG,EAAE,CAAC;AAAA;AAAA,YAC5E,IACE,KAAK,kBAAkB,YACzB,oBAAC,SAAI,WAAU,QACb,+BAAC,WAAM,WAAU,qCACf;AAAA;AAAA,gBAAC;AAAA;AAAA,kBACC,MAAK;AAAA,kBACL,SAAS,CAAC,CAAC,gBAAgB,KAAK,IAAI;AAAA,kBACpC,UAAU,CAAC,MAAM,mBAAmB,EAAE,GAAG,iBAAiB,CAAC,KAAK,IAAI,GAAG,EAAE,OAAO,QAAQ,CAAC;AAAA,kBACzF,WAAU;AAAA;AAAA,cACZ;AAAA,cACC,KAAK;AAAA,eACR,GACF,IAEA;AAAA,cAAC;AAAA;AAAA,gBACC,MAAK;AAAA,gBACL,OAAO,OAAO,gBAAgB,KAAK,IAAI,KAAK,EAAE;AAAA,gBAC9C,UAAU,CAAC,MAAM,mBAAmB,EAAE,GAAG,iBAAiB,CAAC,KAAK,IAAI,GAAG,EAAE,OAAO,SAAS,KAAK,CAAC;AAAA,gBAC/F,WAAU;AAAA,gBACV,aAAa,KAAK,YAAY;AAAA;AAAA,YAChC;AAAA,YAED,KAAK,YAAY,oBAAC,OAAE,WAAU,wCAAwC,eAAK,UAAS;AAAA,eA1C7E,KAAK,IA2Cf,CACD,GACH;AAAA,WACF,IAEA,oBAAC,SAAI,WAAU,sCAAqC,mGAEpD;AAAA,QAEF,qBAAC,SAAI,WAAU,cACb;AAAA,8BAAC,YAAO,SAAS,cAAc,UAAU,QAAQ,WAAU,kJACxD,mBAAS,cAAc,QAC1B;AAAA,UACA,oBAAC,YAAO,SAAS,MAAM,mBAAmB,IAAI,GAAG,WAAU,6FAA4F,oBAAM;AAAA,WAC/J;AAAA,SACF;AAAA,MAGD,UAAU,WAAW,IACpB,oBAAC,SAAI,WAAU,2EAA0E,gJAEzF,IAEA,oBAAC,SAAI,WAAU,qBACb,+BAAC,WAAM,WAAU,kBACf;AAAA,4BAAC,WACC,+BAAC,QAAG,WAAU,wBACZ;AAAA,8BAAC,QAAG,WAAU,mCAAkC,kBAAI;AAAA,UACpD,oBAAC,QAAG,WAAU,mCAAkC,kBAAI;AAAA,UACpD,oBAAC,QAAG,WAAU,mCAAkC,oBAAM;AAAA,UACtD,oBAAC,QAAG,WAAU,mCAAkC,gCAAkB;AAAA,UAClE,oBAAC,QAAG,WAAU,oCAAmC,qBAAO;AAAA,WAC1D,GACF;AAAA,QACA,oBAAC,WACE,oBAAU,IAAI,CAAC,MACd;AAAA,UAAC;AAAA;AAAA,YAEC,SAAS,MAAM,OAAO,KAAK,0BAA0B,EAAE,EAAE,EAAE;AAAA,YAC3D,WAAU;AAAA,YAEV;AAAA,kCAAC,QAAG,WAAU,+BAA+B,YAAE,MAAK;AAAA,cACpD,oBAAC,QAAG,WAAU,yBAAyB,YAAE,MAAK;AAAA,cAC9C,oBAAC,QAAG,WAAU,aACZ,8BAAC,OAAI,SAAS,mBAAmB,EAAE,eAAkC,KAAK,WAAW,KAAG,MACrF,4BAAkB,EAAE,eAAe,GACtC,GACF;AAAA,cACA,oBAAC,QAAG,WAAU,2CACX,iBAAO,KAAK,EAAE,gBAAgB,EAAE,SAAS,IACtC,OAAO,QAAQ,EAAE,gBAAgB,EAAE,IAAI,CAAC,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,KAAK,IAAI,IACzE,UACN;AAAA,cACA,qBAAC,QAAG,WAAU,wBACZ;AAAA,oCAAC,YAAO,SAAS,CAAC,MAAM;AAAE,oBAAE,gBAAgB;AAAG,oCAAkB,CAAC;AAAA,gBAAE,GAAG,WAAU,6CAA4C,kBAAI;AAAA,gBACjI,oBAAC,YAAO,SAAS,CAAC,MAAM;AAAE,oBAAE,gBAAgB;AAAG,iCAAe,EAAE,EAAE;AAAA,gBAAE,GAAG,WAAU,4CAA2C,oBAAM;AAAA,iBACpI;AAAA;AAAA;AAAA,UAnBK,EAAE;AAAA,QAoBT,CACD,GACH;AAAA,SACF,GACF;AAAA,OAEJ;AAAA,IAID,QAAQ,mBAAmB,CAAC,SAC3B,qBAAC,SAAI,WAAU,aACb;AAAA,0BAAC,SAAI,WAAU,oBACb;AAAA,QAAC;AAAA;AAAA,UACC,SAAS,MAAM,aAAa;AAAA,UAC5B,WAAU;AAAA,UAET,YAAE,sCAAsC,kBAAkB;AAAA;AAAA,MAC7D,GACF;AAAA,MAEC,cACC,qBAAC,SAAI,WAAU,2CACb;AAAA,4BAAC,QAAG,WAAU,uBACX,qBAAW,KAAK,sBAAsB,oBACzC;AAAA,QACA,qBAAC,SAAI,WAAU,0BACb;AAAA,+BAAC,SACC;AAAA,gCAAC,WAAM,WAAU,kCAAiC,kBAAI;AAAA,YACtD,qBAAC,YAAO,OAAO,WAAW,kBAAkB,UAAU,CAAC,MAAM,cAAc,EAAE,GAAG,YAAY,kBAAkB,EAAE,OAAO,MAAM,CAAC,GAAG,WAAU,gDACzI;AAAA,kCAAC,YAAO,OAAM,gBAAe,4BAAc;AAAA,cAC3C,oBAAC,YAAO,OAAM,YAAW,sBAAQ;AAAA,cACjC,oBAAC,YAAO,OAAM,YAAW,sBAAQ;AAAA,eACnC;AAAA,aACF;AAAA,UACA,qBAAC,SACC;AAAA,gCAAC,WAAM,WAAU,kCAAiC,kCAAoB;AAAA,YACtE,qBAAC,YAAO,OAAO,WAAW,cAAc,UAAU,CAAC,MAAM,cAAc,EAAE,GAAG,YAAY,cAAc,EAAE,OAAO,MAAM,CAAC,GAAG,WAAU,gDACjI;AAAA,kCAAC,YAAO,OAAM,IAAG,uBAAS;AAAA,cACzB,SAAS,OAAO,CAAC,MAAM,EAAE,OAAO,MAAM,EAAE,IAAI,CAAC,MAC5C,qBAAC,YAAkB,OAAO,EAAE,IAAK;AAAA,kBAAE;AAAA,gBAAK;AAAA,gBAAG,EAAE;AAAA,gBAAK;AAAA,mBAArC,EAAE,EAAoC,CACpD;AAAA,eACH;AAAA,aACF;AAAA,UACA,qBAAC,SAAI,WAAU,0BACb;AAAA,iCAAC,SACC;AAAA,kCAAC,WAAM,WAAU,kCAAiC,iBAAG;AAAA,cACrD;AAAA,gBAAC;AAAA;AAAA,kBACC,SAAO;AAAA,kBACP,KAAK;AAAA,kBACL,OAAO,WAAW;AAAA,kBAClB,UAAU,CAAC,MAAM,cAAc,EAAE,GAAG,YAAY,gBAAgB,KAAK,EAAE,CAAC;AAAA;AAAA,cAC1E;AAAA,eACF;AAAA,YACA,qBAAC,SACC;AAAA,kCAAC,WAAM,WAAU,kCAAiC,iBAAG;AAAA,cACrD;AAAA,gBAAC;AAAA;AAAA,kBACC,SAAO;AAAA,kBACP,KAAK;AAAA,kBACL,OAAO,WAAW;AAAA,kBAClB,UAAU,CAAC,MAAM,cAAc,EAAE,GAAG,YAAY,gBAAgB,EAAE,CAAC;AAAA,kBACnE,aAAY;AAAA;AAAA,cACd;AAAA,eACF;AAAA,aACF;AAAA,WACF;AAAA,QACA,qBAAC,SACC;AAAA,8BAAC,WAAM,WAAU,kCAAiC,8BAAgB;AAAA,UAClE,oBAAC,cAAS,OAAO,eAAe,UAAU,CAAC,MAAM,iBAAiB,EAAE,OAAO,KAAK,GAAG,MAAM,GAAG,WAAU,0DAAyD,aAAY,yEAAwE;AAAA,WACrP;AAAA,QACA,qBAAC,SAAI,WAAU,cACb;AAAA,8BAAC,YAAO,SAAS,kBAAkB,UAAU,QAAQ,WAAU,kJAC5D,mBAAS,cAAc,QAC1B;AAAA,UACA,oBAAC,YAAO,SAAS,MAAM,cAAc,IAAI,GAAG,WAAU,6FAA4F,oBAAM;AAAA,WAC1J;AAAA,SACF;AAAA,MAGD,cAAc,WAAW,IACxB,oBAAC,SAAI,WAAU,2EAA0E,4HAEzF,IAEA,oBAAC,SAAI,WAAU,qBACb,+BAAC,WAAM,WAAU,kBACf;AAAA,4BAAC,WACC,+BAAC,QAAG,WAAU,wBACZ;AAAA,8BAAC,QAAG,WAAU,mCAAkC,kBAAI;AAAA,UACpD,oBAAC,QAAG,WAAU,mCAAkC,oBAAM;AAAA,UACtD,oBAAC,QAAG,WAAU,mCAAkC,oBAAM;AAAA,UACtD,oBAAC,QAAG,WAAU,mCAAkC,yBAAW;AAAA,UAC3D,oBAAC,QAAG,WAAU,mCAAkC,uBAAS;AAAA,UACzD,oBAAC,QAAG,WAAU,oCAAmC,qBAAO;AAAA,WAC1D,GACF;AAAA,QACA,oBAAC,WACE,wBAAc,IAAI,CAAC,QAClB,qBAAC,QAAgB,WAAU,YACzB;AAAA,8BAAC,QAAG,WAAU,aACZ;AAAA,YAAC;AAAA;AAAA,cACC,SACE,IAAI,qBAAqB,iBAAiB,UAC1C,IAAI,qBAAqB,aAAa,SACtC;AAAA,cAGD,cAAI;AAAA;AAAA,UACP,GACF;AAAA,UACA,oBAAC,QAAG,WAAU,qBAAqB,sBAAY,IAAI,YAAY,GAAE;AAAA,UACjE,oBAAC,QAAG,WAAU,qBAAqB,sBAAY,IAAI,YAAY,GAAE;AAAA,UACjE,qBAAC,QAAG,WAAU,mCAAmC;AAAA,gBAAI;AAAA,YAAe;AAAA,YAAG,IAAI,kBAAkB;AAAA,aAAI;AAAA,UACjG,oBAAC,QAAG,WAAU,2CAA2C,cAAI,YAAY,KAAK,UAAU,IAAI,SAAS,IAAI,UAAI;AAAA,UAC7G,qBAAC,QAAG,WAAU,wBACZ;AAAA,gCAAC,YAAO,SAAS,MAAM,aAAa,GAAG,GAAG,WAAU,6CAA4C,kBAAI;AAAA,YACpG,oBAAC,YAAO,SAAS,MAAM,mBAAmB,IAAI,EAAE,GAAG,WAAU,4CAA2C,oBAAM;AAAA,aAChH;AAAA,aAnBO,IAAI,EAoBb,CACD,GACH;AAAA,SACF,GACF;AAAA,OAEJ;AAAA,IAID,QAAQ,WAAW,CAAC,SAAS,KAAK,aAAa,YAC9C,qBAAC,SAAI,WAAU,aACb;AAAA,0BAAC,SAAI,WAAU,oBACb;AAAA,QAAC;AAAA;AAAA,UACC,SAAS,MAAM,eAAe,EAAE,GAAG,WAAW,CAAC;AAAA,UAC/C,WAAU;AAAA,UACX;AAAA;AAAA,MAED,GACF;AAAA,MAEC,eACC,qBAAC,SAAI,WAAU,2CACb;AAAA,4BAAC,QAAG,WAAU,yBAAyB,sBAAY,KAAK,qBAAqB,mBAAkB;AAAA,QAC/F,qBAAC,SAAI,WAAU,0BACb;AAAA,+BAAC,SACC;AAAA,gCAAC,WAAM,WAAU,kCAAiC,kBAAI;AAAA,YACtD;AAAA,cAAC;AAAA;AAAA,gBACC,MAAK;AAAA,gBACL,OAAO,YAAY;AAAA,gBACnB,UAAU,CAAC,MAAM,eAAe,EAAE,GAAG,aAAa,MAAM,EAAE,OAAO,MAAM,CAAC;AAAA,gBACxE,aAAY;AAAA,gBACZ,WAAU;AAAA;AAAA,YACZ;AAAA,aACF;AAAA,UACA,qBAAC,SACC;AAAA,gCAAC,WAAM,WAAU,kCAAiC,6BAAe;AAAA,YACjE;AAAA,cAAC;AAAA;AAAA,gBACC,MAAK;AAAA,gBACL,OAAO,YAAY;AAAA,gBACnB,UAAU,CAAC,MAAM,eAAe,EAAE,GAAG,aAAa,gBAAgB,EAAE,OAAO,MAAM,CAAC;AAAA,gBAClF,aAAY;AAAA,gBACZ,WAAU;AAAA;AAAA,YACZ;AAAA,aACF;AAAA,UACA,qBAAC,SACC;AAAA,gCAAC,WAAM,WAAU,kCAAiC,kCAAoB;AAAA,YACtE;AAAA,cAAC;AAAA;AAAA,gBACC,OAAO,YAAY;AAAA,gBACnB,UAAU,CAAC,MAAM,eAAe,EAAE,GAAG,aAAa,cAAc,EAAE,OAAO,MAAM,CAAC;AAAA,gBAChF,WAAU;AAAA,gBAEV;AAAA,sCAAC,YAAO,OAAM,IAAG,gDAAwB;AAAA,kBACxC,SAAS,OAAO,CAAC,MAAM,EAAE,OAAO,MAAM,EAAE,IAAI,CAAC,MAC5C,qBAAC,YAAkB,OAAO,EAAE,IAAK;AAAA,sBAAE;AAAA,oBAAK;AAAA,oBAAG,EAAE;AAAA,oBAAK;AAAA,uBAArC,EAAE,EAAoC,CACpD;AAAA;AAAA;AAAA,YACH;AAAA,aACF;AAAA,UACA,qBAAC,SACC;AAAA,gCAAC,WAAM,WAAU,kCAAiC,wBAAU;AAAA,YAC5D;AAAA,cAAC;AAAA;AAAA,gBACC,SAAO;AAAA,gBACP,OAAO,YAAY;AAAA,gBACnB,UAAU,CAAC,MAAM,eAAe,EAAE,GAAG,aAAa,WAAW,KAAK,EAAE,CAAC;AAAA;AAAA,YACvE;AAAA,aACF;AAAA,UACA,qBAAC,SACC;AAAA,gCAAC,WAAM,WAAU,kCAAiC,6BAAe;AAAA,YACjE;AAAA,cAAC;AAAA;AAAA,gBACC,SAAO;AAAA,gBACP,KAAK;AAAA,gBACL,OAAO,YAAY;AAAA,gBACnB,UAAU,CAAC,MAAM,eAAe,EAAE,GAAG,aAAa,gBAAgB,KAAK,EAAE,CAAC;AAAA;AAAA,YAC5E;AAAA,aACF;AAAA,UACA,qBAAC,SACC;AAAA,gCAAC,WAAM,WAAU,kCAAiC,6BAAe;AAAA,YACjE;AAAA,cAAC;AAAA;AAAA,gBACC,SAAO;AAAA,gBACP,KAAK;AAAA,gBACL,aAAY;AAAA,gBACZ,OAAO,YAAY;AAAA,gBACnB,UAAU,CAAC,MAAM,eAAe,EAAE,GAAG,aAAa,gBAAgB,EAAE,CAAC;AAAA;AAAA,YACvE;AAAA,aACF;AAAA,WACF;AAAA,QACA,qBAAC,SACC;AAAA,8BAAC,WAAM,WAAU,kCAAiC,yBAAW;AAAA,UAC7D;AAAA,YAAC;AAAA;AAAA,cACC,OAAO,YAAY,eAAe;AAAA,cAClC,UAAU,CAAC,MAAM,eAAe,EAAE,GAAG,aAAa,aAAa,EAAE,OAAO,MAAM,CAAC;AAAA,cAC/E,MAAM;AAAA,cACN,WAAU;AAAA;AAAA,UACZ;AAAA,WACF;AAAA,QACA,qBAAC,SAAI,WAAU,cACb;AAAA;AAAA,YAAC;AAAA;AAAA,cACC,SAAS,YAAY;AACnB,0BAAU,IAAI;AACd,yBAAS,IAAI;AACb,oBAAI;AACF,wBAAM,SAAS,CAAC,CAAC,YAAY;AAC7B,wBAAM,UAAU,SACZ,EAAE,IAAI,YAAY,IAAI,GAAG,aAAa,aAAa,YAAY,eAAe,KAAK,IACnF,EAAE,QAAQ,GAAG,aAAa,aAAa,YAAY,eAAe,KAAK;AAC3E,wBAAM,MAAM,MAAM,MAAM,yBAAyB;AAAA,oBAC/C,QAAQ,SAAS,QAAQ;AAAA,oBACzB,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,oBAC9C,MAAM,KAAK,UAAU,OAAO;AAAA,kBAC9B,CAAC;AACD,sBAAI,CAAC,IAAI,IAAI;AACX,0BAAM,IAAI,MAAM,IAAI,KAAK;AACzB,6BAAS,EAAE,SAAS,qBAAqB;AACzC;AAAA,kBACF;AACA,iCAAe,IAAI;AACnB,wBAAM,WAAW,MAAM,MAAM,gCAAgC,MAAM,EAAE;AACrE,sBAAI,SAAS,IAAI;AACf,0BAAM,IAAI,MAAM,SAAS,KAAK;AAC9B,mCAAe,EAAE,SAAS,CAAC,CAAC;AAAA,kBAC9B;AAAA,gBACF,QAAQ;AACN,2BAAS,qBAAqB;AAAA,gBAChC,UAAE;AACA,4BAAU,KAAK;AAAA,gBACjB;AAAA,cACF;AAAA,cACA,UAAU,UAAU,CAAC,YAAY,QAAQ,CAAC,YAAY,kBAAkB,CAAC,YAAY;AAAA,cACrF,WAAU;AAAA,cAET,mBAAS,cAAe,YAAY,KAAK,WAAW;AAAA;AAAA,UACvD;AAAA,UACA;AAAA,YAAC;AAAA;AAAA,cACC,SAAS,MAAM,eAAe,IAAI;AAAA,cAClC,WAAU;AAAA,cACX;AAAA;AAAA,UAED;AAAA,WACF;AAAA,SACF;AAAA,MAGD,YAAY,WAAW,KAAK,CAAC,cAC5B,oBAAC,SAAI,WAAU,2EAA0E,kHAEzF,IACE,YAAY,SAAS,KACvB,oBAAC,SAAI,WAAU,qCACb,+BAAC,WAAM,WAAU,kBACf;AAAA,4BAAC,WACC,+BAAC,QAAG,WAAU,wBACZ;AAAA,8BAAC,QAAG,WAAU,mCAAkC,kBAAI;AAAA,UACpD,oBAAC,QAAG,WAAU,mCAAkC,mBAAK;AAAA,UACrD,oBAAC,QAAG,WAAU,mCAAkC,yBAAW;AAAA,UAC3D,oBAAC,QAAG,WAAU,mCAAkC,yBAAW;AAAA,UAC3D,oBAAC,QAAG,WAAU,mCAAkC,mBAAK;AAAA,UACrD,oBAAC,QAAG,WAAU,oCAAmC,qBAAO;AAAA,WAC1D,GACF;AAAA,QACA,oBAAC,WACE,sBAAY,IAAI,CAAC,SAChB,qBAAC,QAAiB,WAAU,YAC1B;AAAA,8BAAC,QAAG,WAAU,yBAAyB,eAAK,MAAK;AAAA,UACjD,oBAAC,QAAG,WAAU,aACZ,8BAAC,OAAI,SAAQ,QAAQ,eAAK,gBAAe,GAC3C;AAAA,UACA,oBAAC,QAAG,WAAU,qBACX,eAAK,aACJ,qBAAC,UACE;AAAA,iBAAK,WAAW;AAAA,YAChB,KAAK,WAAW,aAAa,YAC5B,oBAAC,OAAI,SAAQ,SAAQ,WAAU,2BAA0B,oBAAM;AAAA,aAEnE,IAEA,oBAAC,UAAK,WAAU,yBAAwB,qBAAO,GAEnD;AAAA,UACA,qBAAC,QAAG,WAAU,mCAAmC;AAAA,iBAAK;AAAA,YAAe;AAAA,YAAG,KAAK,kBAAkB;AAAA,aAAI;AAAA,UACnG,oBAAC,QAAG,WAAU,mCAAmC,eAAK,WAAU;AAAA,UAChE,qBAAC,QAAG,WAAU,wBACZ;AAAA;AAAA,cAAC;AAAA;AAAA,gBACC,SAAS,MAAM,eAAe;AAAA,kBAC5B,IAAI,KAAK;AAAA,kBACT,cAAc,KAAK;AAAA,kBACnB,gBAAgB,KAAK;AAAA,kBACrB,MAAM,KAAK;AAAA,kBACX,aAAa,KAAK,eAAe;AAAA,kBACjC,gBAAgB,KAAK;AAAA,kBACrB,gBAAgB,KAAK;AAAA,kBACrB,WAAW,KAAK;AAAA,gBAClB,CAAC;AAAA,gBACD,WAAU;AAAA,gBACX;AAAA;AAAA,YAED;AAAA,YACA;AAAA,cAAC;AAAA;AAAA,gBACC,SAAS,YAAY;AACnB,sBAAI,CAAC,QAAQ,0BAA0B,EAAG;AAC1C,sBAAI;AACF,0BAAM,MAAM,MAAM,MAAM,yBAAyB;AAAA,sBAC/C,QAAQ;AAAA,sBACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,sBAC9C,MAAM,KAAK,UAAU,EAAE,IAAI,KAAK,GAAG,CAAC;AAAA,oBACtC,CAAC;AACD,wBAAI,IAAI,IAAI;AACV,qCAAe,CAAC,SAAS,KAAK,OAAO,CAAC,MAAM,EAAE,OAAO,KAAK,EAAE,CAAC;AAAA,oBAC/D,OAAO;AACL,4BAAM,IAAI,MAAM,IAAI,KAAK;AACzB,+BAAS,EAAE,SAAS,uBAAuB;AAAA,oBAC7C;AAAA,kBACF,QAAQ;AACN,6BAAS,uBAAuB;AAAA,kBAClC;AAAA,gBACF;AAAA,gBACA,WAAU;AAAA,gBACX;AAAA;AAAA,YAED;AAAA,aACF;AAAA,aA1DO,KAAK,EA2Dd,CACD,GACH;AAAA,SACF,GACF;AAAA,OAEJ;AAAA,KAEJ;AAEJ;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|