@aglyn/plugins-commerce 1.0.0-beta.278 → 1.0.0-beta.282

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.
Files changed (212) hide show
  1. package/package.json +17 -14
  2. package/src/lib/components/commerce-console-page.js +33 -1
  3. package/src/lib/components/commerce-console-page.js.map +1 -1
  4. package/src/lib/components/console/payments-settings-card.component.js +1 -1
  5. package/src/lib/components/console/payments-settings-card.component.js.map +1 -1
  6. package/src/lib/components/console/pos/pos-hardware-api.d.ts +122 -0
  7. package/src/lib/components/console/pos/pos-hardware-api.js +90 -0
  8. package/src/lib/components/console/pos/pos-hardware-api.js.map +1 -0
  9. package/src/lib/components/console/pos/pos-reader-splash-api.d.ts +58 -0
  10. package/src/lib/components/console/pos/pos-reader-splash-api.js +101 -0
  11. package/src/lib/components/console/pos/pos-reader-splash-api.js.map +1 -0
  12. package/src/lib/components/console/pos-devices-card.component.js +5 -0
  13. package/src/lib/components/console/pos-devices-card.component.js.map +1 -1
  14. package/src/lib/components/console/pos-hardware-card.component.d.ts +26 -0
  15. package/src/lib/components/console/pos-hardware-card.component.js +456 -0
  16. package/src/lib/components/console/pos-hardware-card.component.js.map +1 -0
  17. package/src/lib/components/console/pos-hardware-orders-staff-page.component.d.ts +14 -0
  18. package/src/lib/components/console/pos-hardware-orders-staff-page.component.js +519 -0
  19. package/src/lib/components/console/pos-hardware-orders-staff-page.component.js.map +1 -0
  20. package/src/lib/components/console/pos-ops/pos-check-in-dialog.component.d.ts +27 -0
  21. package/src/lib/components/console/pos-ops/pos-check-in-dialog.component.js +444 -0
  22. package/src/lib/components/console/pos-ops/pos-check-in-dialog.component.js.map +1 -0
  23. package/src/lib/components/console/pos-ops/pos-check-in-zone.component.d.ts +9 -0
  24. package/src/lib/components/console/pos-ops/pos-check-in-zone.component.js +37 -0
  25. package/src/lib/components/console/pos-ops/pos-check-in-zone.component.js.map +1 -0
  26. package/src/lib/components/console/pos-ops/pos-check-ins-card.component.d.ts +24 -0
  27. package/src/lib/components/console/pos-ops/pos-check-ins-card.component.js +346 -0
  28. package/src/lib/components/console/pos-ops/pos-check-ins-card.component.js.map +1 -0
  29. package/src/lib/components/console/pos-ops/pos-customer-lookup.component.d.ts +5 -1
  30. package/src/lib/components/console/pos-ops/pos-customer-lookup.component.js +83 -4
  31. package/src/lib/components/console/pos-ops/pos-customer-lookup.component.js.map +1 -1
  32. package/src/lib/components/console/pos-ops/pos-day-totals-card.component.d.ts +35 -0
  33. package/src/lib/components/console/pos-ops/pos-day-totals-card.component.js +546 -0
  34. package/src/lib/components/console/pos-ops/pos-day-totals-card.component.js.map +1 -0
  35. package/src/lib/components/console/pos-ops/pos-operations-bar.component.d.ts +2 -1
  36. package/src/lib/components/console/pos-ops/pos-operations-bar.component.js +20 -1
  37. package/src/lib/components/console/pos-ops/pos-operations-bar.component.js.map +1 -1
  38. package/src/lib/components/console/pos-ops/pos-ops-api.d.ts +1 -1
  39. package/src/lib/components/console/pos-ops/pos-ops-api.js.map +1 -1
  40. package/src/lib/components/console/pos-page.component.js +6 -3
  41. package/src/lib/components/console/pos-page.component.js.map +1 -1
  42. package/src/lib/components/console/pos-reader-splash-setting.component.d.ts +22 -0
  43. package/src/lib/components/console/pos-reader-splash-setting.component.js +275 -0
  44. package/src/lib/components/console/pos-reader-splash-setting.component.js.map +1 -0
  45. package/src/lib/components/console/pos-reader-splash-staff-page.component.d.ts +14 -0
  46. package/src/lib/components/console/pos-reader-splash-staff-page.component.js +301 -0
  47. package/src/lib/components/console/pos-reader-splash-staff-page.component.js.map +1 -0
  48. package/src/lib/components/console/pos-zones.d.ts +37 -3
  49. package/src/lib/components/console/pos-zones.js +11 -1
  50. package/src/lib/components/console/pos-zones.js.map +1 -1
  51. package/src/lib/components/console/product-check-in-fields.component.d.ts +20 -0
  52. package/src/lib/components/console/product-check-in-fields.component.js +172 -0
  53. package/src/lib/components/console/product-check-in-fields.component.js.map +1 -0
  54. package/src/lib/components/console/product-editor-dialog.component.js +48 -9
  55. package/src/lib/components/console/product-editor-dialog.component.js.map +1 -1
  56. package/src/lib/components/console/product-register-fields.component.d.ts +12 -0
  57. package/src/lib/components/console/product-register-fields.component.js +39 -1
  58. package/src/lib/components/console/product-register-fields.component.js.map +1 -1
  59. package/src/lib/components/console/products-hub-card.component.js +21 -6
  60. package/src/lib/components/console/products-hub-card.component.js.map +1 -1
  61. package/src/lib/components/console/reservations-card.component.js +239 -70
  62. package/src/lib/components/console/reservations-card.component.js.map +1 -1
  63. package/src/lib/components/reservation-widget.js +16 -0
  64. package/src/lib/components/reservation-widget.js.map +1 -1
  65. package/src/lib/constants/operator-alerts.d.ts +6 -0
  66. package/src/lib/constants/operator-alerts.js +20 -1
  67. package/src/lib/constants/operator-alerts.js.map +1 -1
  68. package/src/lib/declarations.console-server.js +7 -0
  69. package/src/lib/declarations.console-server.js.map +1 -1
  70. package/src/lib/declarations.d.ts +26 -0
  71. package/src/lib/declarations.js +34 -0
  72. package/src/lib/declarations.js.map +1 -0
  73. package/src/lib/model/commerce-check-in-product.d.ts +37 -0
  74. package/src/lib/model/commerce-check-in-product.js +49 -0
  75. package/src/lib/model/commerce-check-in-product.js.map +1 -0
  76. package/src/lib/model/commerce-check-in.d.ts +187 -0
  77. package/src/lib/model/commerce-check-in.js +468 -0
  78. package/src/lib/model/commerce-check-in.js.map +1 -0
  79. package/src/lib/model/commerce-pos-day-report.d.ts +209 -0
  80. package/src/lib/model/commerce-pos-day-report.js +572 -0
  81. package/src/lib/model/commerce-pos-day-report.js.map +1 -0
  82. package/src/lib/model/commerce-pos-offline.d.ts +65 -3
  83. package/src/lib/model/commerce-pos-offline.js +104 -7
  84. package/src/lib/model/commerce-pos-offline.js.map +1 -1
  85. package/src/lib/model/commerce-pos-ops.d.ts +3 -0
  86. package/src/lib/model/commerce-pos-ops.js +1 -0
  87. package/src/lib/model/commerce-pos-ops.js.map +1 -1
  88. package/src/lib/model/commerce-pos.d.ts +43 -3
  89. package/src/lib/model/commerce-pos.js +73 -5
  90. package/src/lib/model/commerce-pos.js.map +1 -1
  91. package/src/lib/model/commerce-reservations.d.ts +73 -7
  92. package/src/lib/model/commerce-reservations.js +90 -10
  93. package/src/lib/model/commerce-reservations.js.map +1 -1
  94. package/src/lib/model/commerce.d.ts +40 -0
  95. package/src/lib/model/commerce.js +22 -4
  96. package/src/lib/model/commerce.js.map +1 -1
  97. package/src/lib/model/index.d.ts +1 -0
  98. package/src/lib/model/index.js +1 -0
  99. package/src/lib/model/index.js.map +1 -1
  100. package/src/lib/model/plugin-permissions.d.ts +1 -1
  101. package/src/lib/model/plugin-permissions.js +2 -1
  102. package/src/lib/model/plugin-permissions.js.map +1 -1
  103. package/src/lib/model/pos-hardware.d.ts +288 -0
  104. package/src/lib/model/pos-hardware.js +499 -0
  105. package/src/lib/model/pos-hardware.js.map +1 -0
  106. package/src/lib/model/pos-offline-card-limits.d.ts +20 -0
  107. package/src/lib/model/pos-offline-card-limits.js +28 -0
  108. package/src/lib/model/pos-offline-card-limits.js.map +1 -0
  109. package/src/lib/model/pos-reader-splash.d.ts +114 -0
  110. package/src/lib/model/pos-reader-splash.js +141 -0
  111. package/src/lib/model/pos-reader-splash.js.map +1 -0
  112. package/src/lib/model/product-write.d.ts +6 -0
  113. package/src/lib/plugin-config.d.ts +10 -0
  114. package/src/lib/plugin-config.js +40 -0
  115. package/src/lib/plugin-config.js.map +1 -1
  116. package/src/lib/plugin.js +28 -0
  117. package/src/lib/plugin.js.map +1 -1
  118. package/src/lib/server/cart-checkout.js +3 -1
  119. package/src/lib/server/cart-checkout.js.map +1 -1
  120. package/src/lib/server/cart.js +12 -1
  121. package/src/lib/server/cart.js.map +1 -1
  122. package/src/lib/server/catalog.js +49 -12
  123. package/src/lib/server/catalog.js.map +1 -1
  124. package/src/lib/server/checkout-extras.js +1 -1
  125. package/src/lib/server/checkout-extras.js.map +1 -1
  126. package/src/lib/server/checkout.js +7 -0
  127. package/src/lib/server/checkout.js.map +1 -1
  128. package/src/lib/server/person-eraser.d.ts +8 -1
  129. package/src/lib/server/person-eraser.js +23 -1
  130. package/src/lib/server/person-eraser.js.map +1 -1
  131. package/src/lib/server/pos-check-in.d.ts +49 -0
  132. package/src/lib/server/pos-check-in.js +652 -0
  133. package/src/lib/server/pos-check-in.js.map +1 -0
  134. package/src/lib/server/pos-day-report.d.ts +46 -0
  135. package/src/lib/server/pos-day-report.js +299 -0
  136. package/src/lib/server/pos-day-report.js.map +1 -0
  137. package/src/lib/server/pos-hardware-admin.d.ts +50 -0
  138. package/src/lib/server/pos-hardware-admin.js +366 -0
  139. package/src/lib/server/pos-hardware-admin.js.map +1 -0
  140. package/src/lib/server/pos-hardware-notify.d.ts +27 -0
  141. package/src/lib/server/pos-hardware-notify.js +142 -0
  142. package/src/lib/server/pos-hardware-notify.js.map +1 -0
  143. package/src/lib/server/pos-hardware-user-eraser.d.ts +26 -0
  144. package/src/lib/server/pos-hardware-user-eraser.js +67 -0
  145. package/src/lib/server/pos-hardware-user-eraser.js.map +1 -0
  146. package/src/lib/server/pos-hardware-webhook.d.ts +31 -0
  147. package/src/lib/server/pos-hardware-webhook.js +176 -0
  148. package/src/lib/server/pos-hardware-webhook.js.map +1 -0
  149. package/src/lib/server/pos-hardware.d.ts +58 -0
  150. package/src/lib/server/pos-hardware.js +234 -0
  151. package/src/lib/server/pos-hardware.js.map +1 -0
  152. package/src/lib/server/pos-offline-card-reconcile.d.ts +38 -0
  153. package/src/lib/server/pos-offline-card-reconcile.js +58 -0
  154. package/src/lib/server/pos-offline-card-reconcile.js.map +1 -0
  155. package/src/lib/server/pos-offline-sync.d.ts +32 -0
  156. package/src/lib/server/pos-offline-sync.js +191 -15
  157. package/src/lib/server/pos-offline-sync.js.map +1 -1
  158. package/src/lib/server/pos-ops-routes.d.ts +4 -2
  159. package/src/lib/server/pos-ops-routes.js +14 -2
  160. package/src/lib/server/pos-ops-routes.js.map +1 -1
  161. package/src/lib/server/pos-order.js +39 -51
  162. package/src/lib/server/pos-order.js.map +1 -1
  163. package/src/lib/server/pos-payment.js +8 -4
  164. package/src/lib/server/pos-payment.js.map +1 -1
  165. package/src/lib/server/pos-reader-splash-admin.d.ts +36 -0
  166. package/src/lib/server/pos-reader-splash-admin.js +295 -0
  167. package/src/lib/server/pos-reader-splash-admin.js.map +1 -0
  168. package/src/lib/server/pos-reader-splash-render.d.ts +40 -0
  169. package/src/lib/server/pos-reader-splash-render.js +138 -0
  170. package/src/lib/server/pos-reader-splash-render.js.map +1 -0
  171. package/src/lib/server/pos-reader-splash-server.d.ts +32 -0
  172. package/src/lib/server/pos-reader-splash-server.js +32 -0
  173. package/src/lib/server/pos-reader-splash-server.js.map +1 -0
  174. package/src/lib/server/pos-reader-splash.d.ts +105 -0
  175. package/src/lib/server/pos-reader-splash.js +548 -0
  176. package/src/lib/server/pos-reader-splash.js.map +1 -0
  177. package/src/lib/server/pos-sale.d.ts +2 -1
  178. package/src/lib/server/pos-sale.js +3 -1
  179. package/src/lib/server/pos-sale.js.map +1 -1
  180. package/src/lib/server/pos-terminal.d.ts +67 -4
  181. package/src/lib/server/pos-terminal.js +239 -32
  182. package/src/lib/server/pos-terminal.js.map +1 -1
  183. package/src/lib/server/process-restock.js +4 -0
  184. package/src/lib/server/process-restock.js.map +1 -1
  185. package/src/lib/server/product-card.js +2 -2
  186. package/src/lib/server/product-card.js.map +1 -1
  187. package/src/lib/server/product-catalog.d.ts +2 -0
  188. package/src/lib/server/product-catalog.js +11 -4
  189. package/src/lib/server/product-catalog.js.map +1 -1
  190. package/src/lib/server/product.js +3 -1
  191. package/src/lib/server/product.js.map +1 -1
  192. package/src/lib/server/related.js +8 -1
  193. package/src/lib/server/related.js.map +1 -1
  194. package/src/lib/server/reservation-availability-query.d.ts +35 -0
  195. package/src/lib/server/reservation-availability-query.js +34 -0
  196. package/src/lib/server/reservation-availability-query.js.map +1 -0
  197. package/src/lib/server/reservation-availability.d.ts +21 -0
  198. package/src/lib/server/reservation-availability.js +64 -10
  199. package/src/lib/server/reservation-availability.js.map +1 -1
  200. package/src/lib/server/reservation-walk-in.d.ts +28 -0
  201. package/src/lib/server/reservation-walk-in.js +166 -0
  202. package/src/lib/server/reservation-walk-in.js.map +1 -0
  203. package/src/lib/server/reserve.js +13 -10
  204. package/src/lib/server/reserve.js.map +1 -1
  205. package/src/lib/server/reviews.js +3 -1
  206. package/src/lib/server/reviews.js.map +1 -1
  207. package/src/lib/server/site-page-resolver.js +5 -2
  208. package/src/lib/server/site-page-resolver.js.map +1 -1
  209. package/src/lib/server.js +26 -0
  210. package/src/lib/server.js.map +1 -1
  211. package/src/lib/testing/fake-firestore.js +72 -0
  212. package/src/lib/testing/fake-firestore.js.map +1 -1
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../../../libs/plugins/commerce/src/lib/components/console/product-editor-dialog.component.tsx"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n'use client'\n\nimport * as CommerceModel from '../../model'\nimport { useSnackbar } from '@aglyn/shared-ui-snackstack'\nimport { Timestamp } from '@aglyn/shared-util-timestamp'\nimport {\n Alert,\n Autocomplete,\n Box,\n Button,\n Dialog,\n DialogActions,\n DialogContent,\n DialogTitle,\n Divider,\n IconButton,\n MenuItem,\n Stack,\n TableBody,\n TableCell,\n TableHead,\n TableRow,\n TextField,\n Typography,\n} from '@mui/material'\nimport { collection, doc, getDoc } from 'firebase/firestore'\nimport { ScanAdornment } from '../../barcode/scan-button.component'\nimport { productCollectionFields } from './smart-collections'\nimport { memo, useCallback, useMemo, useRef, useState } from 'react'\nimport {\n ceilingedWindow,\n collectionCeiling,\n useFirestore,\n useFirestoreCollection,\n useHostResourceApi,\n writeGuardedBySeed,\n useUser,\n} from '@aglyn/tenant-feature-instance'\nimport { writeSiteWideChange } from '@aglyn/tenant-feature-instance/hooks/helpers/site-wide-change'\nimport { type PickedMedia, useMediaPicker } from '@aglyn/aglyn'\nimport {\n type ConsoleWidgetSlotRenderer,\n useConsoleWidgetSlot,\n} from '@aglyn/aglyn/app-utils/console-widget-slot-context'\nimport {\n seoListingFieldCount,\n seoListingFieldTooLong,\n type SeoListingFieldKey,\n} from '@aglyn/aglyn/app-utils/seo-listing-fields'\nimport type { ConsoleSeoFieldValues } from '@aglyn/aglyn/plugin-manager/feature-plugins'\nimport { ScrollTable } from '@aglyn/shared-ui-jsx/components/scroll-table.component'\nimport { useContentStable } from '@aglyn/shared-ui-jsx/hooks/use-content-stable'\nimport {\n EntitlementUpsell,\n useCommerceEntitlement,\n} from './entitlement-gate.component'\nimport {\n PRODUCT_EDITOR_ZONE,\n type ConsoleProductCopyValues,\n type ConsoleProductEditorZoneProps,\n} from './product-zones'\nimport {\n type MembersVideo,\n MembersVideosField,\n PaidDownloadAddButton,\n PaidMediaProtection,\n} from './paid-media'\nimport { ProductRegisterFields } from './product-register-fields.component'\n\n/**\n * What each picker in this dialog will offer.\n *\n * Every one is a chooser rather than a list, so the ceiling is the number of\n * options a reader can meaningfully scan, and the walk that reaches it is\n * ordered by document name — a picker that silently omits an option is worse\n * than one that admits it stops, because the omission looks like the option\n * not existing.\n */\nconst CATEGORY_CEILING = 250\nconst RELATED_PRODUCT_CEILING = 300\nconst SUPPLIER_CEILING = 50\n\nexport interface ProductEditorDialogProps {\n hostId: string\n /** Product doc (with `$id`) to edit, `null` for a new product. */\n product: (CommerceModel.HostProduct & { $id: string }) | null\n /**\n * The listener that produced `product` has NOT been confirmed by the\n * server (AGL-1358). Required rather than optional on purpose: the\n * products listener lives in the parent hub card, so this dialog cannot\n * compute the verdict, and an optional prop a caller forgets is a guard\n * that is off while looking present.\n */\n seedFromCache: boolean\n /** That listener FAILED (`status === 'error'`). */\n seedUnreadable?: boolean\n open: boolean\n onClose: () => void\n}\n\n/**\n * The search listing fields this editor holds (AGL-2910): `product.seo`\n * carries a title and a description beside its share image, and nothing\n * else a listing zone may propose.\n */\nconst PRODUCT_SEO_LISTING_FIELDS: readonly Extract<SeoListingFieldKey, 'title' | 'description'>[] = [\n 'title',\n 'description',\n]\n\n/**\n * A product nobody has saved yet, as the editor starts one: at the default\n * price (AGL-3676), for the owner to change or clear.\n */\nfunction blankProduct(): CommerceModel.HostProduct {\n return {\n name: '',\n slug: '',\n type: 'physical',\n status: 'draft',\n variants: [{ id: 'default', priceUsd: CommerceModel.COMMERCE_DEFAULT_PRICE_USD }],\n }\n}\n\n/** What the editor says while a variant has no price (AGL-3676): savable, not sellable. */\nexport const PRODUCT_PRICE_EMPTY_NOTICE =\n 'Visitors will see “Price coming soon” and can’t buy this yet. Set a price to start selling it.'\n\n/** Stable key for matching variants across matrix regenerations. */\nfunction comboKey(options: Record<string, string> | undefined): string {\n return Object.entries(options ?? {})\n .sort(([a], [b]) => a.localeCompare(b))\n .map(([name, value]) => `${name}:${value}`)\n .join('|')\n}\n\nfunction comboLabel(options: Record<string, string> | undefined): string {\n const values = Object.values(options ?? {})\n return values.length ? values.join(' / ') : 'Default'\n}\n\n\n/** Stand-in for a list the product does not hold yet, the same one each render. */\nconst NO_ITEMS: readonly string[] = []\nconst NO_OPTIONS: readonly CommerceModel.ProductOption[] = []\nconst NO_FILES: readonly DigitalFile[] = []\nconst NO_VIDEOS: readonly MembersVideo[] = []\nconst FILL_ROW = { flex: 1 } as const\n\nconst categoryLabel = (category: any): string => category.name\nconst recordLabel = (item: any): string => item.name ?? item.$id\nconst sameRecord = (option: any, value: any): boolean => option.$id === value.$id\n\ninterface ProductChipsFieldProps<T> {\n label: string\n options: readonly T[]\n value: readonly T[]\n /** `index` is the prop of the same name, handed back for a per-row field. */\n onChange(next: T[], index: number): void\n index?: number\n freeSolo?: boolean\n getOptionLabel?: (option: T) => string\n isOptionEqualToValue?: (option: T, value: T) => boolean\n placeholder?: string\n helperText?: string\n fill?: boolean\n}\n\n/**\n * One of the editor's chip lists — tags, categories, an option's values,\n * related products — MEMOIZED, and every prop it takes is stable while its\n * own list is (AGL-3423).\n *\n * A multiple Autocomplete hands its input a new chip array as\n * `startAdornment` on every render, and MUI's `InputBase` copies that into\n * its `FormControl` from a passive effect: a state update left pending after\n * every commit the field takes part in. React 19 counts each such commit as a\n * nested update, and keystrokes delivered back to back commit one after\n * another with nothing to clear the count, so the fifty-first throws\n * \"Maximum update depth exceeded\" (#185). Every field in this editor writes\n * one draft, so every keystroke in any of them re-rendered all four lists;\n * kept out of those renders, a list commits only when it changes.\n */\nconst ProductChipsField = memo(function ProductChipsField<T>(\n props: ProductChipsFieldProps<T>,\n) {\n const { index = 0, onChange } = props\n return (\n <Autocomplete<T, true, false, boolean>\n multiple\n freeSolo={props.freeSolo}\n options={props.options as T[]}\n value={props.value as T[]}\n getOptionLabel={props.getOptionLabel as (option: T | string) => string}\n isOptionEqualToValue={props.isOptionEqualToValue}\n onChange={(_event, next) => onChange(next as T[], index)}\n renderInput={(params) => (\n <TextField\n {...params}\n label={props.label}\n size=\"small\"\n placeholder={props.placeholder}\n helperText={props.helperText}\n />\n )}\n sx={props.fill ? FILL_ROW : undefined}\n />\n )\n}) as <T>(props: ProductChipsFieldProps<T>) => JSX.Element\n\ntype DigitalFile = NonNullable<CommerceModel.HostProduct['digitalFiles']>[number]\n\n/** A change to the product, or a function of the product as it stands. */\ntype ProductPatch =\n | Partial<CommerceModel.HostProduct>\n | ((product: CommerceModel.HostProduct) => Partial<CommerceModel.HostProduct>)\n\n/** Spreads a patch over the draft as last rendered. One identity per dialog. */\ntype ProductUpdate = (patch: ProductPatch) => void\n\n/** A stable empty list, so a product without modifiers never redraws its section. */\nconst NO_MODIFIER_GROUPS: CommerceModel.ProductModifierGroup[] = []\n\n/** Replaces the draft with what `build` makes of it as last rendered. */\ntype DraftReplace = (\n build: (product: CommerceModel.HostProduct) => CommerceModel.HostProduct,\n) => void\n\n/** Opens the media browser and hands what was chosen to `apply`. */\ntype MediaPick = (apply: (media: PickedMedia) => void) => Promise<void>\n\n/** A change to one option, or `null` to remove it. */\ntype OptionChange = (\n index: number,\n patch: Partial<CommerceModel.ProductOption> | null,\n) => void\n\n/** What was typed into one variant's field, as the matrix hands it on. */\ntype VariantFieldChange = (\n index: number,\n field: keyof CommerceModel.ProductVariant,\n raw: string,\n) => void\n\ntype FieldChange = { target: { value: string } }\n\n/**\n * A text field that redraws only when what it shows changes (AGL-3423).\n *\n * Every field in this editor writes one draft, so a keystroke in any of them\n * re-renders the dialog, and drawn whole that is some forty inputs and twelve\n * hundred components for one letter in a product with four variants. When a\n * keystroke costs that much, typed input queues and is processed back to\n * back, which is what lets a chip list's pending update climb to #185 (see\n * `ProductChipsField`). The sections below are memoized on the slice of the\n * draft they show, and each field in them is this, handed a handler and\n * styles that keep their identity, so the keystroke redraws the field it\n * lands in.\n */\nconst MemoTextField = memo(TextField) as typeof TextField\n\nconst FIRST_ROW = { mt: 1 } as const\nconst WIDE_ROW = { xs: 'column', sm: 'row' } as const\nconst NARROW_SELECT = { minWidth: 140 } as const\nconst SUPPLIER_SELECT = { minWidth: 160 } as const\nconst OVERSELL_SELECT = { minWidth: 200 } as const\nconst KIND_SELECT = { minWidth: 130 } as const\nconst SHORT_SELECT = { minWidth: 120 } as const\nconst BILLING_SELECT = { minWidth: 180 } as const\nconst COUNT_FIELD = { width: 140 } as const\nconst VERSION_FIELD = { width: 100 } as const\nconst OPTION_FIELD = { width: 160 } as const\nconst PRICE_CELL = { width: 88 } as const\nconst CODE_CELL = { width: 110 } as const\nconst BARCODE_CELL = { width: 150 } as const\nconst STOCK_CELL = { width: 72 } as const\nconst DECIMAL_INPUT = { htmlInput: { inputMode: 'decimal' } } as const\nconst NUMERIC_INPUT = { htmlInput: { inputMode: 'numeric' } } as const\n\nconst TYPE_MENU = [\n <MenuItem key=\"physical\" value=\"physical\">{'Physical'}</MenuItem>,\n <MenuItem key=\"digital\" value=\"digital\">{'Digital'}</MenuItem>,\n <MenuItem key=\"service\" value=\"service\">{'Service'}</MenuItem>,\n]\nconst STATUS_MENU = [\n <MenuItem key=\"draft\" value=\"draft\">{'Draft'}</MenuItem>,\n <MenuItem key=\"active\" value=\"active\">{'Active'}</MenuItem>,\n <MenuItem key=\"archived\" value=\"archived\">{'Archived'}</MenuItem>,\n]\nconst OVERSELL_MENU = [\n <MenuItem key=\"deny\" value=\"deny\">{'Stop selling (sold out)'}</MenuItem>,\n <MenuItem key=\"backorder\" value=\"backorder\">{'Keep selling (backorder)'}</MenuItem>,\n]\nconst TAX_MENU = [\n <MenuItem key=\"taxable\" value=\"taxable\">{'Taxable'}</MenuItem>,\n <MenuItem key=\"exempt\" value=\"exempt\">{'Tax exempt'}</MenuItem>,\n]\nconst INTERVAL_MENU = [\n <MenuItem key=\"month\" value=\"month\">{'Monthly'}</MenuItem>,\n <MenuItem key=\"year\" value=\"year\">{'Yearly'}</MenuItem>,\n]\n\n/**\n * A zone hosted in the dialog, drawn again only when what it is handed\n * changes (AGL-3423). The shell's renderer is not memoized: drawn straight\n * into the dialog, every widget in the zone would redraw on each keystroke in\n * any field.\n */\nconst HostedZone = memo(function HostedZone(\n props: { renderer: ConsoleWidgetSlotRenderer; slot: string } & Record<string, unknown>,\n) {\n const { renderer: Renderer, ...zone } = props\n return <Renderer {...zone} />\n})\n\ninterface ProductBasicsFieldsProps {\n name: string\n slug: string\n type: CommerceModel.ProductType\n status: CommerceModel.ProductStatus\n supplierId: string | undefined\n description: string\n suppliers: readonly any[]\n onName(event: FieldChange): void\n onSlug(event: FieldChange): void\n update: ProductUpdate\n}\n\n/** The product's name and address, type, status, supplier and description. */\nconst ProductBasicsFields = memo(function ProductBasicsFields(\n props: ProductBasicsFieldsProps,\n) {\n const { suppliers, update } = props\n const setType = useCallback(\n (event: FieldChange) =>\n update({ type: event.target.value as CommerceModel.ProductType }),\n [update],\n )\n const setStatus = useCallback(\n (event: FieldChange) =>\n update({ status: event.target.value as CommerceModel.ProductStatus }),\n [update],\n )\n const setSupplier = useCallback(\n (event: FieldChange) => update({ supplierId: event.target.value || undefined }),\n [update],\n )\n const setDescription = useCallback(\n (event: FieldChange) => update({ description: event.target.value }),\n [update],\n )\n const supplierMenu = useMemo(\n () => [\n <MenuItem key=\"\" value=\"\">\n {'None (self-fulfilled)'}\n </MenuItem>,\n ...suppliers.map((supplier: any) => (\n <MenuItem key={supplier.$id} value={supplier.$id}>\n {supplier.name}\n </MenuItem>\n )),\n ],\n [suppliers],\n )\n return (\n <>\n <Stack direction={WIDE_ROW} spacing={2} sx={FIRST_ROW}>\n <MemoTextField\n label=\"Name\"\n value={props.name}\n onChange={props.onName}\n size=\"small\"\n autoFocus\n fullWidth\n />\n <MemoTextField\n label=\"Slug\"\n value={props.slug}\n onChange={props.onSlug}\n size=\"small\"\n fullWidth\n helperText={props.slug ? `/products/${props.slug}` : undefined}\n />\n </Stack>\n <Stack direction=\"row\" spacing={2}>\n <MemoTextField\n label=\"Type\"\n value={props.type}\n onChange={setType}\n size=\"small\"\n select\n sx={NARROW_SELECT}\n >\n {TYPE_MENU}\n </MemoTextField>\n <MemoTextField\n label=\"Status\"\n value={props.status}\n onChange={setStatus}\n size=\"small\"\n select\n sx={NARROW_SELECT}\n >\n {STATUS_MENU}\n </MemoTextField>\n {suppliers.length > 0 ? (\n <MemoTextField\n label=\"Supplier\"\n value={props.supplierId ?? ''}\n onChange={setSupplier}\n size=\"small\"\n select\n sx={SUPPLIER_SELECT}\n helperText=\"Routes paid orders\"\n >\n {supplierMenu}\n </MemoTextField>\n ) : null}\n </Stack>\n <MemoTextField\n label=\"Description\"\n value={props.description}\n onChange={setDescription}\n size=\"small\"\n multiline\n minRows={2}\n />\n </>\n )\n})\n\n/** The product's images, each removable, and the button that adds one. */\nconst ProductMediaFields = memo(function ProductMediaFields(props: {\n mediaUrls: readonly string[]\n update: ProductUpdate\n pick: MediaPick\n}) {\n const { mediaUrls, update, pick } = props\n return (\n <Box sx={{ display: 'flex', gap: 1, flexWrap: 'wrap' }}>\n {mediaUrls.map((url, index) => (\n <Box key={`${url}-${index}`} sx={{ position: 'relative' }}>\n <Box\n component=\"img\"\n src={url}\n alt=\"\"\n sx={{\n width: 72,\n height: 72,\n objectFit: 'cover',\n borderRadius: 1,\n border: 1,\n borderColor: 'divider',\n }}\n />\n <IconButton\n size=\"small\"\n aria-label=\"Remove image\"\n onClick={() =>\n update((product) => ({\n mediaUrls: (product.mediaUrls ?? []).filter(\n (_item, itemIndex) => itemIndex !== index,\n ),\n }))\n }\n sx={{\n position: 'absolute',\n top: -8,\n right: -8,\n bgcolor: 'background.paper',\n border: 1,\n borderColor: 'divider',\n p: 0.25,\n }}\n >\n {'✕'}\n </IconButton>\n </Box>\n ))}\n <Button\n size=\"small\"\n onClick={() =>\n void pick((media) =>\n update((product) => ({\n mediaUrls: [...(product.mediaUrls ?? []), media.url],\n })),\n )\n }\n >\n {'Add image'}\n </Button>\n </Box>\n )\n})\n\nconst ProductOptionRow = memo(function ProductOptionRow(props: {\n index: number\n option: CommerceModel.ProductOption\n onChange: OptionChange\n onValues(values: string[], index: number): void\n}) {\n const { index, option, onChange, onValues } = props\n const setName = useCallback(\n (event: FieldChange) => onChange(index, { name: event.target.value }),\n [index, onChange],\n )\n return (\n <Stack direction=\"row\" spacing={1} sx={{ alignItems: 'flex-start' }}>\n <MemoTextField\n label=\"Option\"\n value={option.name}\n onChange={setName}\n size=\"small\"\n sx={OPTION_FIELD}\n placeholder=\"Size\"\n />\n <ProductChipsField<string>\n freeSolo\n fill\n label=\"Values\"\n placeholder=\"S, M, L…\"\n options={NO_ITEMS}\n value={option.values}\n index={index}\n onChange={onValues}\n />\n <Button\n size=\"small\"\n color=\"error\"\n onClick={() => onChange(index, null)}\n sx={{ mt: 0.5 }}\n >\n {'Remove'}\n </Button>\n </Stack>\n )\n})\n\n/** The product's options, one row each, and the button that adds one. */\nconst ProductOptionsFields = memo(function ProductOptionsFields(props: {\n options: readonly CommerceModel.ProductOption[]\n onChange: OptionChange\n onValues(values: string[], index: number): void\n}) {\n const { options, onChange, onValues } = props\n return (\n <>\n {options.map((option, index) => (\n <ProductOptionRow\n key={index}\n index={index}\n option={option}\n onChange={onChange}\n onValues={onValues}\n />\n ))}\n {options.length < CommerceModel.COMMERCE_MAX_OPTIONS ? (\n <Button\n size=\"small\"\n sx={{ alignSelf: 'flex-start' }}\n onClick={() => onChange(options.length, { name: '', values: [] })}\n >\n {'Add option'}\n </Button>\n ) : null}\n </>\n )\n})\n\nconst ProductVariantRow = memo(function ProductVariantRow(props: {\n index: number\n variant: CommerceModel.ProductVariant\n stockApplies: boolean\n onField: VariantFieldChange\n}) {\n const { index, variant, stockApplies, onField } = props\n const label = comboLabel(variant.options)\n // One handler per cell, each keeping its identity while the row's does.\n const set = useMemo(() => {\n const cell =\n (field: keyof CommerceModel.ProductVariant) => (event: FieldChange) =>\n onField(index, field, event.target.value)\n return {\n priceUsd: cell('priceUsd'),\n compareAtPriceUsd: cell('compareAtPriceUsd'),\n sku: cell('sku'),\n barcode: cell('barcode'),\n inventory: cell('inventory'),\n weightGrams: cell('weightGrams'),\n }\n }, [index, onField])\n const stockInput = useMemo(\n () => ({\n htmlInput: {\n inputMode: 'numeric' as const,\n 'aria-label': `Stock — ${label}`,\n },\n }),\n [label],\n )\n // A camera scan fills the barcode the same way typing it does (AGL-3619).\n const barcodeInput = useMemo(\n () => ({\n htmlInput: { 'aria-label': `Barcode — ${label}` },\n input: {\n endAdornment: (\n <ScanAdornment\n label={`Scan the barcode for ${label}`}\n onScan={(code) => onField(index, 'barcode', code)}\n />\n ),\n },\n }),\n [label, index, onField],\n )\n return (\n <TableRow>\n <TableCell sx={{ whiteSpace: 'nowrap' }}>{label}</TableCell>\n <TableCell>\n <MemoTextField\n value={variant.priceUsd ?? ''}\n onChange={set.priceUsd}\n size=\"small\"\n sx={PRICE_CELL}\n // An empty price is marked (AGL-2916), gently (AGL-3676): the\n // product saves without one, and the storefront says \"Price\n // coming soon\" and sells it nowhere.\n color={CommerceModel.variantHasPrice(variant) ? undefined : 'warning'}\n focused={CommerceModel.variantHasPrice(variant) ? undefined : true}\n placeholder=\"Set\"\n slotProps={DECIMAL_INPUT}\n />\n </TableCell>\n <TableCell>\n <MemoTextField\n value={variant.compareAtPriceUsd ?? ''}\n onChange={set.compareAtPriceUsd}\n size=\"small\"\n sx={PRICE_CELL}\n slotProps={DECIMAL_INPUT}\n />\n </TableCell>\n <TableCell>\n <MemoTextField\n value={variant.sku ?? ''}\n onChange={set.sku}\n size=\"small\"\n sx={CODE_CELL}\n />\n </TableCell>\n <TableCell>\n <MemoTextField\n value={variant.barcode ?? ''}\n onChange={set.barcode}\n size=\"small\"\n sx={BARCODE_CELL}\n slotProps={barcodeInput}\n />\n </TableCell>\n <TableCell>\n <MemoTextField\n value={variant.inventory ?? ''}\n placeholder={stockApplies ? '—' : 'n/a'}\n disabled={!stockApplies}\n onChange={set.inventory}\n size=\"small\"\n sx={STOCK_CELL}\n slotProps={stockInput}\n />\n </TableCell>\n <TableCell>\n <MemoTextField\n value={variant.weightGrams ?? ''}\n onChange={set.weightGrams}\n size=\"small\"\n sx={PRICE_CELL}\n slotProps={NUMERIC_INPUT}\n />\n </TableCell>\n </TableRow>\n )\n})\n\n/** The matrix's column headings, one element for every render. */\nconst VARIANTS_HEAD = (\n <TableHead>\n <TableRow>\n <TableCell>{'Variant'}</TableCell>\n <TableCell>{'Price ($)'}</TableCell>\n <TableCell>{'Compare-at'}</TableCell>\n <TableCell>{'SKU'}</TableCell>\n <TableCell>{'Barcode'}</TableCell>\n <TableCell>{'Stock'}</TableCell>\n <TableCell>{'Weight (g)'}</TableCell>\n </TableRow>\n </TableHead>\n)\n\n/**\n * The variants matrix: one row per combination of the options above, each\n * with its own price, SKU, barcode, stock and weight. A keystroke in one row\n * leaves the others' props as they were.\n */\nconst ProductVariantsTable = memo(function ProductVariantsTable(props: {\n variants: readonly CommerceModel.ProductVariant[]\n stockApplies: boolean\n onField: VariantFieldChange\n}) {\n const { variants, stockApplies, onField } = props\n return (\n <Box>\n <ScrollTable size=\"small\">\n {VARIANTS_HEAD}\n <TableBody>\n {variants.map((variant, index) => (\n <ProductVariantRow\n key={variant.id}\n index={index}\n variant={variant}\n stockApplies={stockApplies}\n onField={onField}\n />\n ))}\n </TableBody>\n </ScrollTable>\n </Box>\n )\n})\n\n/** What happens when stock runs out, the gift-card kind, tax, and the low-stock alert. */\nconst ProductSellingFields = memo(function ProductSellingFields(props: {\n oversellPolicy: 'deny' | 'backorder'\n giftCard: boolean\n taxExempt: boolean\n lowStockThreshold: number | undefined\n stockApplies: boolean\n giftsLocked: boolean\n giftsPlanLabel: string | undefined\n update: ProductUpdate\n}) {\n const { giftsLocked, giftsPlanLabel, update } = props\n const setOversellPolicy = useCallback(\n (event: FieldChange) =>\n update({ oversellPolicy: event.target.value as 'deny' | 'backorder' }),\n [update],\n )\n const setKind = useCallback(\n (event: FieldChange) => update({ giftCard: event.target.value === 'gift' }),\n [update],\n )\n const setTax = useCallback(\n (event: FieldChange) => update({ taxExempt: event.target.value === 'exempt' }),\n [update],\n )\n const setLowStock = useCallback(\n (event: FieldChange) => {\n const raw = event.target.value.trim()\n update({\n lowStockThreshold:\n raw === '' ? undefined : Math.max(0, Math.round(Number(raw))),\n })\n },\n [update],\n )\n const kindMenu = useMemo(\n () => [\n <MenuItem key=\"standard\" value=\"standard\">\n {'Standard'}\n </MenuItem>,\n // Disabled, never removed (AGL-2080). A product saved as a gift\n // card before the plan lapsed still has `giftCard: true`, and a\n // MUI select whose value is absent from its options renders\n // blank — the next edit would silently rewrite the product to\n // Standard. Locking the option refuses NEW configuration\n // without rewriting existing data.\n <MenuItem value=\"gift\" key=\"gift\" disabled={giftsLocked}>\n {giftsLocked ? `Gift card — ${giftsPlanLabel ?? 'upgrade'} plan` : 'Gift card'}\n </MenuItem>,\n ],\n [giftsLocked, giftsPlanLabel],\n )\n return (\n <Stack direction=\"row\" spacing={2}>\n <MemoTextField\n label=\"When out of stock\"\n value={props.oversellPolicy}\n onChange={setOversellPolicy}\n size=\"small\"\n select\n sx={OVERSELL_SELECT}\n >\n {OVERSELL_MENU}\n </MemoTextField>\n <MemoTextField\n label=\"Kind\"\n value={props.giftCard ? 'gift' : 'standard'}\n onChange={setKind}\n size=\"small\"\n select\n sx={KIND_SELECT}\n helperText={\n giftsLocked\n ? `Gift cards are on ${giftsPlanLabel ?? 'a higher plan'}`\n : 'Gift cards issue a code'\n }\n >\n {kindMenu}\n </MemoTextField>\n <MemoTextField\n label=\"Tax\"\n value={props.taxExempt ? 'exempt' : 'taxable'}\n onChange={setTax}\n size=\"small\"\n select\n sx={SHORT_SELECT}\n >\n {TAX_MENU}\n </MemoTextField>\n <MemoTextField\n label=\"Low-stock alert at\"\n value={props.lowStockThreshold ?? ''}\n placeholder=\"Off\"\n disabled={!props.stockApplies}\n onChange={setLowStock}\n size=\"small\"\n sx={COUNT_FIELD}\n slotProps={NUMERIC_INPUT}\n helperText=\"Notifies managers\"\n />\n </Stack>\n )\n})\n\n/** One-time or subscription billing, its interval, and a free trial. */\nconst ProductBillingFields = memo(function ProductBillingFields(props: {\n subscription: CommerceModel.HostProduct['subscription']\n subscriptionOptional: boolean | undefined\n subsLocked: boolean\n subsPlanLabel: string | undefined\n update: ProductUpdate\n replaceDraft: DraftReplace\n}) {\n const { subscription, subscriptionOptional, subsLocked, update, replaceDraft } =\n props\n const setBilling = useCallback(\n (event: FieldChange) => {\n const value = event.target.value\n // `replaceDraft`, not `update`: a patch is spread over the draft,\n // which would resurrect the keys deleted below.\n replaceDraft((product) => {\n // \"Both\" (AGL-545): the PDP offers one-time OR subscribe at\n // the same price; the interval field beside picks the cadence.\n // Cleared keys are deleted (not set undefined) so the\n // client-direct setDoc on save never sees undefined values.\n const next = { ...product }\n if (value === 'once') {\n delete next.subscription\n } else {\n next.subscription = {\n ...(product.subscription ?? {}),\n interval:\n value === 'both'\n ? (product.subscription?.interval ?? 'month')\n : (value as 'month' | 'year'),\n }\n }\n if (value === 'both') next.subscriptionOptional = true\n else delete next.subscriptionOptional\n return next\n })\n },\n [replaceDraft],\n )\n const setBillingInterval = useCallback(\n (event: FieldChange) => {\n const interval = event.target.value as 'month' | 'year'\n update((product) => ({\n subscription: { ...product.subscription!, interval },\n }))\n },\n [update],\n )\n const setTrialDays = useCallback(\n (event: FieldChange) => {\n const raw = event.target.value.trim()\n update((product) => ({\n subscription: {\n ...product.subscription!,\n ...(raw === ''\n ? { trialDays: undefined }\n : { trialDays: Math.max(1, Math.round(Number(raw))) }),\n },\n }))\n },\n [update],\n )\n const billingMenu = useMemo(\n () => [\n <MenuItem key=\"once\" value=\"once\">\n {'One-time purchase'}\n </MenuItem>,\n // Same rule as the gift-card option: disabled, not removed, so an\n // existing subscription product keeps its interval instead of being\n // silently reset to one-time.\n <MenuItem value=\"month\" key=\"month\" disabled={subsLocked}>\n {'Monthly subscription'}\n </MenuItem>,\n <MenuItem value=\"year\" key=\"year\" disabled={subsLocked}>\n {'Yearly subscription'}\n </MenuItem>,\n <MenuItem value=\"both\" key=\"both\" disabled={subsLocked}>\n {'Both — buyer chooses'}\n </MenuItem>,\n ],\n [subsLocked],\n )\n return (\n <Stack direction=\"row\" spacing={2}>\n <MemoTextField\n label=\"Billing\"\n value={\n subscription\n ? subscriptionOptional\n ? 'both'\n : subscription.interval\n : 'once'\n }\n onChange={setBilling}\n size=\"small\"\n select\n sx={BILLING_SELECT}\n helperText={\n subsLocked\n ? `Subscriptions are on ${props.subsPlanLabel ?? 'a higher plan'}`\n : 'Subscriptions bill until canceled'\n }\n >\n {billingMenu}\n </MemoTextField>\n {subscription && subscriptionOptional ? (\n <MemoTextField\n label=\"Interval\"\n value={subscription.interval}\n onChange={setBillingInterval}\n size=\"small\"\n select\n sx={SHORT_SELECT}\n >\n {INTERVAL_MENU}\n </MemoTextField>\n ) : null}\n {subscription ? (\n <MemoTextField\n label=\"Free trial (days)\"\n placeholder=\"None\"\n value={subscription.trialDays ?? ''}\n onChange={setTrialDays}\n size=\"small\"\n sx={COUNT_FIELD}\n slotProps={NUMERIC_INPUT}\n />\n ) : null}\n </Stack>\n )\n})\n\nconst DigitalFileRow = memo(function DigitalFileRow(props: {\n index: number\n file: DigitalFile\n hostId: string\n productId: string | undefined\n update: ProductUpdate\n}) {\n const { index, file, update } = props\n const setVersion = useCallback(\n (event: FieldChange) => {\n const version = event.target.value.slice(0, 20)\n update((product) => {\n const digitalFiles = [...(product.digitalFiles ?? [])]\n digitalFiles[index] = { ...file, version }\n return { digitalFiles }\n })\n },\n [file, index, update],\n )\n return (\n <Stack direction=\"row\" spacing={1} sx={{ alignItems: 'center' }}>\n <Typography variant=\"body2\" sx={{ flex: 1 }} noWrap>\n {file.fileName}\n {file.version ? ` · v${file.version}` : ''}\n </Typography>\n <PaidMediaProtection\n url={file.url}\n hostId={props.hostId}\n productId={props.productId}\n kind=\"download\"\n />\n <MemoTextField\n label=\"Version\"\n value={file.version ?? ''}\n onChange={setVersion}\n size=\"small\"\n sx={VERSION_FIELD}\n />\n <Button\n size=\"small\"\n color=\"error\"\n onClick={() =>\n update((product) => ({\n digitalFiles: (product.digitalFiles ?? []).filter(\n (_item, itemIndex) => itemIndex !== index,\n ),\n }))\n }\n >\n {'✕'}\n </Button>\n </Stack>\n )\n})\n\n/*\n * The paid-media controls beside the digital fields, drawn again only when\n * what they are handed changes: a keystroke in the download limit leaves the\n * videos, and the protection check on each, as they were.\n */\nconst MemoMembersVideosField = memo(MembersVideosField)\nconst MemoPaidDownloadAddButton = memo(PaidDownloadAddButton)\n\n/** A digital product's files, its download limit and its members videos. */\nconst ProductDigitalFields = memo(function ProductDigitalFields(props: {\n hostId: string\n productId: string | undefined\n digitalFiles: readonly DigitalFile[]\n downloadLimit: number | undefined\n gatedVideos: readonly MembersVideo[]\n update: ProductUpdate\n}) {\n const { hostId, productId, update } = props\n const addFile = useCallback(\n (file: DigitalFile) =>\n update((product) => ({\n digitalFiles: [...(product.digitalFiles ?? []), file],\n })),\n [update],\n )\n const setDownloadLimit = useCallback(\n (event: FieldChange) => {\n const raw = event.target.value.trim()\n update({\n downloadLimit:\n raw === '' ? undefined : Math.max(1, Math.round(Number(raw))),\n })\n },\n [update],\n )\n const setVideos = useCallback(\n (gatedVideos: MembersVideo[]) => update({ gatedVideos }),\n [update],\n )\n return (\n <>\n <Divider textAlign=\"left\">{'Digital delivery'}</Divider>\n {props.digitalFiles.map((file, index) => (\n <DigitalFileRow\n key={index}\n index={index}\n file={file}\n hostId={hostId}\n productId={productId}\n update={update}\n />\n ))}\n <Stack direction=\"row\" spacing={2}>\n {/* Paid downloads are private files delivered through expiring\n links (AGL-2847); adding one makes the file private. */}\n <MemoPaidDownloadAddButton\n hostId={hostId}\n productId={productId}\n onAdd={addFile}\n />\n <MemoTextField\n label=\"Download limit\"\n placeholder=\"Unlimited\"\n value={props.downloadLimit ?? ''}\n onChange={setDownloadLimit}\n size=\"small\"\n sx={COUNT_FIELD}\n slotProps={NUMERIC_INPUT}\n helperText=\"Attempts per order\"\n />\n </Stack>\n <Typography variant=\"caption\" color=\"text.secondary\">\n {'Buyers always download the current files — uploading a new ' +\n 'version re-delivers to everyone.'}\n </Typography>\n {/* Members videos are private files delivered through expiring\n links (AGL-2814); adding one makes the file private. */}\n <MemoMembersVideosField\n hostId={hostId}\n productId={productId}\n videos={props.gatedVideos}\n onChange={setVideos}\n />\n </>\n )\n})\n\n/** The product's search listing: its title, description and share image. */\nconst ProductSeoFields = memo(function ProductSeoFields(props: {\n title: string | undefined\n description: string | undefined\n hasImage: boolean\n update: ProductUpdate\n pick: MediaPick\n}) {\n const { title, description, update, pick } = props\n const setTitle = useCallback(\n (event: FieldChange) => {\n const next = event.target.value\n update((product) => ({ seo: { ...product.seo, title: next } }))\n },\n [update],\n )\n const setDescription = useCallback(\n (event: FieldChange) => {\n const next = event.target.value\n update((product) => ({ seo: { ...product.seo, description: next } }))\n },\n [update],\n )\n return (\n <>\n <Divider textAlign=\"left\">{'Search engine listing'}</Divider>\n <Stack direction={WIDE_ROW} spacing={2}>\n <MemoTextField\n label=\"SEO title\"\n value={title ?? ''}\n onChange={setTitle}\n // The counts every search listing editor prints (AGL-2910): what a\n // search result shows before it truncates.\n helperText={seoListingFieldCount('title', title)}\n error={seoListingFieldTooLong('title', title)}\n size=\"small\"\n fullWidth\n />\n <Button\n size=\"small\"\n onClick={() =>\n void pick((media) =>\n update((product) => ({\n seo: { ...product.seo, imageUrl: media.url },\n })),\n )\n }\n >\n {props.hasImage ? 'Change OG image' : 'OG image'}\n </Button>\n </Stack>\n <MemoTextField\n label=\"SEO description\"\n value={description ?? ''}\n onChange={setDescription}\n helperText={seoListingFieldCount('description', description)}\n error={seoListingFieldTooLong('description', description)}\n size=\"small\"\n multiline\n minRows={2}\n />\n </>\n )\n})\n\n/**\n * Products hub editor (AGL-279): the full catalog editor — basics,\n * media, tags, options → variants matrix, per-variant pricing/stock, and\n * SEO overrides. Saving denormalizes `priceUsd`/`inventory` from the\n * first variant so the legacy Product block + checkout API (AGL-90) keep\n * charging correctly without reading the variants array.\n */\nexport function ProductEditorDialog(props: ProductEditorDialogProps) {\n const { hostId, product, seedFromCache, seedUnreadable, open, onClose } =\n props\n\n /**\n * Field-level entitlement gates (AGL-2080). Both of these were fully\n * configurable by an unentitled org and refused only at checkout — by\n * `server/checkout.ts:149` for subscriptions and `:157` /\n * `cart-checkout.ts:156` for gift cards. The operator saw a saved product;\n * the buyer saw the refusal.\n *\n * `ready && !entitled`, never `!entitled`. `checkEntitlement(undefined)`\n * resolves the FREE tier rather than \"unknown\", so gating on the raw call\n * would disable these controls at a PAYING org for the render or two its\n * org doc is in flight. Erring open for that window costs nothing — the\n * server enforces regardless — while erring closed is a paying customer\n * told they cannot use what they bought.\n */\n const subs = useCommerceEntitlement(hostId, 'storefrontSubscriptions')\n const gifts = useCommerceEntitlement(hostId, 'giftCards')\n // The register settings show only where the plan includes POS (AGL-3607).\n const pos = useCommerceEntitlement(hostId, 'pos')\n const subsLocked = subs.ready && !subs.entitled\n const giftsLocked = gifts.ready && !gifts.entitled\n const firestore = useFirestore()\n const { data: user } = useUser()\n const createHostResource = useHostResourceApi()\n const { enqueueSnackbar } = useSnackbar()\n /**\n * The three pickers this dialog draws, read only once it is OPEN.\n *\n * `ProductEditorDialog` is rendered unconditionally by the products hub and\n * takes `open` as a prop, so its body runs on every render of that page. A\n * listener built here without the gate subscribes whether or not anyone\n * opens the editor, which charges every visit to the catalog for three\n * collections the visitor never sees.\n *\n * `null` is what `useFirestoreCollection` takes to mean \"do not subscribe\",\n * so the closed dialog costs nothing and the open one pays once.\n */\n const { data: categoryDocs } = useFirestoreCollection<any>(\n () =>\n open\n ? collectionCeiling(\n collection(firestore, 'hosts', hostId, 'productCategories'),\n CATEGORY_CEILING,\n )\n : null,\n [firestore, hostId, open],\n { idField: '$id' },\n )\n const { data: allProductDocs } = useFirestoreCollection<any>(\n () =>\n open\n ? collectionCeiling(\n collection(firestore, 'hosts', hostId, 'products'),\n RELATED_PRODUCT_CEILING,\n )\n : null,\n [firestore, hostId, open],\n { idField: '$id' },\n )\n const { data: supplierDocs } = useFirestoreCollection<any>(\n () =>\n open\n ? collectionCeiling(\n collection(firestore, 'hosts', hostId, 'suppliers'),\n SUPPLIER_CEILING,\n )\n : null,\n [firestore, hostId, open],\n { idField: '$id' },\n )\n const categories = useMemo(\n () => ceilingedWindow<any>(categoryDocs ?? undefined, CATEGORY_CEILING),\n [categoryDocs],\n )\n const relatedProducts = useMemo(\n () =>\n ceilingedWindow<any>(allProductDocs ?? undefined, RELATED_PRODUCT_CEILING),\n [allProductDocs],\n )\n const suppliers = useMemo(\n () => ceilingedWindow<any>(supplierDocs ?? undefined, SUPPLIER_CEILING),\n [supplierDocs],\n )\n\n const lifted = useMemo(\n () => (product ? CommerceModel.liftLegacyProduct(product) : null),\n [product],\n )\n const [draft, setDraft] = useState<CommerceModel.HostProduct | null>(null)\n const [slugTouched, setSlugTouched] = useState(false)\n // The console media browser is provided by the shell (AGL-395); opening it\n // resolves with the chosen asset (or null if cancelled).\n const { pickMedia } = useMediaPicker()\n const pick = useCallback<MediaPick>(\n async (apply) => {\n const media = await pickMedia?.()\n if (media) apply(media)\n },\n [pickMedia],\n )\n // Lazy-init per open; parent remounts via `key` on product change.\n const current: CommerceModel.HostProduct = draft ?? lifted ?? blankProduct()\n /*\n * The two writes every field goes through, each keeping its identity for\n * the life of the dialog so a memoized section redraws only when its own\n * slice of the draft does (AGL-3423). Both write from the draft as last\n * rendered, which `latest` holds: `update` spreads a patch over it, and a\n * patch that is a function is handed it, so no field holds a copy of the\n * product to spread. A write that lands after a picker closes lands on the\n * draft as it is then.\n */\n const latest = useRef(current)\n latest.current = current\n const replaceDraft = useCallback<DraftReplace>(\n (build) => setDraft(build(latest.current)),\n [],\n )\n const update = useCallback<ProductUpdate>(\n (patch) =>\n replaceDraft((at) => ({\n ...at,\n ...(typeof patch === 'function' ? patch(at) : patch),\n })),\n [replaceDraft],\n )\n const setTags = useCallback(\n (tags: string[]) =>\n update({ tags: tags.map((tag) => String(tag).trim()).filter(Boolean) }),\n [update],\n )\n const setCategories = useCallback(\n (picked: any[]) =>\n update({ categoryIds: picked.map((category: any) => category.$id) }),\n [update],\n )\n const setRelatedProducts = useCallback(\n (picked: any[]) =>\n update({ relatedProductIds: picked.map((item: any) => item.$id) }),\n [update],\n )\n const categoryIds = current.categoryIds\n const pickedCategories = useMemo(\n () =>\n categories.rows.filter((category: any) =>\n (categoryIds ?? []).includes(category.$id),\n ),\n [categories.rows, categoryIds],\n )\n const relatedProductIds = current.relatedProductIds\n const productId = product?.$id\n const relatedOptions = useMemo(\n () =>\n relatedProducts.rows.filter(\n (item: any) => !item.deletedAt && item.$id !== productId,\n ),\n [relatedProducts.rows, productId],\n )\n const pickedRelated = useMemo(\n () =>\n relatedProducts.rows.filter((item: any) =>\n (relatedProductIds ?? []).includes(item.$id),\n ),\n [relatedProducts.rows, relatedProductIds],\n )\n\n /** The shell's zone renderer (AGL-2910); `null` outside the console shell. */\n const WidgetSlot = useConsoleWidgetSlot()\n /**\n * A listing zone widget's proposal, staged into the draft like typing.\n * Functional, because a proposal can arrive after a generation finishes,\n * and a closure over the render that started it would put back every edit\n * made while it ran. Only the fields a product's listing holds are taken.\n */\n const proposeSeoValues = useCallback(\n (values: ConsoleSeoFieldValues) => {\n const staged: { title?: string; description?: string } = {}\n for (const field of PRODUCT_SEO_LISTING_FIELDS) {\n const value = values[field]\n if (typeof value === 'string') staged[field] = value\n }\n if (!Object.keys(staged).length) return\n setDraft((prior) => {\n const base = prior ?? lifted ?? blankProduct()\n return { ...base, seo: { ...base.seo, ...staged } }\n })\n },\n [lifted],\n )\n\n /**\n * The product zone's proposal (AGL-2916): copy staged into the draft like\n * typing, functional for the reason `proposeSeoValues` gives. Option names\n * go through `renameProductOptions`, so every variant keeps its price, SKU\n * and stock.\n */\n const proposeProductValues = useCallback(\n (values: ConsoleProductCopyValues) => {\n setDraft((prior) => {\n const base = prior ?? lifted ?? blankProduct()\n return { ...base, ...CommerceModel.productCopyPatch(base, values) }\n })\n },\n [lifted],\n )\n const zoneCategories = useMemo(\n () => categories.rows.map((category: any) => ({ id: String(category.$id), name: String(category.name ?? '') })),\n [categories.rows],\n )\n /*\n * What the two zones are handed, held by content: a keystroke in a field\n * neither zone reads (a SKU, a price) leaves both as they were.\n */\n const zoneProduct = useContentStable<ConsoleProductEditorZoneProps['product']>({\n id: product?.$id ?? null,\n name: current.name,\n type: current.type,\n description: String(current.description ?? ''),\n tags: current.tags ?? [],\n categoryIds: current.categoryIds ?? [],\n options: (current.options ?? []).map((option) => ({ name: option.name, values: option.values })),\n mediaUrls: current.mediaUrls ?? [],\n seoTitle: current.seo?.title ?? '',\n seoDescription: current.seo?.description ?? '',\n shipping: {\n lengthCm: current.shipping?.lengthCm ?? null,\n widthCm: current.shipping?.widthCm ?? null,\n heightCm: current.shipping?.heightCm ?? null,\n hsCode: current.shipping?.hsCode ?? '',\n originCountry: current.shipping?.originCountry ?? '',\n },\n channel: {\n brand: current.channel?.brand ?? '',\n gtin: current.channel?.gtin ?? '',\n mpn: current.channel?.mpn ?? '',\n condition: current.channel?.condition ?? '',\n googleProductCategory: current.channel?.googleProductCategory ?? '',\n },\n })\n const seoSubject = useContentStable({\n kind: 'product',\n id: product?.$id ?? null,\n name: current.name,\n description: String(current.description ?? ''),\n })\n const seoValues = useContentStable({\n title: current.seo?.title ?? '',\n description: current.seo?.description ?? '',\n })\n\n const error = current.name ? CommerceModel.validateProduct(current) : null\n\n /**\n * Stock tracking is inert on a subscription-only product (AGL-1744) —\n * nothing decrements it on the first charge or on any renewal, so the\n * editor stops offering a number it cannot keep true. Existing\n * configuration is NOT discarded: the stored value stays on the document\n * (this save is a full replace of `current`, and `current` is untouched\n * here), stays visible in the disabled field, and becomes editable again\n * the moment Billing goes back to \"One-time purchase\" or \"Both\".\n */\n const stockApplies = CommerceModel.stockTrackingApplies(current)\n const strandedStock = stockApplies\n ? null\n : CommerceModel.productInventory(current)\n\n /**\n * The one destructive move, and the merchant makes it deliberately.\n *\n * Needed because the checkout gate is unchanged: a stored `0` on a\n * subscription-only product still 409s every new subscriber, and with the\n * field disabled that would be a trap with no way out. `inventoryByLocation`\n * goes with it — `adjustVariantInventory` re-sums the flat count from those\n * buckets (AGL-286), so leaving them would let a later restock resurrect a\n * count this just cleared. Keys are DELETED rather than set undefined; the\n * save is a client-direct `setDoc`, which rejects undefined values.\n */\n const handleClearStockTracking = () => {\n update((at) => ({\n variants: at.variants.map((variant) => {\n const { inventoryByLocation: _perLocation, ...rest } = variant\n return { ...rest, inventory: null }\n }),\n }))\n }\n\n const handleName = useCallback(\n (event: FieldChange) => {\n const name = event.target.value\n update({\n name,\n ...(!product && !slugTouched ? { slug: CommerceModel.commerceSlug(name) } : {}),\n })\n },\n [product, slugTouched, update],\n )\n const handleSlug = useCallback(\n (event: FieldChange) => {\n setSlugTouched(true)\n update({ slug: CommerceModel.commerceSlug(event.target.value) })\n },\n [update],\n )\n\n const handleOptionsChange = useCallback<OptionChange>(\n (index, patch) =>\n update((at) => {\n // A RENAME moves each variant's selection to the new name (AGL-3066).\n // Rebuilding the matrix matches variants by name and value, so under a\n // new name it finds none and replaces every variant, its id, price, SKU\n // and stock with them. Only a change of values rebuilds.\n if (\n patch &&\n at.options?.[index] &&\n Object.keys(patch).length === 1 &&\n typeof patch.name === 'string'\n ) {\n return CommerceModel.renameProductOptions(\n at,\n at.options.map((option, optionIndex) =>\n optionIndex === index ? patch.name : option.name,\n ),\n )\n }\n const options = [...(at.options ?? [])]\n if (patch === null) options.splice(index, 1)\n else options[index] = { name: '', values: [], ...options[index], ...patch }\n // Regenerate the matrix, carrying data over by option-combo key so\n // edits to prices/SKUs survive option tweaks.\n const previous = new Map(\n at.variants.map((variant) => [comboKey(variant.options), variant]),\n )\n const fallback = at.variants[0]\n const variants = CommerceModel.expandVariantMatrix(options).map(\n (combo, comboIndex) => {\n const existing = previous.get(comboKey(combo))\n return (\n existing ??\n // An unpriced variant is stored with no `priceUsd` (AGL-3676),\n // as a proposed product's are; the type names the priced shape.\n ({\n id: `v${Date.now().toString(36)}${comboIndex}`,\n options: combo,\n // The first variant's price, or none where it has none;\n // the default only on a product with no variant yet.\n ...(fallback\n ? CommerceModel.variantHasPrice(fallback)\n ? { priceUsd: fallback.priceUsd }\n : {}\n : { priceUsd: CommerceModel.COMMERCE_DEFAULT_PRICE_USD }),\n inventory: fallback?.inventory ?? null,\n } as CommerceModel.ProductVariant)\n )\n },\n )\n return { options, variants }\n }),\n [update],\n )\n const setOptionValues = useCallback(\n (values: string[], index: number) =>\n handleOptionsChange(index, {\n values: values.map((value) => String(value).trim()).filter(Boolean),\n }),\n [handleOptionsChange],\n )\n\n const handleVariantField = useCallback<VariantFieldChange>(\n (index, field, raw) =>\n update((at) => {\n const variants = [...at.variants]\n const numeric = ['priceUsd', 'compareAtPriceUsd', 'weightGrams']\n const value =\n field === 'inventory'\n ? raw.trim() === ''\n ? null\n : Math.max(0, Math.round(Number(raw)))\n : numeric.includes(field)\n ? raw.trim() === ''\n ? undefined\n : Number(raw)\n : raw\n variants[index] = { ...variants[index], [field]: value }\n // A cleared price is no price (AGL-3676), never an `undefined` the\n // client-direct `setDoc` refuses.\n if (\n value === undefined &&\n (field === 'priceUsd' ||\n field === 'compareAtPriceUsd' ||\n field === 'weightGrams')\n ) {\n delete (variants[index] as any)[field]\n }\n return { variants }\n }),\n [update],\n )\n\n\n const handleSave = useCallback(async () => {\n if (!current.name.trim() || error) return\n /*\n * The fields the save writes — `$id` and the seed's `skus`/`barcodes`\n * dropped, the name with its search keys, slug, price, stock fields,\n * image — are `productSaveFields`, the same code the native apps' save\n * route runs (AGL-3652). JSON-safe: no Firestore Timestamp, which would\n * not survive the API hop; millis fields are what checkout reads.\n */\n const base = CommerceModel.productSaveFields(current, Date.now())\n try {\n /**\n * Refuse an EDIT whose seed the server never confirmed (AGL-1358).\n *\n * `merge: false` — a genuine full-document replace, and the payload is\n * `{...current}`, which is `draft ?? lifted(product)`: every field the\n * dialog was seeded with, whether or not it was touched. So a cached\n * seed does not lose the one edit, it replaces the stored product with\n * the cache's whole picture of it — price, variants, stock, media,\n * status, SEO. Anything written since that snapshot, by a colleague or\n * by the checkout engine, is gone.\n *\n * Only the edit path is guarded. A NEW product goes through the\n * quota-enforcing resources API at a fresh uid and can overwrite\n * nothing; the first snapshot of any listener is `fromCache: true`, so\n * guarding a create would refuse a save that was never unsafe.\n *\n * The guard WRAPS the write: an early return is a shape you can keep\n * while losing the protection.\n */\n const verdict = await writeGuardedBySeed(\n {\n subject: 'product',\n unreadable: Boolean(product) && seedUnreadable,\n fromCache: Boolean(product) && seedFromCache,\n },\n async () => {\n // The smart collections this product's rules answer, from the\n // host's rules as they stand now (AGL-3321).\n const membership = await productCollectionFields(\n firestore,\n hostId,\n CommerceModel.productMembershipInput(base, current),\n )\n if (product) {\n /**\n * RESERVATIONS ARE NOT THE EDITOR'S TO WRITE (AGL-2356).\n *\n * Checkout stores live stock holds in a `stockHolds` map on this\n * document, and this is a `merge: false` replace of a payload\n * built from the dialog's SEED. Left alone it would write whatever\n * that seed happened to carry, and both directions are wrong: a\n * seed taken before a shopper reached checkout erases a live\n * reservation and reopens the oversell for that session, and a\n * seed carrying a hold that has since settled resurrects a\n * reservation against stock that is already sold.\n *\n * So the field is dropped from the payload and re-read from the\n * server immediately before the write. One extra read on a product\n * save, in exchange for an editor that cannot invent or destroy a\n * reservation. The AGL-1358 seed guard above bounds how stale the\n * REST of this payload can be; it cannot help here, because a hold\n * legitimately appears seconds after a perfectly fresh seed.\n */\n const productRef = doc(\n firestore,\n 'hosts',\n hostId,\n 'products',\n product.$id,\n )\n const stored = await getDoc(productRef).catch(() => undefined)\n // A product deleted since the editor opened stays deleted. This\n // replace writes `deletedAt: null`, so saving it would bring the\n // product back without the allowance check a create meets — a\n // deleted product no longer holds a slot (AGL-3918). The app's\n // save route refuses the same way.\n if (stored?.get('deletedAt') != null) {\n throw new Error('This product was deleted, so it can no longer be saved')\n }\n const liveHolds = stored?.get('stockHolds')\n // Edit stays client-direct (no quota consumed); full replace.\n // The product page renders it with no publish step, so the save\n // carries the site's cache drop with it (AGL-3386).\n await writeSiteWideChange({\n firestore,\n user,\n hostId,\n write: (batch) =>\n batch.set(\n productRef,\n {\n // The seed's holds dropped, the live ones carried, and\n // `deletedAt: null` — the editor edits a LIVE product, and\n // the products table lists only `deletedAt == null`\n // (AGL-3321).\n ...CommerceModel.productEditWrite(base, liveHolds),\n ...membership,\n updatedAt: Timestamp.now(),\n },\n { merge: false },\n ),\n })\n } else {\n // New product rides the quota-enforcing resources API (AGL-473) —\n // it re-checks the `commerce` entitlement and productsPerHost.\n await createHostResource({\n hostId,\n resource: 'product',\n data: { ...base, ...membership, createdAtMs: Date.now() },\n })\n }\n },\n )\n // A refusal leaves the editor open with every field as edited. Closing\n // it would discard the work AND look like a save that succeeded.\n if (!verdict.ok) {\n return void enqueueSnackbar(verdict.message, {\n variant: 'warning',\n persist: false,\n })\n }\n onClose()\n enqueueSnackbar('Product saved', { variant: 'success', persist: false })\n } catch (saveError: any) {\n console.error(saveError)\n enqueueSnackbar(saveError?.message ?? 'An error has occurred', {\n variant: 'error',\n allowDuplicate: true,\n })\n }\n }, [\n user,\n current,\n error,\n product,\n seedFromCache,\n seedUnreadable,\n firestore,\n hostId,\n createHostResource,\n onClose,\n enqueueSnackbar,\n ])\n\n\n return (\n <Dialog open={open} onClose={onClose} maxWidth=\"md\" fullWidth>\n <DialogTitle>{product ? 'Edit product' : 'Add product'}</DialogTitle>\n <DialogContent sx={{ display: 'flex', flexDirection: 'column', gap: 2 }}>\n <ProductBasicsFields\n name={current.name}\n slug={current.slug}\n type={current.type}\n status={current.status}\n supplierId={current.supplierId}\n description={current.description ?? ''}\n suppliers={suppliers.rows}\n onName={handleName}\n onSlug={handleSlug}\n update={update}\n />\n <ProductChipsField<string>\n freeSolo\n label=\"Tags\"\n placeholder=\"Type and press Enter\"\n options={NO_ITEMS}\n value={current.tags ?? NO_ITEMS}\n onChange={setTags}\n />\n {categories.rows.length > 0 ? (\n <ProductChipsField<any>\n label=\"Categories\"\n options={categories.rows}\n getOptionLabel={categoryLabel}\n isOptionEqualToValue={sameRecord}\n value={pickedCategories}\n onChange={setCategories}\n />\n ) : null}\n {/*\n The product zone (AGL-2916), hosted like the listing zone below: a\n widget proposes copy from what this product says and shows, staged in\n the fields above like typing. Save product is still the only write.\n */}\n {WidgetSlot ? (\n <HostedZone\n renderer={WidgetSlot}\n slot={PRODUCT_EDITOR_ZONE.id}\n hostId={hostId}\n orgId={undefined}\n product={zoneProduct}\n categories={zoneCategories}\n proposeValues={proposeProductValues}\n />\n ) : null}\n\n <Divider textAlign=\"left\">{'Media'}</Divider>\n <ProductMediaFields\n mediaUrls={current.mediaUrls ?? NO_ITEMS}\n update={update}\n pick={pick}\n />\n\n <Divider textAlign=\"left\">{'Options & variants'}</Divider>\n <ProductOptionsFields\n options={current.options ?? NO_OPTIONS}\n onChange={handleOptionsChange}\n onValues={setOptionValues}\n />\n <ProductVariantsTable\n variants={current.variants}\n stockApplies={stockApplies}\n onField={handleVariantField}\n />\n {CommerceModel.productPriceMissing(current) ? (\n <Alert severity=\"warning\">{PRODUCT_PRICE_EMPTY_NOTICE}</Alert>\n ) : null}\n <Typography variant=\"caption\" color=\"text.secondary\">\n {stockApplies\n ? 'Blank stock = untracked; 0 shows sold out. The first variant’s ' +\n 'price feeds legacy Product blocks.'\n : 'Stock is not tracked on a digital or service subscription — ' +\n 'nothing decrements it, on the first charge or on any renewal. ' +\n 'A physical subscription decrements per cycle, and “Both — ' +\n 'buyer chooses” tracks the one-time sales. The first variant’s ' +\n 'price feeds legacy Product blocks.'}\n </Typography>\n {strandedStock != null ? (\n <Alert\n severity=\"warning\"\n action={\n <Button size=\"small\" onClick={handleClearStockTracking}>\n {'Clear stock'}\n </Button>\n }\n >\n {`This product still has stock set (${strandedStock}), but a ` +\n 'digital or service subscription never decrements it — not the ' +\n 'first charge, not any renewal — so the number will not change ' +\n 'on its own and does not cap subscribers. It is kept, not ' +\n 'deleted: a stored 0 still blocks new subscribers, and the ' +\n 'value becomes editable again if you switch Billing back to ' +\n 'one-time or “Both”, or the Type to physical.'}\n </Alert>\n ) : null}\n {/* One linked upsell for both locked selectors (AGL-2080). The\n helper text under each control names the plan, but a disabled\n MenuItem is only visible with the menu open and neither is a\n path anywhere — the retention directive wants the upgrade\n prominent and one-click, so the link lives here, beside the\n controls it unlocks. */}\n {subsLocked || giftsLocked ? (\n <EntitlementUpsell\n planLabel={undefined}\n upgradeHref={subsLocked ? subs.upgradeHref : gifts.upgradeHref}\n >\n {subsLocked && giftsLocked\n ? `Subscription products (${subs.planLabel ?? 'higher plan'}) ` +\n `and gift cards (${gifts.planLabel ?? 'higher plan'}) are ` +\n 'not on your plan. You can still save this product — those ' +\n 'two options stay locked until you upgrade.'\n : subsLocked\n ? `Subscription products are on ${subs.planLabel ?? 'a higher plan'}. ` +\n 'A subscription saved without it is refused at checkout, ' +\n 'so the option stays locked here instead.'\n : `Gift cards are on ${gifts.planLabel ?? 'a higher plan'}. ` +\n 'A gift-card product saved without it is refused at ' +\n 'checkout, so the option stays locked here instead.'}\n </EntitlementUpsell>\n ) : null}\n <ProductSellingFields\n oversellPolicy={current.oversellPolicy ?? 'deny'}\n giftCard={Boolean(current.giftCard)}\n taxExempt={Boolean(current.taxExempt)}\n lowStockThreshold={current.lowStockThreshold}\n stockApplies={stockApplies}\n giftsLocked={giftsLocked}\n giftsPlanLabel={gifts.planLabel}\n update={update}\n />\n <ProductBillingFields\n subscription={current.subscription}\n subscriptionOptional={current.subscriptionOptional}\n subsLocked={subsLocked}\n subsPlanLabel={subs.planLabel}\n update={update}\n replaceDraft={replaceDraft}\n />\n {pos.ready && pos.entitled ? (\n <ProductRegisterFields\n posQuickKey={Boolean(current.posQuickKey)}\n modifierGroups={current.modifierGroups ?? NO_MODIFIER_GROUPS}\n update={update}\n />\n ) : pos.ready ? (\n <EntitlementUpsell planLabel={pos.planLabel} upgradeHref={pos.upgradeHref}>\n {'Register quick keys and modifier groups (sizes, add-ons) come with the point of sale.'}\n </EntitlementUpsell>\n ) : null}\n {current.type === 'digital' ? (\n <ProductDigitalFields\n hostId={hostId}\n productId={product?.$id}\n digitalFiles={current.digitalFiles ?? NO_FILES}\n downloadLimit={current.downloadLimit}\n gatedVideos={current.gatedVideos ?? NO_VIDEOS}\n update={update}\n />\n ) : null}\n\n <ProductChipsField<any>\n label=\"Related products (upsells)\"\n helperText=\"Shown by the Related products block; blank falls back to frequently-bought-together\"\n options={relatedOptions}\n getOptionLabel={recordLabel}\n isOptionEqualToValue={sameRecord}\n value={pickedRelated}\n onChange={setRelatedProducts}\n />\n\n <ProductSeoFields\n title={current.seo?.title}\n description={current.seo?.description}\n hasImage={Boolean(current.seo?.imageUrl)}\n update={update}\n pick={pick}\n />\n {/*\n The search listing zone (AGL-2910), hosted here through the shell's\n renderer: a plugin's dialog cannot mount the console's slot itself.\n A widget proposes a title and a description from what this product\n says; they are staged in the fields above like typing, and Save\n product is still the only write.\n */}\n {WidgetSlot ? (\n <HostedZone\n renderer={WidgetSlot}\n slot=\"seoFields\"\n hostId={hostId}\n orgId={undefined}\n orgSlug=\"\"\n subject={seoSubject}\n fields={PRODUCT_SEO_LISTING_FIELDS}\n values={seoValues}\n hasImage={Boolean(current.seo?.imageUrl)}\n proposeValues={proposeSeoValues}\n />\n ) : null}\n\n {error ? <Alert severity=\"warning\">{error}</Alert> : null}\n {product?.$id ? (\n <Typography variant=\"caption\" color=\"text.secondary\">\n {`id: ${product.$id}`}\n </Typography>\n ) : null}\n </DialogContent>\n <DialogActions>\n <Button onClick={onClose}>{'Cancel'}</Button>\n <Button\n variant=\"contained\"\n color=\"primary\"\n disabled={!current.name.trim() || Boolean(error)}\n onClick={handleSave}\n >\n {'Save product'}\n </Button>\n </DialogActions>\n </Dialog>\n )\n}\nProductEditorDialog.displayName = 'ProductEditorDialog'\n\nexport default ProductEditorDialog\n"],"names":["CommerceModel","useSnackbar","Timestamp","Alert","Autocomplete","Box","Button","Dialog","DialogActions","DialogContent","DialogTitle","Divider","IconButton","MenuItem","Stack","TableBody","TableCell","TableHead","TableRow","TextField","Typography","collection","doc","getDoc","ScanAdornment","productCollectionFields","memo","useCallback","useMemo","useRef","useState","ceilingedWindow","collectionCeiling","useFirestore","useFirestoreCollection","useHostResourceApi","writeGuardedBySeed","useUser","writeSiteWideChange","useMediaPicker","useConsoleWidgetSlot","seoListingFieldCount","seoListingFieldTooLong","ScrollTable","useContentStable","EntitlementUpsell","useCommerceEntitlement","PRODUCT_EDITOR_ZONE","MembersVideosField","PaidDownloadAddButton","PaidMediaProtection","ProductRegisterFields","CATEGORY_CEILING","RELATED_PRODUCT_CEILING","SUPPLIER_CEILING","PRODUCT_SEO_LISTING_FIELDS","blankProduct","name","slug","type","status","variants","id","priceUsd","COMMERCE_DEFAULT_PRICE_USD","PRODUCT_PRICE_EMPTY_NOTICE","comboKey","options","Object","entries","sort","a","b","localeCompare","map","value","join","comboLabel","values","length","NO_ITEMS","NO_OPTIONS","NO_FILES","NO_VIDEOS","FILL_ROW","flex","categoryLabel","category","recordLabel","item","$id","sameRecord","option","ProductChipsField","props","index","onChange","multiple","freeSolo","getOptionLabel","isOptionEqualToValue","_event","next","renderInput","params","label","size","placeholder","helperText","sx","fill","undefined","NO_MODIFIER_GROUPS","MemoTextField","FIRST_ROW","mt","WIDE_ROW","xs","sm","NARROW_SELECT","minWidth","SUPPLIER_SELECT","OVERSELL_SELECT","KIND_SELECT","SHORT_SELECT","BILLING_SELECT","COUNT_FIELD","width","VERSION_FIELD","OPTION_FIELD","PRICE_CELL","CODE_CELL","BARCODE_CELL","STOCK_CELL","DECIMAL_INPUT","htmlInput","inputMode","NUMERIC_INPUT","TYPE_MENU","STATUS_MENU","OVERSELL_MENU","TAX_MENU","INTERVAL_MENU","HostedZone","renderer","Renderer","zone","ProductBasicsFields","suppliers","update","setType","event","target","setStatus","setSupplier","supplierId","setDescription","description","supplierMenu","supplier","direction","spacing","onName","autoFocus","fullWidth","onSlug","select","multiline","minRows","ProductMediaFields","mediaUrls","pick","display","gap","flexWrap","url","position","component","src","alt","height","objectFit","borderRadius","border","borderColor","aria-label","onClick","product","filter","_item","itemIndex","top","right","bgcolor","p","media","ProductOptionRow","onValues","setName","alignItems","color","ProductOptionsFields","COMMERCE_MAX_OPTIONS","alignSelf","ProductVariantRow","variant","stockApplies","onField","set","cell","field","compareAtPriceUsd","sku","barcode","inventory","weightGrams","stockInput","barcodeInput","input","endAdornment","onScan","code","whiteSpace","variantHasPrice","focused","slotProps","disabled","VARIANTS_HEAD","ProductVariantsTable","ProductSellingFields","giftsLocked","giftsPlanLabel","setOversellPolicy","oversellPolicy","setKind","giftCard","setTax","taxExempt","setLowStock","raw","trim","lowStockThreshold","Math","max","round","Number","kindMenu","ProductBillingFields","subscription","subscriptionOptional","subsLocked","replaceDraft","setBilling","interval","setBillingInterval","setTrialDays","trialDays","billingMenu","subsPlanLabel","DigitalFileRow","file","setVersion","version","slice","digitalFiles","noWrap","fileName","hostId","productId","kind","MemoMembersVideosField","MemoPaidDownloadAddButton","ProductDigitalFields","addFile","setDownloadLimit","downloadLimit","setVideos","gatedVideos","textAlign","onAdd","videos","ProductSeoFields","title","setTitle","seo","error","imageUrl","hasImage","ProductEditorDialog","draft","current","subs","gifts","seedFromCache","seedUnreadable","open","onClose","pos","ready","entitled","firestore","data","user","createHostResource","enqueueSnackbar","categoryDocs","idField","allProductDocs","supplierDocs","categories","relatedProducts","lifted","liftLegacyProduct","setDraft","slugTouched","setSlugTouched","pickMedia","apply","latest","build","patch","at","setTags","tags","tag","String","Boolean","setCategories","picked","categoryIds","setRelatedProducts","relatedProductIds","pickedCategories","rows","includes","relatedOptions","deletedAt","pickedRelated","WidgetSlot","proposeSeoValues","staged","keys","prior","base","proposeProductValues","productCopyPatch","zoneCategories","zoneProduct","seoTitle","seoDescription","shipping","lengthCm","widthCm","heightCm","hsCode","originCountry","channel","brand","gtin","mpn","condition","googleProductCategory","seoSubject","seoValues","validateProduct","stockTrackingApplies","strandedStock","productInventory","handleClearStockTracking","inventoryByLocation","_perLocation","rest","handleName","commerceSlug","handleSlug","handleOptionsChange","renameProductOptions","optionIndex","splice","previous","Map","fallback","expandVariantMatrix","combo","comboIndex","existing","get","Date","now","toString","setOptionValues","handleVariantField","numeric","handleSave","productSaveFields","verdict","subject","unreadable","fromCache","membership","productMembershipInput","productRef","stored","catch","Error","liveHolds","write","batch","productEditWrite","updatedAt","merge","resource","createdAtMs","ok","message","persist","saveError","console","allowDuplicate","maxWidth","flexDirection","slot","orgId","proposeValues","productPriceMissing","severity","action","planLabel","upgradeHref","posQuickKey","modifierGroups","orgSlug","fields","displayName"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../../../../../libs/plugins/commerce/src/lib/components/console/product-editor-dialog.component.tsx"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n'use client'\n\nimport * as CommerceModel from '../../model'\nimport { useSnackbar } from '@aglyn/shared-ui-snackstack'\nimport { Timestamp } from '@aglyn/shared-util-timestamp'\nimport {\n Alert,\n Autocomplete,\n Box,\n Button,\n Dialog,\n DialogActions,\n DialogContent,\n DialogTitle,\n Divider,\n IconButton,\n MenuItem,\n Stack,\n TableBody,\n TableCell,\n TableHead,\n TableRow,\n TextField,\n Typography,\n} from '@mui/material'\nimport { collection, doc, getDoc } from 'firebase/firestore'\nimport { ScanAdornment } from '../../barcode/scan-button.component'\nimport { productCollectionFields } from './smart-collections'\nimport { memo, useCallback, useMemo, useRef, useState } from 'react'\nimport {\n ceilingedWindow,\n collectionCeiling,\n useFirestore,\n useFirestoreCollection,\n useHostResourceApi,\n writeGuardedBySeed,\n useUser,\n} from '@aglyn/tenant-feature-instance'\nimport { writeSiteWideChange } from '@aglyn/tenant-feature-instance/hooks/helpers/site-wide-change'\nimport { type PickedMedia, useMediaPicker } from '@aglyn/aglyn'\nimport {\n type ConsoleWidgetSlotRenderer,\n useConsoleWidgetSlot,\n} from '@aglyn/aglyn/app-utils/console-widget-slot-context'\nimport {\n seoListingFieldCount,\n seoListingFieldTooLong,\n type SeoListingFieldKey,\n} from '@aglyn/aglyn/app-utils/seo-listing-fields'\nimport type { ConsoleSeoFieldValues } from '@aglyn/aglyn/plugin-manager/feature-plugins'\nimport { ScrollTable } from '@aglyn/shared-ui-jsx/components/scroll-table.component'\nimport { useContentStable } from '@aglyn/shared-ui-jsx/hooks/use-content-stable'\nimport {\n EntitlementUpsell,\n useCommerceEntitlement,\n} from './entitlement-gate.component'\nimport {\n PRODUCT_EDITOR_ZONE,\n type ConsoleProductCopyValues,\n type ConsoleProductEditorZoneProps,\n} from './product-zones'\nimport {\n type MembersVideo,\n MembersVideosField,\n PaidDownloadAddButton,\n PaidMediaProtection,\n} from './paid-media'\nimport { ProductCheckInFields } from './product-check-in-fields.component'\nimport { ProductRegisterFields, ProductSellOnlineField } from './product-register-fields.component'\n\n/**\n * What each picker in this dialog will offer.\n *\n * Every one is a chooser rather than a list, so the ceiling is the number of\n * options a reader can meaningfully scan, and the walk that reaches it is\n * ordered by document name — a picker that silently omits an option is worse\n * than one that admits it stops, because the omission looks like the option\n * not existing.\n */\nconst CATEGORY_CEILING = 250\nconst RELATED_PRODUCT_CEILING = 300\nconst SUPPLIER_CEILING = 50\n\nexport interface ProductEditorDialogProps {\n hostId: string\n /** Product doc (with `$id`) to edit, `null` for a new product. */\n product: (CommerceModel.HostProduct & { $id: string }) | null\n /**\n * The listener that produced `product` has NOT been confirmed by the\n * server (AGL-1358). Required rather than optional on purpose: the\n * products listener lives in the parent hub card, so this dialog cannot\n * compute the verdict, and an optional prop a caller forgets is a guard\n * that is off while looking present.\n */\n seedFromCache: boolean\n /** That listener FAILED (`status === 'error'`). */\n seedUnreadable?: boolean\n open: boolean\n onClose: () => void\n}\n\n/**\n * The search listing fields this editor holds (AGL-2910): `product.seo`\n * carries a title and a description beside its share image, and nothing\n * else a listing zone may propose.\n */\nconst PRODUCT_SEO_LISTING_FIELDS: readonly Extract<SeoListingFieldKey, 'title' | 'description'>[] = [\n 'title',\n 'description',\n]\n\n/**\n * A product nobody has saved yet, as the editor starts one: at the default\n * price (AGL-3676), for the owner to change or clear.\n */\nfunction blankProduct(): CommerceModel.HostProduct {\n return {\n name: '',\n slug: '',\n type: 'physical',\n status: 'draft',\n variants: [{ id: 'default', priceUsd: CommerceModel.COMMERCE_DEFAULT_PRICE_USD }],\n }\n}\n\n/** What the editor says while a variant has no price (AGL-3676): savable, not sellable. */\nexport const PRODUCT_PRICE_EMPTY_NOTICE =\n 'Visitors will see “Price coming soon” and can’t buy this yet. Set a price to start selling it.'\n\n/** Stable key for matching variants across matrix regenerations. */\nfunction comboKey(options: Record<string, string> | undefined): string {\n return Object.entries(options ?? {})\n .sort(([a], [b]) => a.localeCompare(b))\n .map(([name, value]) => `${name}:${value}`)\n .join('|')\n}\n\nfunction comboLabel(options: Record<string, string> | undefined): string {\n const values = Object.values(options ?? {})\n return values.length ? values.join(' / ') : 'Default'\n}\n\n\n/** Stand-in for a list the product does not hold yet, the same one each render. */\nconst NO_ITEMS: readonly string[] = []\nconst NO_OPTIONS: readonly CommerceModel.ProductOption[] = []\nconst NO_FILES: readonly DigitalFile[] = []\nconst NO_VIDEOS: readonly MembersVideo[] = []\nconst FILL_ROW = { flex: 1 } as const\n\nconst categoryLabel = (category: any): string => category.name\nconst recordLabel = (item: any): string => item.name ?? item.$id\nconst sameRecord = (option: any, value: any): boolean => option.$id === value.$id\n\ninterface ProductChipsFieldProps<T> {\n label: string\n options: readonly T[]\n value: readonly T[]\n /** `index` is the prop of the same name, handed back for a per-row field. */\n onChange(next: T[], index: number): void\n index?: number\n freeSolo?: boolean\n getOptionLabel?: (option: T) => string\n isOptionEqualToValue?: (option: T, value: T) => boolean\n placeholder?: string\n helperText?: string\n fill?: boolean\n}\n\n/**\n * One of the editor's chip lists — tags, categories, an option's values,\n * related products — MEMOIZED, and every prop it takes is stable while its\n * own list is (AGL-3423).\n *\n * A multiple Autocomplete hands its input a new chip array as\n * `startAdornment` on every render, and MUI's `InputBase` copies that into\n * its `FormControl` from a passive effect: a state update left pending after\n * every commit the field takes part in. React 19 counts each such commit as a\n * nested update, and keystrokes delivered back to back commit one after\n * another with nothing to clear the count, so the fifty-first throws\n * \"Maximum update depth exceeded\" (#185). Every field in this editor writes\n * one draft, so every keystroke in any of them re-rendered all four lists;\n * kept out of those renders, a list commits only when it changes.\n */\nconst ProductChipsField = memo(function ProductChipsField<T>(\n props: ProductChipsFieldProps<T>,\n) {\n const { index = 0, onChange } = props\n return (\n <Autocomplete<T, true, false, boolean>\n multiple\n freeSolo={props.freeSolo}\n options={props.options as T[]}\n value={props.value as T[]}\n getOptionLabel={props.getOptionLabel as (option: T | string) => string}\n isOptionEqualToValue={props.isOptionEqualToValue}\n onChange={(_event, next) => onChange(next as T[], index)}\n renderInput={(params) => (\n <TextField\n {...params}\n label={props.label}\n size=\"small\"\n placeholder={props.placeholder}\n helperText={props.helperText}\n />\n )}\n sx={props.fill ? FILL_ROW : undefined}\n />\n )\n}) as <T>(props: ProductChipsFieldProps<T>) => JSX.Element\n\ntype DigitalFile = NonNullable<CommerceModel.HostProduct['digitalFiles']>[number]\n\n/** A change to the product, or a function of the product as it stands. */\ntype ProductPatch =\n | Partial<CommerceModel.HostProduct>\n | ((product: CommerceModel.HostProduct) => Partial<CommerceModel.HostProduct>)\n\n/** Spreads a patch over the draft as last rendered. One identity per dialog. */\ntype ProductUpdate = (patch: ProductPatch) => void\n\n/** A stable empty list, so a product without modifiers never redraws its section. */\nconst NO_MODIFIER_GROUPS: CommerceModel.ProductModifierGroup[] = []\n\n/** Replaces the draft with what `build` makes of it as last rendered. */\ntype DraftReplace = (\n build: (product: CommerceModel.HostProduct) => CommerceModel.HostProduct,\n) => void\n\n/** Opens the media browser and hands what was chosen to `apply`. */\ntype MediaPick = (apply: (media: PickedMedia) => void) => Promise<void>\n\n/** A change to one option, or `null` to remove it. */\ntype OptionChange = (\n index: number,\n patch: Partial<CommerceModel.ProductOption> | null,\n) => void\n\n/** What was typed into one variant's field, as the matrix hands it on. */\ntype VariantFieldChange = (\n index: number,\n field: keyof CommerceModel.ProductVariant,\n raw: string,\n) => void\n\ntype FieldChange = { target: { value: string } }\n\n/**\n * A text field that redraws only when what it shows changes (AGL-3423).\n *\n * Every field in this editor writes one draft, so a keystroke in any of them\n * re-renders the dialog, and drawn whole that is some forty inputs and twelve\n * hundred components for one letter in a product with four variants. When a\n * keystroke costs that much, typed input queues and is processed back to\n * back, which is what lets a chip list's pending update climb to #185 (see\n * `ProductChipsField`). The sections below are memoized on the slice of the\n * draft they show, and each field in them is this, handed a handler and\n * styles that keep their identity, so the keystroke redraws the field it\n * lands in.\n */\nconst MemoTextField = memo(TextField) as typeof TextField\n\nconst FIRST_ROW = { mt: 1 } as const\nconst WIDE_ROW = { xs: 'column', sm: 'row' } as const\nconst NARROW_SELECT = { minWidth: 140 } as const\nconst SUPPLIER_SELECT = { minWidth: 160 } as const\nconst OVERSELL_SELECT = { minWidth: 200 } as const\nconst KIND_SELECT = { minWidth: 130 } as const\nconst SHORT_SELECT = { minWidth: 120 } as const\nconst BILLING_SELECT = { minWidth: 180 } as const\nconst COUNT_FIELD = { width: 140 } as const\nconst VERSION_FIELD = { width: 100 } as const\nconst OPTION_FIELD = { width: 160 } as const\nconst PRICE_CELL = { width: 88 } as const\nconst CODE_CELL = { width: 110 } as const\nconst BARCODE_CELL = { width: 150 } as const\nconst STOCK_CELL = { width: 72 } as const\nconst DECIMAL_INPUT = { htmlInput: { inputMode: 'decimal' } } as const\nconst NUMERIC_INPUT = { htmlInput: { inputMode: 'numeric' } } as const\n\nconst TYPE_MENU = [\n <MenuItem key=\"physical\" value=\"physical\">{'Physical'}</MenuItem>,\n <MenuItem key=\"digital\" value=\"digital\">{'Digital'}</MenuItem>,\n <MenuItem key=\"service\" value=\"service\">{'Service'}</MenuItem>,\n]\nconst STATUS_MENU = [\n <MenuItem key=\"draft\" value=\"draft\">{'Draft'}</MenuItem>,\n <MenuItem key=\"active\" value=\"active\">{'Active'}</MenuItem>,\n <MenuItem key=\"archived\" value=\"archived\">{'Archived'}</MenuItem>,\n]\nconst OVERSELL_MENU = [\n <MenuItem key=\"deny\" value=\"deny\">{'Stop selling (sold out)'}</MenuItem>,\n <MenuItem key=\"backorder\" value=\"backorder\">{'Keep selling (backorder)'}</MenuItem>,\n]\nconst TAX_MENU = [\n <MenuItem key=\"taxable\" value=\"taxable\">{'Taxable'}</MenuItem>,\n <MenuItem key=\"exempt\" value=\"exempt\">{'Tax exempt'}</MenuItem>,\n]\nconst INTERVAL_MENU = [\n <MenuItem key=\"month\" value=\"month\">{'Monthly'}</MenuItem>,\n <MenuItem key=\"year\" value=\"year\">{'Yearly'}</MenuItem>,\n]\n\n/**\n * A zone hosted in the dialog, drawn again only when what it is handed\n * changes (AGL-3423). The shell's renderer is not memoized: drawn straight\n * into the dialog, every widget in the zone would redraw on each keystroke in\n * any field.\n */\nconst HostedZone = memo(function HostedZone(\n props: { renderer: ConsoleWidgetSlotRenderer; slot: string } & Record<string, unknown>,\n) {\n const { renderer: Renderer, ...zone } = props\n return <Renderer {...zone} />\n})\n\ninterface ProductBasicsFieldsProps {\n name: string\n slug: string\n type: CommerceModel.ProductType\n status: CommerceModel.ProductStatus\n supplierId: string | undefined\n description: string\n suppliers: readonly any[]\n onName(event: FieldChange): void\n onSlug(event: FieldChange): void\n update: ProductUpdate\n}\n\n/** The product's name and address, type, status, supplier and description. */\nconst ProductBasicsFields = memo(function ProductBasicsFields(\n props: ProductBasicsFieldsProps,\n) {\n const { suppliers, update } = props\n const setType = useCallback(\n (event: FieldChange) =>\n update({ type: event.target.value as CommerceModel.ProductType }),\n [update],\n )\n const setStatus = useCallback(\n (event: FieldChange) =>\n update({ status: event.target.value as CommerceModel.ProductStatus }),\n [update],\n )\n const setSupplier = useCallback(\n (event: FieldChange) => update({ supplierId: event.target.value || undefined }),\n [update],\n )\n const setDescription = useCallback(\n (event: FieldChange) => update({ description: event.target.value }),\n [update],\n )\n const supplierMenu = useMemo(\n () => [\n <MenuItem key=\"\" value=\"\">\n {'None (self-fulfilled)'}\n </MenuItem>,\n ...suppliers.map((supplier: any) => (\n <MenuItem key={supplier.$id} value={supplier.$id}>\n {supplier.name}\n </MenuItem>\n )),\n ],\n [suppliers],\n )\n return (\n <>\n <Stack direction={WIDE_ROW} spacing={2} sx={FIRST_ROW}>\n <MemoTextField\n label=\"Name\"\n value={props.name}\n onChange={props.onName}\n size=\"small\"\n autoFocus\n fullWidth\n />\n <MemoTextField\n label=\"Slug\"\n value={props.slug}\n onChange={props.onSlug}\n size=\"small\"\n fullWidth\n helperText={props.slug ? `/products/${props.slug}` : undefined}\n />\n </Stack>\n <Stack direction=\"row\" spacing={2}>\n <MemoTextField\n label=\"Type\"\n value={props.type}\n onChange={setType}\n size=\"small\"\n select\n sx={NARROW_SELECT}\n >\n {TYPE_MENU}\n </MemoTextField>\n <MemoTextField\n label=\"Status\"\n value={props.status}\n onChange={setStatus}\n size=\"small\"\n select\n sx={NARROW_SELECT}\n >\n {STATUS_MENU}\n </MemoTextField>\n {suppliers.length > 0 ? (\n <MemoTextField\n label=\"Supplier\"\n value={props.supplierId ?? ''}\n onChange={setSupplier}\n size=\"small\"\n select\n sx={SUPPLIER_SELECT}\n helperText=\"Routes paid orders\"\n >\n {supplierMenu}\n </MemoTextField>\n ) : null}\n </Stack>\n <MemoTextField\n label=\"Description\"\n value={props.description}\n onChange={setDescription}\n size=\"small\"\n multiline\n minRows={2}\n />\n </>\n )\n})\n\n/** The product's images, each removable, and the button that adds one. */\nconst ProductMediaFields = memo(function ProductMediaFields(props: {\n mediaUrls: readonly string[]\n update: ProductUpdate\n pick: MediaPick\n}) {\n const { mediaUrls, update, pick } = props\n return (\n <Box sx={{ display: 'flex', gap: 1, flexWrap: 'wrap' }}>\n {mediaUrls.map((url, index) => (\n <Box key={`${url}-${index}`} sx={{ position: 'relative' }}>\n <Box\n component=\"img\"\n src={url}\n alt=\"\"\n sx={{\n width: 72,\n height: 72,\n objectFit: 'cover',\n borderRadius: 1,\n border: 1,\n borderColor: 'divider',\n }}\n />\n <IconButton\n size=\"small\"\n aria-label=\"Remove image\"\n onClick={() =>\n update((product) => ({\n mediaUrls: (product.mediaUrls ?? []).filter(\n (_item, itemIndex) => itemIndex !== index,\n ),\n }))\n }\n sx={{\n position: 'absolute',\n top: -8,\n right: -8,\n bgcolor: 'background.paper',\n border: 1,\n borderColor: 'divider',\n p: 0.25,\n }}\n >\n {'✕'}\n </IconButton>\n </Box>\n ))}\n <Button\n size=\"small\"\n onClick={() =>\n void pick((media) =>\n update((product) => ({\n mediaUrls: [...(product.mediaUrls ?? []), media.url],\n })),\n )\n }\n >\n {'Add image'}\n </Button>\n </Box>\n )\n})\n\nconst ProductOptionRow = memo(function ProductOptionRow(props: {\n index: number\n option: CommerceModel.ProductOption\n onChange: OptionChange\n onValues(values: string[], index: number): void\n}) {\n const { index, option, onChange, onValues } = props\n const setName = useCallback(\n (event: FieldChange) => onChange(index, { name: event.target.value }),\n [index, onChange],\n )\n return (\n <Stack direction=\"row\" spacing={1} sx={{ alignItems: 'flex-start' }}>\n <MemoTextField\n label=\"Option\"\n value={option.name}\n onChange={setName}\n size=\"small\"\n sx={OPTION_FIELD}\n placeholder=\"Size\"\n />\n <ProductChipsField<string>\n freeSolo\n fill\n label=\"Values\"\n placeholder=\"S, M, L…\"\n options={NO_ITEMS}\n value={option.values}\n index={index}\n onChange={onValues}\n />\n <Button\n size=\"small\"\n color=\"error\"\n onClick={() => onChange(index, null)}\n sx={{ mt: 0.5 }}\n >\n {'Remove'}\n </Button>\n </Stack>\n )\n})\n\n/** The product's options, one row each, and the button that adds one. */\nconst ProductOptionsFields = memo(function ProductOptionsFields(props: {\n options: readonly CommerceModel.ProductOption[]\n onChange: OptionChange\n onValues(values: string[], index: number): void\n}) {\n const { options, onChange, onValues } = props\n return (\n <>\n {options.map((option, index) => (\n <ProductOptionRow\n key={index}\n index={index}\n option={option}\n onChange={onChange}\n onValues={onValues}\n />\n ))}\n {options.length < CommerceModel.COMMERCE_MAX_OPTIONS ? (\n <Button\n size=\"small\"\n sx={{ alignSelf: 'flex-start' }}\n onClick={() => onChange(options.length, { name: '', values: [] })}\n >\n {'Add option'}\n </Button>\n ) : null}\n </>\n )\n})\n\nconst ProductVariantRow = memo(function ProductVariantRow(props: {\n index: number\n variant: CommerceModel.ProductVariant\n stockApplies: boolean\n onField: VariantFieldChange\n}) {\n const { index, variant, stockApplies, onField } = props\n const label = comboLabel(variant.options)\n // One handler per cell, each keeping its identity while the row's does.\n const set = useMemo(() => {\n const cell =\n (field: keyof CommerceModel.ProductVariant) => (event: FieldChange) =>\n onField(index, field, event.target.value)\n return {\n priceUsd: cell('priceUsd'),\n compareAtPriceUsd: cell('compareAtPriceUsd'),\n sku: cell('sku'),\n barcode: cell('barcode'),\n inventory: cell('inventory'),\n weightGrams: cell('weightGrams'),\n }\n }, [index, onField])\n const stockInput = useMemo(\n () => ({\n htmlInput: {\n inputMode: 'numeric' as const,\n 'aria-label': `Stock — ${label}`,\n },\n }),\n [label],\n )\n // A camera scan fills the barcode the same way typing it does (AGL-3619).\n const barcodeInput = useMemo(\n () => ({\n htmlInput: { 'aria-label': `Barcode — ${label}` },\n input: {\n endAdornment: (\n <ScanAdornment\n label={`Scan the barcode for ${label}`}\n onScan={(code) => onField(index, 'barcode', code)}\n />\n ),\n },\n }),\n [label, index, onField],\n )\n return (\n <TableRow>\n <TableCell sx={{ whiteSpace: 'nowrap' }}>{label}</TableCell>\n <TableCell>\n <MemoTextField\n value={variant.priceUsd ?? ''}\n onChange={set.priceUsd}\n size=\"small\"\n sx={PRICE_CELL}\n // An empty price is marked (AGL-2916), gently (AGL-3676): the\n // product saves without one, and the storefront says \"Price\n // coming soon\" and sells it nowhere.\n color={CommerceModel.variantHasPrice(variant) ? undefined : 'warning'}\n focused={CommerceModel.variantHasPrice(variant) ? undefined : true}\n placeholder=\"Set\"\n slotProps={DECIMAL_INPUT}\n />\n </TableCell>\n <TableCell>\n <MemoTextField\n value={variant.compareAtPriceUsd ?? ''}\n onChange={set.compareAtPriceUsd}\n size=\"small\"\n sx={PRICE_CELL}\n slotProps={DECIMAL_INPUT}\n />\n </TableCell>\n <TableCell>\n <MemoTextField\n value={variant.sku ?? ''}\n onChange={set.sku}\n size=\"small\"\n sx={CODE_CELL}\n />\n </TableCell>\n <TableCell>\n <MemoTextField\n value={variant.barcode ?? ''}\n onChange={set.barcode}\n size=\"small\"\n sx={BARCODE_CELL}\n slotProps={barcodeInput}\n />\n </TableCell>\n <TableCell>\n <MemoTextField\n value={variant.inventory ?? ''}\n placeholder={stockApplies ? '—' : 'n/a'}\n disabled={!stockApplies}\n onChange={set.inventory}\n size=\"small\"\n sx={STOCK_CELL}\n slotProps={stockInput}\n />\n </TableCell>\n <TableCell>\n <MemoTextField\n value={variant.weightGrams ?? ''}\n onChange={set.weightGrams}\n size=\"small\"\n sx={PRICE_CELL}\n slotProps={NUMERIC_INPUT}\n />\n </TableCell>\n </TableRow>\n )\n})\n\n/** The matrix's column headings, one element for every render. */\nconst VARIANTS_HEAD = (\n <TableHead>\n <TableRow>\n <TableCell>{'Variant'}</TableCell>\n <TableCell>{'Price ($)'}</TableCell>\n <TableCell>{'Compare-at'}</TableCell>\n <TableCell>{'SKU'}</TableCell>\n <TableCell>{'Barcode'}</TableCell>\n <TableCell>{'Stock'}</TableCell>\n <TableCell>{'Weight (g)'}</TableCell>\n </TableRow>\n </TableHead>\n)\n\n/**\n * The variants matrix: one row per combination of the options above, each\n * with its own price, SKU, barcode, stock and weight. A keystroke in one row\n * leaves the others' props as they were.\n */\nconst ProductVariantsTable = memo(function ProductVariantsTable(props: {\n variants: readonly CommerceModel.ProductVariant[]\n stockApplies: boolean\n onField: VariantFieldChange\n}) {\n const { variants, stockApplies, onField } = props\n return (\n <Box>\n <ScrollTable size=\"small\">\n {VARIANTS_HEAD}\n <TableBody>\n {variants.map((variant, index) => (\n <ProductVariantRow\n key={variant.id}\n index={index}\n variant={variant}\n stockApplies={stockApplies}\n onField={onField}\n />\n ))}\n </TableBody>\n </ScrollTable>\n </Box>\n )\n})\n\n/** What happens when stock runs out, the gift-card kind, tax, and the low-stock alert. */\nconst ProductSellingFields = memo(function ProductSellingFields(props: {\n oversellPolicy: 'deny' | 'backorder'\n giftCard: boolean\n taxExempt: boolean\n lowStockThreshold: number | undefined\n stockApplies: boolean\n giftsLocked: boolean\n giftsPlanLabel: string | undefined\n update: ProductUpdate\n}) {\n const { giftsLocked, giftsPlanLabel, update } = props\n const setOversellPolicy = useCallback(\n (event: FieldChange) =>\n update({ oversellPolicy: event.target.value as 'deny' | 'backorder' }),\n [update],\n )\n const setKind = useCallback(\n (event: FieldChange) => update({ giftCard: event.target.value === 'gift' }),\n [update],\n )\n const setTax = useCallback(\n (event: FieldChange) => update({ taxExempt: event.target.value === 'exempt' }),\n [update],\n )\n const setLowStock = useCallback(\n (event: FieldChange) => {\n const raw = event.target.value.trim()\n update({\n lowStockThreshold:\n raw === '' ? undefined : Math.max(0, Math.round(Number(raw))),\n })\n },\n [update],\n )\n const kindMenu = useMemo(\n () => [\n <MenuItem key=\"standard\" value=\"standard\">\n {'Standard'}\n </MenuItem>,\n // Disabled, never removed (AGL-2080). A product saved as a gift\n // card before the plan lapsed still has `giftCard: true`, and a\n // MUI select whose value is absent from its options renders\n // blank — the next edit would silently rewrite the product to\n // Standard. Locking the option refuses NEW configuration\n // without rewriting existing data.\n <MenuItem value=\"gift\" key=\"gift\" disabled={giftsLocked}>\n {giftsLocked ? `Gift card — ${giftsPlanLabel ?? 'upgrade'} plan` : 'Gift card'}\n </MenuItem>,\n ],\n [giftsLocked, giftsPlanLabel],\n )\n return (\n <Stack direction=\"row\" spacing={2}>\n <MemoTextField\n label=\"When out of stock\"\n value={props.oversellPolicy}\n onChange={setOversellPolicy}\n size=\"small\"\n select\n sx={OVERSELL_SELECT}\n >\n {OVERSELL_MENU}\n </MemoTextField>\n <MemoTextField\n label=\"Kind\"\n value={props.giftCard ? 'gift' : 'standard'}\n onChange={setKind}\n size=\"small\"\n select\n sx={KIND_SELECT}\n helperText={\n giftsLocked\n ? `Gift cards are on ${giftsPlanLabel ?? 'a higher plan'}`\n : 'Gift cards issue a code'\n }\n >\n {kindMenu}\n </MemoTextField>\n <MemoTextField\n label=\"Tax\"\n value={props.taxExempt ? 'exempt' : 'taxable'}\n onChange={setTax}\n size=\"small\"\n select\n sx={SHORT_SELECT}\n >\n {TAX_MENU}\n </MemoTextField>\n <MemoTextField\n label=\"Low-stock alert at\"\n value={props.lowStockThreshold ?? ''}\n placeholder=\"Off\"\n disabled={!props.stockApplies}\n onChange={setLowStock}\n size=\"small\"\n sx={COUNT_FIELD}\n slotProps={NUMERIC_INPUT}\n helperText=\"Notifies managers\"\n />\n </Stack>\n )\n})\n\n/** One-time or subscription billing, its interval, and a free trial. */\nconst ProductBillingFields = memo(function ProductBillingFields(props: {\n subscription: CommerceModel.HostProduct['subscription']\n subscriptionOptional: boolean | undefined\n subsLocked: boolean\n subsPlanLabel: string | undefined\n update: ProductUpdate\n replaceDraft: DraftReplace\n}) {\n const { subscription, subscriptionOptional, subsLocked, update, replaceDraft } =\n props\n const setBilling = useCallback(\n (event: FieldChange) => {\n const value = event.target.value\n // `replaceDraft`, not `update`: a patch is spread over the draft,\n // which would resurrect the keys deleted below.\n replaceDraft((product) => {\n // \"Both\" (AGL-545): the PDP offers one-time OR subscribe at\n // the same price; the interval field beside picks the cadence.\n // Cleared keys are deleted (not set undefined) so the\n // client-direct setDoc on save never sees undefined values.\n const next = { ...product }\n if (value === 'once') {\n delete next.subscription\n } else {\n next.subscription = {\n ...(product.subscription ?? {}),\n interval:\n value === 'both'\n ? (product.subscription?.interval ?? 'month')\n : (value as 'month' | 'year'),\n }\n }\n if (value === 'both') next.subscriptionOptional = true\n else delete next.subscriptionOptional\n return next\n })\n },\n [replaceDraft],\n )\n const setBillingInterval = useCallback(\n (event: FieldChange) => {\n const interval = event.target.value as 'month' | 'year'\n update((product) => ({\n subscription: { ...product.subscription!, interval },\n }))\n },\n [update],\n )\n const setTrialDays = useCallback(\n (event: FieldChange) => {\n const raw = event.target.value.trim()\n update((product) => ({\n subscription: {\n ...product.subscription!,\n ...(raw === ''\n ? { trialDays: undefined }\n : { trialDays: Math.max(1, Math.round(Number(raw))) }),\n },\n }))\n },\n [update],\n )\n const billingMenu = useMemo(\n () => [\n <MenuItem key=\"once\" value=\"once\">\n {'One-time purchase'}\n </MenuItem>,\n // Same rule as the gift-card option: disabled, not removed, so an\n // existing subscription product keeps its interval instead of being\n // silently reset to one-time.\n <MenuItem value=\"month\" key=\"month\" disabled={subsLocked}>\n {'Monthly subscription'}\n </MenuItem>,\n <MenuItem value=\"year\" key=\"year\" disabled={subsLocked}>\n {'Yearly subscription'}\n </MenuItem>,\n <MenuItem value=\"both\" key=\"both\" disabled={subsLocked}>\n {'Both — buyer chooses'}\n </MenuItem>,\n ],\n [subsLocked],\n )\n return (\n <Stack direction=\"row\" spacing={2}>\n <MemoTextField\n label=\"Billing\"\n value={\n subscription\n ? subscriptionOptional\n ? 'both'\n : subscription.interval\n : 'once'\n }\n onChange={setBilling}\n size=\"small\"\n select\n sx={BILLING_SELECT}\n helperText={\n subsLocked\n ? `Subscriptions are on ${props.subsPlanLabel ?? 'a higher plan'}`\n : 'Subscriptions bill until canceled'\n }\n >\n {billingMenu}\n </MemoTextField>\n {subscription && subscriptionOptional ? (\n <MemoTextField\n label=\"Interval\"\n value={subscription.interval}\n onChange={setBillingInterval}\n size=\"small\"\n select\n sx={SHORT_SELECT}\n >\n {INTERVAL_MENU}\n </MemoTextField>\n ) : null}\n {subscription ? (\n <MemoTextField\n label=\"Free trial (days)\"\n placeholder=\"None\"\n value={subscription.trialDays ?? ''}\n onChange={setTrialDays}\n size=\"small\"\n sx={COUNT_FIELD}\n slotProps={NUMERIC_INPUT}\n />\n ) : null}\n </Stack>\n )\n})\n\nconst DigitalFileRow = memo(function DigitalFileRow(props: {\n index: number\n file: DigitalFile\n hostId: string\n productId: string | undefined\n update: ProductUpdate\n}) {\n const { index, file, update } = props\n const setVersion = useCallback(\n (event: FieldChange) => {\n const version = event.target.value.slice(0, 20)\n update((product) => {\n const digitalFiles = [...(product.digitalFiles ?? [])]\n digitalFiles[index] = { ...file, version }\n return { digitalFiles }\n })\n },\n [file, index, update],\n )\n return (\n <Stack direction=\"row\" spacing={1} sx={{ alignItems: 'center' }}>\n <Typography variant=\"body2\" sx={{ flex: 1 }} noWrap>\n {file.fileName}\n {file.version ? ` · v${file.version}` : ''}\n </Typography>\n <PaidMediaProtection\n url={file.url}\n hostId={props.hostId}\n productId={props.productId}\n kind=\"download\"\n />\n <MemoTextField\n label=\"Version\"\n value={file.version ?? ''}\n onChange={setVersion}\n size=\"small\"\n sx={VERSION_FIELD}\n />\n <Button\n size=\"small\"\n color=\"error\"\n onClick={() =>\n update((product) => ({\n digitalFiles: (product.digitalFiles ?? []).filter(\n (_item, itemIndex) => itemIndex !== index,\n ),\n }))\n }\n >\n {'✕'}\n </Button>\n </Stack>\n )\n})\n\n/*\n * The paid-media controls beside the digital fields, drawn again only when\n * what they are handed changes: a keystroke in the download limit leaves the\n * videos, and the protection check on each, as they were.\n */\nconst MemoMembersVideosField = memo(MembersVideosField)\nconst MemoPaidDownloadAddButton = memo(PaidDownloadAddButton)\n\n/** A digital product's files, its download limit and its members videos. */\nconst ProductDigitalFields = memo(function ProductDigitalFields(props: {\n hostId: string\n productId: string | undefined\n digitalFiles: readonly DigitalFile[]\n downloadLimit: number | undefined\n gatedVideos: readonly MembersVideo[]\n update: ProductUpdate\n}) {\n const { hostId, productId, update } = props\n const addFile = useCallback(\n (file: DigitalFile) =>\n update((product) => ({\n digitalFiles: [...(product.digitalFiles ?? []), file],\n })),\n [update],\n )\n const setDownloadLimit = useCallback(\n (event: FieldChange) => {\n const raw = event.target.value.trim()\n update({\n downloadLimit:\n raw === '' ? undefined : Math.max(1, Math.round(Number(raw))),\n })\n },\n [update],\n )\n const setVideos = useCallback(\n (gatedVideos: MembersVideo[]) => update({ gatedVideos }),\n [update],\n )\n return (\n <>\n <Divider textAlign=\"left\">{'Digital delivery'}</Divider>\n {props.digitalFiles.map((file, index) => (\n <DigitalFileRow\n key={index}\n index={index}\n file={file}\n hostId={hostId}\n productId={productId}\n update={update}\n />\n ))}\n <Stack direction=\"row\" spacing={2}>\n {/* Paid downloads are private files delivered through expiring\n links (AGL-2847); adding one makes the file private. */}\n <MemoPaidDownloadAddButton\n hostId={hostId}\n productId={productId}\n onAdd={addFile}\n />\n <MemoTextField\n label=\"Download limit\"\n placeholder=\"Unlimited\"\n value={props.downloadLimit ?? ''}\n onChange={setDownloadLimit}\n size=\"small\"\n sx={COUNT_FIELD}\n slotProps={NUMERIC_INPUT}\n helperText=\"Attempts per order\"\n />\n </Stack>\n <Typography variant=\"caption\" color=\"text.secondary\">\n {'Buyers always download the current files — uploading a new ' +\n 'version re-delivers to everyone.'}\n </Typography>\n {/* Members videos are private files delivered through expiring\n links (AGL-2814); adding one makes the file private. */}\n <MemoMembersVideosField\n hostId={hostId}\n productId={productId}\n videos={props.gatedVideos}\n onChange={setVideos}\n />\n </>\n )\n})\n\n/** The product's search listing: its title, description and share image. */\nconst ProductSeoFields = memo(function ProductSeoFields(props: {\n title: string | undefined\n description: string | undefined\n hasImage: boolean\n update: ProductUpdate\n pick: MediaPick\n}) {\n const { title, description, update, pick } = props\n const setTitle = useCallback(\n (event: FieldChange) => {\n const next = event.target.value\n update((product) => ({ seo: { ...product.seo, title: next } }))\n },\n [update],\n )\n const setDescription = useCallback(\n (event: FieldChange) => {\n const next = event.target.value\n update((product) => ({ seo: { ...product.seo, description: next } }))\n },\n [update],\n )\n return (\n <>\n <Divider textAlign=\"left\">{'Search engine listing'}</Divider>\n <Stack direction={WIDE_ROW} spacing={2}>\n <MemoTextField\n label=\"SEO title\"\n value={title ?? ''}\n onChange={setTitle}\n // The counts every search listing editor prints (AGL-2910): what a\n // search result shows before it truncates.\n helperText={seoListingFieldCount('title', title)}\n error={seoListingFieldTooLong('title', title)}\n size=\"small\"\n fullWidth\n />\n <Button\n size=\"small\"\n onClick={() =>\n void pick((media) =>\n update((product) => ({\n seo: { ...product.seo, imageUrl: media.url },\n })),\n )\n }\n >\n {props.hasImage ? 'Change OG image' : 'OG image'}\n </Button>\n </Stack>\n <MemoTextField\n label=\"SEO description\"\n value={description ?? ''}\n onChange={setDescription}\n helperText={seoListingFieldCount('description', description)}\n error={seoListingFieldTooLong('description', description)}\n size=\"small\"\n multiline\n minRows={2}\n />\n </>\n )\n})\n\n/**\n * Products hub editor (AGL-279): the full catalog editor — basics,\n * media, tags, options → variants matrix, per-variant pricing/stock, and\n * SEO overrides. Saving denormalizes `priceUsd`/`inventory` from the\n * first variant so the legacy Product block + checkout API (AGL-90) keep\n * charging correctly without reading the variants array.\n */\nexport function ProductEditorDialog(props: ProductEditorDialogProps) {\n const { hostId, product, seedFromCache, seedUnreadable, open, onClose } =\n props\n\n /**\n * Field-level entitlement gates (AGL-2080). Both of these were fully\n * configurable by an unentitled org and refused only at checkout — by\n * `server/checkout.ts:149` for subscriptions and `:157` /\n * `cart-checkout.ts:156` for gift cards. The operator saw a saved product;\n * the buyer saw the refusal.\n *\n * `ready && !entitled`, never `!entitled`. `checkEntitlement(undefined)`\n * resolves the FREE tier rather than \"unknown\", so gating on the raw call\n * would disable these controls at a PAYING org for the render or two its\n * org doc is in flight. Erring open for that window costs nothing — the\n * server enforces regardless — while erring closed is a paying customer\n * told they cannot use what they bought.\n */\n const subs = useCommerceEntitlement(hostId, 'storefrontSubscriptions')\n const gifts = useCommerceEntitlement(hostId, 'giftCards')\n // The register settings show only where the plan includes POS (AGL-3607).\n const pos = useCommerceEntitlement(hostId, 'pos')\n const subsLocked = subs.ready && !subs.entitled\n const giftsLocked = gifts.ready && !gifts.entitled\n const firestore = useFirestore()\n const { data: user } = useUser()\n const createHostResource = useHostResourceApi()\n const { enqueueSnackbar } = useSnackbar()\n /**\n * The three pickers this dialog draws, read only once it is OPEN.\n *\n * `ProductEditorDialog` is rendered unconditionally by the products hub and\n * takes `open` as a prop, so its body runs on every render of that page. A\n * listener built here without the gate subscribes whether or not anyone\n * opens the editor, which charges every visit to the catalog for three\n * collections the visitor never sees.\n *\n * `null` is what `useFirestoreCollection` takes to mean \"do not subscribe\",\n * so the closed dialog costs nothing and the open one pays once.\n */\n const { data: categoryDocs } = useFirestoreCollection<any>(\n () =>\n open\n ? collectionCeiling(\n collection(firestore, 'hosts', hostId, 'productCategories'),\n CATEGORY_CEILING,\n )\n : null,\n [firestore, hostId, open],\n { idField: '$id' },\n )\n const { data: allProductDocs } = useFirestoreCollection<any>(\n () =>\n open\n ? collectionCeiling(\n collection(firestore, 'hosts', hostId, 'products'),\n RELATED_PRODUCT_CEILING,\n )\n : null,\n [firestore, hostId, open],\n { idField: '$id' },\n )\n const { data: supplierDocs } = useFirestoreCollection<any>(\n () =>\n open\n ? collectionCeiling(\n collection(firestore, 'hosts', hostId, 'suppliers'),\n SUPPLIER_CEILING,\n )\n : null,\n [firestore, hostId, open],\n { idField: '$id' },\n )\n const categories = useMemo(\n () => ceilingedWindow<any>(categoryDocs ?? undefined, CATEGORY_CEILING),\n [categoryDocs],\n )\n const relatedProducts = useMemo(\n () =>\n ceilingedWindow<any>(allProductDocs ?? undefined, RELATED_PRODUCT_CEILING),\n [allProductDocs],\n )\n const suppliers = useMemo(\n () => ceilingedWindow<any>(supplierDocs ?? undefined, SUPPLIER_CEILING),\n [supplierDocs],\n )\n\n const lifted = useMemo(\n () => (product ? CommerceModel.liftLegacyProduct(product) : null),\n [product],\n )\n const [draft, setDraft] = useState<CommerceModel.HostProduct | null>(null)\n const [slugTouched, setSlugTouched] = useState(false)\n // The console media browser is provided by the shell (AGL-395); opening it\n // resolves with the chosen asset (or null if cancelled).\n const { pickMedia } = useMediaPicker()\n const pick = useCallback<MediaPick>(\n async (apply) => {\n const media = await pickMedia?.()\n if (media) apply(media)\n },\n [pickMedia],\n )\n // Lazy-init per open; parent remounts via `key` on product change.\n const current: CommerceModel.HostProduct = draft ?? lifted ?? blankProduct()\n /*\n * The two writes every field goes through, each keeping its identity for\n * the life of the dialog so a memoized section redraws only when its own\n * slice of the draft does (AGL-3423). Both write from the draft as last\n * rendered, which `latest` holds: `update` spreads a patch over it, and a\n * patch that is a function is handed it, so no field holds a copy of the\n * product to spread. A write that lands after a picker closes lands on the\n * draft as it is then.\n */\n const latest = useRef(current)\n latest.current = current\n const replaceDraft = useCallback<DraftReplace>(\n (build) => setDraft(build(latest.current)),\n [],\n )\n const update = useCallback<ProductUpdate>(\n (patch) =>\n replaceDraft((at) => ({\n ...at,\n ...(typeof patch === 'function' ? patch(at) : patch),\n })),\n [replaceDraft],\n )\n // The check-in section's view of the variants (AGL-4043): ids, options and\n // their check-in setting only, so a keystroke in a price or a SKU leaves it\n // alone (AGL-3423).\n const checkInVariantsKey = JSON.stringify(\n current.variants.map((variant) => [variant.id, variant.options ?? null, variant.checkIn ?? null]),\n )\n const checkInVariants = useMemo(\n () => current.variants.map(({ id, options, checkIn }) => ({ id, options, checkIn })),\n // Keyed on what it reads, not on the array the last keystroke replaced.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [checkInVariantsKey],\n )\n const setTags = useCallback(\n (tags: string[]) =>\n update({ tags: tags.map((tag) => String(tag).trim()).filter(Boolean) }),\n [update],\n )\n const setCategories = useCallback(\n (picked: any[]) =>\n update({ categoryIds: picked.map((category: any) => category.$id) }),\n [update],\n )\n const setRelatedProducts = useCallback(\n (picked: any[]) =>\n update({ relatedProductIds: picked.map((item: any) => item.$id) }),\n [update],\n )\n const categoryIds = current.categoryIds\n const pickedCategories = useMemo(\n () =>\n categories.rows.filter((category: any) =>\n (categoryIds ?? []).includes(category.$id),\n ),\n [categories.rows, categoryIds],\n )\n const relatedProductIds = current.relatedProductIds\n const productId = product?.$id\n const relatedOptions = useMemo(\n () =>\n relatedProducts.rows.filter(\n (item: any) => !item.deletedAt && item.$id !== productId,\n ),\n [relatedProducts.rows, productId],\n )\n const pickedRelated = useMemo(\n () =>\n relatedProducts.rows.filter((item: any) =>\n (relatedProductIds ?? []).includes(item.$id),\n ),\n [relatedProducts.rows, relatedProductIds],\n )\n\n /** The shell's zone renderer (AGL-2910); `null` outside the console shell. */\n const WidgetSlot = useConsoleWidgetSlot()\n /**\n * A listing zone widget's proposal, staged into the draft like typing.\n * Functional, because a proposal can arrive after a generation finishes,\n * and a closure over the render that started it would put back every edit\n * made while it ran. Only the fields a product's listing holds are taken.\n */\n const proposeSeoValues = useCallback(\n (values: ConsoleSeoFieldValues) => {\n const staged: { title?: string; description?: string } = {}\n for (const field of PRODUCT_SEO_LISTING_FIELDS) {\n const value = values[field]\n if (typeof value === 'string') staged[field] = value\n }\n if (!Object.keys(staged).length) return\n setDraft((prior) => {\n const base = prior ?? lifted ?? blankProduct()\n return { ...base, seo: { ...base.seo, ...staged } }\n })\n },\n [lifted],\n )\n\n /**\n * The product zone's proposal (AGL-2916): copy staged into the draft like\n * typing, functional for the reason `proposeSeoValues` gives. Option names\n * go through `renameProductOptions`, so every variant keeps its price, SKU\n * and stock.\n */\n const proposeProductValues = useCallback(\n (values: ConsoleProductCopyValues) => {\n setDraft((prior) => {\n const base = prior ?? lifted ?? blankProduct()\n return { ...base, ...CommerceModel.productCopyPatch(base, values) }\n })\n },\n [lifted],\n )\n const zoneCategories = useMemo(\n () => categories.rows.map((category: any) => ({ id: String(category.$id), name: String(category.name ?? '') })),\n [categories.rows],\n )\n /*\n * What the two zones are handed, held by content: a keystroke in a field\n * neither zone reads (a SKU, a price) leaves both as they were.\n */\n const zoneProduct = useContentStable<ConsoleProductEditorZoneProps['product']>({\n id: product?.$id ?? null,\n name: current.name,\n type: current.type,\n description: String(current.description ?? ''),\n tags: current.tags ?? [],\n categoryIds: current.categoryIds ?? [],\n options: (current.options ?? []).map((option) => ({ name: option.name, values: option.values })),\n mediaUrls: current.mediaUrls ?? [],\n seoTitle: current.seo?.title ?? '',\n seoDescription: current.seo?.description ?? '',\n shipping: {\n lengthCm: current.shipping?.lengthCm ?? null,\n widthCm: current.shipping?.widthCm ?? null,\n heightCm: current.shipping?.heightCm ?? null,\n hsCode: current.shipping?.hsCode ?? '',\n originCountry: current.shipping?.originCountry ?? '',\n },\n channel: {\n brand: current.channel?.brand ?? '',\n gtin: current.channel?.gtin ?? '',\n mpn: current.channel?.mpn ?? '',\n condition: current.channel?.condition ?? '',\n googleProductCategory: current.channel?.googleProductCategory ?? '',\n },\n })\n const seoSubject = useContentStable({\n kind: 'product',\n id: product?.$id ?? null,\n name: current.name,\n description: String(current.description ?? ''),\n })\n const seoValues = useContentStable({\n title: current.seo?.title ?? '',\n description: current.seo?.description ?? '',\n })\n\n const error = current.name ? CommerceModel.validateProduct(current) : null\n\n /**\n * Stock tracking is inert on a subscription-only product (AGL-1744) —\n * nothing decrements it on the first charge or on any renewal, so the\n * editor stops offering a number it cannot keep true. Existing\n * configuration is NOT discarded: the stored value stays on the document\n * (this save is a full replace of `current`, and `current` is untouched\n * here), stays visible in the disabled field, and becomes editable again\n * the moment Billing goes back to \"One-time purchase\" or \"Both\".\n */\n const stockApplies = CommerceModel.stockTrackingApplies(current)\n const strandedStock = stockApplies\n ? null\n : CommerceModel.productInventory(current)\n\n /**\n * The one destructive move, and the merchant makes it deliberately.\n *\n * Needed because the checkout gate is unchanged: a stored `0` on a\n * subscription-only product still 409s every new subscriber, and with the\n * field disabled that would be a trap with no way out. `inventoryByLocation`\n * goes with it — `adjustVariantInventory` re-sums the flat count from those\n * buckets (AGL-286), so leaving them would let a later restock resurrect a\n * count this just cleared. Keys are DELETED rather than set undefined; the\n * save is a client-direct `setDoc`, which rejects undefined values.\n */\n const handleClearStockTracking = () => {\n update((at) => ({\n variants: at.variants.map((variant) => {\n const { inventoryByLocation: _perLocation, ...rest } = variant\n return { ...rest, inventory: null }\n }),\n }))\n }\n\n const handleName = useCallback(\n (event: FieldChange) => {\n const name = event.target.value\n update({\n name,\n ...(!product && !slugTouched ? { slug: CommerceModel.commerceSlug(name) } : {}),\n })\n },\n [product, slugTouched, update],\n )\n const handleSlug = useCallback(\n (event: FieldChange) => {\n setSlugTouched(true)\n update({ slug: CommerceModel.commerceSlug(event.target.value) })\n },\n [update],\n )\n\n const handleOptionsChange = useCallback<OptionChange>(\n (index, patch) =>\n update((at) => {\n // A RENAME moves each variant's selection to the new name (AGL-3066).\n // Rebuilding the matrix matches variants by name and value, so under a\n // new name it finds none and replaces every variant, its id, price, SKU\n // and stock with them. Only a change of values rebuilds.\n if (\n patch &&\n at.options?.[index] &&\n Object.keys(patch).length === 1 &&\n typeof patch.name === 'string'\n ) {\n return CommerceModel.renameProductOptions(\n at,\n at.options.map((option, optionIndex) =>\n optionIndex === index ? patch.name : option.name,\n ),\n )\n }\n const options = [...(at.options ?? [])]\n if (patch === null) options.splice(index, 1)\n else options[index] = { name: '', values: [], ...options[index], ...patch }\n // Regenerate the matrix, carrying data over by option-combo key so\n // edits to prices/SKUs survive option tweaks.\n const previous = new Map(\n at.variants.map((variant) => [comboKey(variant.options), variant]),\n )\n const fallback = at.variants[0]\n const variants = CommerceModel.expandVariantMatrix(options).map(\n (combo, comboIndex) => {\n const existing = previous.get(comboKey(combo))\n return (\n existing ??\n // An unpriced variant is stored with no `priceUsd` (AGL-3676),\n // as a proposed product's are; the type names the priced shape.\n ({\n id: `v${Date.now().toString(36)}${comboIndex}`,\n options: combo,\n // The first variant's price, or none where it has none;\n // the default only on a product with no variant yet.\n ...(fallback\n ? CommerceModel.variantHasPrice(fallback)\n ? { priceUsd: fallback.priceUsd }\n : {}\n : { priceUsd: CommerceModel.COMMERCE_DEFAULT_PRICE_USD }),\n inventory: fallback?.inventory ?? null,\n } as CommerceModel.ProductVariant)\n )\n },\n )\n return { options, variants }\n }),\n [update],\n )\n const setOptionValues = useCallback(\n (values: string[], index: number) =>\n handleOptionsChange(index, {\n values: values.map((value) => String(value).trim()).filter(Boolean),\n }),\n [handleOptionsChange],\n )\n\n const handleVariantField = useCallback<VariantFieldChange>(\n (index, field, raw) =>\n update((at) => {\n const variants = [...at.variants]\n const numeric = ['priceUsd', 'compareAtPriceUsd', 'weightGrams']\n const value =\n field === 'inventory'\n ? raw.trim() === ''\n ? null\n : Math.max(0, Math.round(Number(raw)))\n : numeric.includes(field)\n ? raw.trim() === ''\n ? undefined\n : Number(raw)\n : raw\n variants[index] = { ...variants[index], [field]: value }\n // A cleared price is no price (AGL-3676), never an `undefined` the\n // client-direct `setDoc` refuses.\n if (\n value === undefined &&\n (field === 'priceUsd' ||\n field === 'compareAtPriceUsd' ||\n field === 'weightGrams')\n ) {\n delete (variants[index] as any)[field]\n }\n return { variants }\n }),\n [update],\n )\n\n\n const handleSave = useCallback(async () => {\n if (!current.name.trim() || error) return\n /*\n * The fields the save writes — `$id` and the seed's `skus`/`barcodes`\n * dropped, the name with its search keys, slug, price, stock fields,\n * image — are `productSaveFields`, the same code the native apps' save\n * route runs (AGL-3652). JSON-safe: no Firestore Timestamp, which would\n * not survive the API hop; millis fields are what checkout reads.\n */\n const base = CommerceModel.productSaveFields(current, Date.now())\n try {\n /**\n * Refuse an EDIT whose seed the server never confirmed (AGL-1358).\n *\n * `merge: false` — a genuine full-document replace, and the payload is\n * `{...current}`, which is `draft ?? lifted(product)`: every field the\n * dialog was seeded with, whether or not it was touched. So a cached\n * seed does not lose the one edit, it replaces the stored product with\n * the cache's whole picture of it — price, variants, stock, media,\n * status, SEO. Anything written since that snapshot, by a colleague or\n * by the checkout engine, is gone.\n *\n * Only the edit path is guarded. A NEW product goes through the\n * quota-enforcing resources API at a fresh uid and can overwrite\n * nothing; the first snapshot of any listener is `fromCache: true`, so\n * guarding a create would refuse a save that was never unsafe.\n *\n * The guard WRAPS the write: an early return is a shape you can keep\n * while losing the protection.\n */\n const verdict = await writeGuardedBySeed(\n {\n subject: 'product',\n unreadable: Boolean(product) && seedUnreadable,\n fromCache: Boolean(product) && seedFromCache,\n },\n async () => {\n // The smart collections this product's rules answer, from the\n // host's rules as they stand now (AGL-3321).\n const membership = await productCollectionFields(\n firestore,\n hostId,\n CommerceModel.productMembershipInput(base, current),\n )\n if (product) {\n /**\n * RESERVATIONS ARE NOT THE EDITOR'S TO WRITE (AGL-2356).\n *\n * Checkout stores live stock holds in a `stockHolds` map on this\n * document, and this is a `merge: false` replace of a payload\n * built from the dialog's SEED. Left alone it would write whatever\n * that seed happened to carry, and both directions are wrong: a\n * seed taken before a shopper reached checkout erases a live\n * reservation and reopens the oversell for that session, and a\n * seed carrying a hold that has since settled resurrects a\n * reservation against stock that is already sold.\n *\n * So the field is dropped from the payload and re-read from the\n * server immediately before the write. One extra read on a product\n * save, in exchange for an editor that cannot invent or destroy a\n * reservation. The AGL-1358 seed guard above bounds how stale the\n * REST of this payload can be; it cannot help here, because a hold\n * legitimately appears seconds after a perfectly fresh seed.\n */\n const productRef = doc(\n firestore,\n 'hosts',\n hostId,\n 'products',\n product.$id,\n )\n const stored = await getDoc(productRef).catch(() => undefined)\n // A product deleted since the editor opened stays deleted. This\n // replace writes `deletedAt: null`, so saving it would bring the\n // product back without the allowance check a create meets — a\n // deleted product no longer holds a slot (AGL-3918). The app's\n // save route refuses the same way.\n if (stored?.get('deletedAt') != null) {\n throw new Error('This product was deleted, so it can no longer be saved')\n }\n const liveHolds = stored?.get('stockHolds')\n // Edit stays client-direct (no quota consumed); full replace.\n // The product page renders it with no publish step, so the save\n // carries the site's cache drop with it (AGL-3386).\n await writeSiteWideChange({\n firestore,\n user,\n hostId,\n write: (batch) =>\n batch.set(\n productRef,\n {\n // The seed's holds dropped, the live ones carried, and\n // `deletedAt: null` — the editor edits a LIVE product, and\n // the products table lists only `deletedAt == null`\n // (AGL-3321).\n ...CommerceModel.productEditWrite(base, liveHolds),\n ...membership,\n updatedAt: Timestamp.now(),\n },\n { merge: false },\n ),\n })\n } else {\n // New product rides the quota-enforcing resources API (AGL-473) —\n // it re-checks the `commerce` entitlement and productsPerHost.\n await createHostResource({\n hostId,\n resource: 'product',\n data: { ...base, ...membership, createdAtMs: Date.now() },\n })\n }\n },\n )\n // A refusal leaves the editor open with every field as edited. Closing\n // it would discard the work AND look like a save that succeeded.\n if (!verdict.ok) {\n return void enqueueSnackbar(verdict.message, {\n variant: 'warning',\n persist: false,\n })\n }\n onClose()\n enqueueSnackbar('Product saved', { variant: 'success', persist: false })\n } catch (saveError: any) {\n console.error(saveError)\n enqueueSnackbar(saveError?.message ?? 'An error has occurred', {\n variant: 'error',\n allowDuplicate: true,\n })\n }\n }, [\n user,\n current,\n error,\n product,\n seedFromCache,\n seedUnreadable,\n firestore,\n hostId,\n createHostResource,\n onClose,\n enqueueSnackbar,\n ])\n\n\n return (\n <Dialog open={open} onClose={onClose} maxWidth=\"md\" fullWidth>\n <DialogTitle>{product ? 'Edit product' : 'Add product'}</DialogTitle>\n <DialogContent sx={{ display: 'flex', flexDirection: 'column', gap: 2 }}>\n <ProductBasicsFields\n name={current.name}\n slug={current.slug}\n type={current.type}\n status={current.status}\n supplierId={current.supplierId}\n description={current.description ?? ''}\n suppliers={suppliers.rows}\n onName={handleName}\n onSlug={handleSlug}\n update={update}\n />\n <ProductChipsField<string>\n freeSolo\n label=\"Tags\"\n placeholder=\"Type and press Enter\"\n options={NO_ITEMS}\n value={current.tags ?? NO_ITEMS}\n onChange={setTags}\n />\n {categories.rows.length > 0 ? (\n <ProductChipsField<any>\n label=\"Categories\"\n options={categories.rows}\n getOptionLabel={categoryLabel}\n isOptionEqualToValue={sameRecord}\n value={pickedCategories}\n onChange={setCategories}\n />\n ) : null}\n {/*\n The product zone (AGL-2916), hosted like the listing zone below: a\n widget proposes copy from what this product says and shows, staged in\n the fields above like typing. Save product is still the only write.\n */}\n {WidgetSlot ? (\n <HostedZone\n renderer={WidgetSlot}\n slot={PRODUCT_EDITOR_ZONE.id}\n hostId={hostId}\n orgId={undefined}\n product={zoneProduct}\n categories={zoneCategories}\n proposeValues={proposeProductValues}\n />\n ) : null}\n\n <Divider textAlign=\"left\">{'Media'}</Divider>\n <ProductMediaFields\n mediaUrls={current.mediaUrls ?? NO_ITEMS}\n update={update}\n pick={pick}\n />\n\n <Divider textAlign=\"left\">{'Options & variants'}</Divider>\n <ProductOptionsFields\n options={current.options ?? NO_OPTIONS}\n onChange={handleOptionsChange}\n onValues={setOptionValues}\n />\n <ProductVariantsTable\n variants={current.variants}\n stockApplies={stockApplies}\n onField={handleVariantField}\n />\n {CommerceModel.productPriceMissing(current) ? (\n <Alert severity=\"warning\">{PRODUCT_PRICE_EMPTY_NOTICE}</Alert>\n ) : null}\n <Typography variant=\"caption\" color=\"text.secondary\">\n {stockApplies\n ? 'Blank stock = untracked; 0 shows sold out. The first variant’s ' +\n 'price feeds legacy Product blocks.'\n : 'Stock is not tracked on a digital or service subscription — ' +\n 'nothing decrements it, on the first charge or on any renewal. ' +\n 'A physical subscription decrements per cycle, and “Both — ' +\n 'buyer chooses” tracks the one-time sales. The first variant’s ' +\n 'price feeds legacy Product blocks.'}\n </Typography>\n {strandedStock != null ? (\n <Alert\n severity=\"warning\"\n action={\n <Button size=\"small\" onClick={handleClearStockTracking}>\n {'Clear stock'}\n </Button>\n }\n >\n {`This product still has stock set (${strandedStock}), but a ` +\n 'digital or service subscription never decrements it — not the ' +\n 'first charge, not any renewal — so the number will not change ' +\n 'on its own and does not cap subscribers. It is kept, not ' +\n 'deleted: a stored 0 still blocks new subscribers, and the ' +\n 'value becomes editable again if you switch Billing back to ' +\n 'one-time or “Both”, or the Type to physical.'}\n </Alert>\n ) : null}\n {/* One linked upsell for both locked selectors (AGL-2080). The\n helper text under each control names the plan, but a disabled\n MenuItem is only visible with the menu open and neither is a\n path anywhere — the retention directive wants the upgrade\n prominent and one-click, so the link lives here, beside the\n controls it unlocks. */}\n {subsLocked || giftsLocked ? (\n <EntitlementUpsell\n planLabel={undefined}\n upgradeHref={subsLocked ? subs.upgradeHref : gifts.upgradeHref}\n >\n {subsLocked && giftsLocked\n ? `Subscription products (${subs.planLabel ?? 'higher plan'}) ` +\n `and gift cards (${gifts.planLabel ?? 'higher plan'}) are ` +\n 'not on your plan. You can still save this product — those ' +\n 'two options stay locked until you upgrade.'\n : subsLocked\n ? `Subscription products are on ${subs.planLabel ?? 'a higher plan'}. ` +\n 'A subscription saved without it is refused at checkout, ' +\n 'so the option stays locked here instead.'\n : `Gift cards are on ${gifts.planLabel ?? 'a higher plan'}. ` +\n 'A gift-card product saved without it is refused at ' +\n 'checkout, so the option stays locked here instead.'}\n </EntitlementUpsell>\n ) : null}\n <ProductSellingFields\n oversellPolicy={current.oversellPolicy ?? 'deny'}\n giftCard={Boolean(current.giftCard)}\n taxExempt={Boolean(current.taxExempt)}\n lowStockThreshold={current.lowStockThreshold}\n stockApplies={stockApplies}\n giftsLocked={giftsLocked}\n giftsPlanLabel={gifts.planLabel}\n update={update}\n />\n <ProductBillingFields\n subscription={current.subscription}\n subscriptionOptional={current.subscriptionOptional}\n subsLocked={subsLocked}\n subsPlanLabel={subs.planLabel}\n update={update}\n replaceDraft={replaceDraft}\n />\n {pos.ready && pos.entitled ? (\n <>\n <ProductRegisterFields\n posQuickKey={Boolean(current.posQuickKey)}\n sellOnline={CommerceModel.productSellsOnline(current)}\n modifierGroups={current.modifierGroups ?? NO_MODIFIER_GROUPS}\n update={update}\n />\n <ProductCheckInFields checkIn={current.checkIn} variants={checkInVariants} update={update} />\n </>\n ) : pos.ready ? (\n <>\n <EntitlementUpsell planLabel={pos.planLabel} upgradeHref={pos.upgradeHref}>\n {'Register quick keys, modifier groups (sizes, add-ons), check-in at the window and selling a product in person only come with the point of sale.'}\n </EntitlementUpsell>\n {/* A product already set to in person only (AGL-4060) can always be put back online. */}\n {!CommerceModel.productSellsOnline(current) ? (\n <ProductSellOnlineField sellOnline={false} update={update} />\n ) : null}\n </>\n ) : null}\n {current.type === 'digital' ? (\n <ProductDigitalFields\n hostId={hostId}\n productId={product?.$id}\n digitalFiles={current.digitalFiles ?? NO_FILES}\n downloadLimit={current.downloadLimit}\n gatedVideos={current.gatedVideos ?? NO_VIDEOS}\n update={update}\n />\n ) : null}\n\n <ProductChipsField<any>\n label=\"Related products (upsells)\"\n helperText=\"Shown by the Related products block; blank falls back to frequently-bought-together\"\n options={relatedOptions}\n getOptionLabel={recordLabel}\n isOptionEqualToValue={sameRecord}\n value={pickedRelated}\n onChange={setRelatedProducts}\n />\n\n <ProductSeoFields\n title={current.seo?.title}\n description={current.seo?.description}\n hasImage={Boolean(current.seo?.imageUrl)}\n update={update}\n pick={pick}\n />\n {/*\n The search listing zone (AGL-2910), hosted here through the shell's\n renderer: a plugin's dialog cannot mount the console's slot itself.\n A widget proposes a title and a description from what this product\n says; they are staged in the fields above like typing, and Save\n product is still the only write.\n */}\n {WidgetSlot ? (\n <HostedZone\n renderer={WidgetSlot}\n slot=\"seoFields\"\n hostId={hostId}\n orgId={undefined}\n orgSlug=\"\"\n subject={seoSubject}\n fields={PRODUCT_SEO_LISTING_FIELDS}\n values={seoValues}\n hasImage={Boolean(current.seo?.imageUrl)}\n proposeValues={proposeSeoValues}\n />\n ) : null}\n\n {error ? <Alert severity=\"warning\">{error}</Alert> : null}\n {product?.$id ? (\n <Typography variant=\"caption\" color=\"text.secondary\">\n {`id: ${product.$id}`}\n </Typography>\n ) : null}\n </DialogContent>\n <DialogActions>\n <Button onClick={onClose}>{'Cancel'}</Button>\n <Button\n variant=\"contained\"\n color=\"primary\"\n disabled={!current.name.trim() || Boolean(error)}\n onClick={handleSave}\n >\n {'Save product'}\n </Button>\n </DialogActions>\n </Dialog>\n )\n}\nProductEditorDialog.displayName = 'ProductEditorDialog'\n\nexport default ProductEditorDialog\n"],"names":["CommerceModel","useSnackbar","Timestamp","Alert","Autocomplete","Box","Button","Dialog","DialogActions","DialogContent","DialogTitle","Divider","IconButton","MenuItem","Stack","TableBody","TableCell","TableHead","TableRow","TextField","Typography","collection","doc","getDoc","ScanAdornment","productCollectionFields","memo","useCallback","useMemo","useRef","useState","ceilingedWindow","collectionCeiling","useFirestore","useFirestoreCollection","useHostResourceApi","writeGuardedBySeed","useUser","writeSiteWideChange","useMediaPicker","useConsoleWidgetSlot","seoListingFieldCount","seoListingFieldTooLong","ScrollTable","useContentStable","EntitlementUpsell","useCommerceEntitlement","PRODUCT_EDITOR_ZONE","MembersVideosField","PaidDownloadAddButton","PaidMediaProtection","ProductCheckInFields","ProductRegisterFields","ProductSellOnlineField","CATEGORY_CEILING","RELATED_PRODUCT_CEILING","SUPPLIER_CEILING","PRODUCT_SEO_LISTING_FIELDS","blankProduct","name","slug","type","status","variants","id","priceUsd","COMMERCE_DEFAULT_PRICE_USD","PRODUCT_PRICE_EMPTY_NOTICE","comboKey","options","Object","entries","sort","a","b","localeCompare","map","value","join","comboLabel","values","length","NO_ITEMS","NO_OPTIONS","NO_FILES","NO_VIDEOS","FILL_ROW","flex","categoryLabel","category","recordLabel","item","$id","sameRecord","option","ProductChipsField","props","index","onChange","multiple","freeSolo","getOptionLabel","isOptionEqualToValue","_event","next","renderInput","params","label","size","placeholder","helperText","sx","fill","undefined","NO_MODIFIER_GROUPS","MemoTextField","FIRST_ROW","mt","WIDE_ROW","xs","sm","NARROW_SELECT","minWidth","SUPPLIER_SELECT","OVERSELL_SELECT","KIND_SELECT","SHORT_SELECT","BILLING_SELECT","COUNT_FIELD","width","VERSION_FIELD","OPTION_FIELD","PRICE_CELL","CODE_CELL","BARCODE_CELL","STOCK_CELL","DECIMAL_INPUT","htmlInput","inputMode","NUMERIC_INPUT","TYPE_MENU","STATUS_MENU","OVERSELL_MENU","TAX_MENU","INTERVAL_MENU","HostedZone","renderer","Renderer","zone","ProductBasicsFields","suppliers","update","setType","event","target","setStatus","setSupplier","supplierId","setDescription","description","supplierMenu","supplier","direction","spacing","onName","autoFocus","fullWidth","onSlug","select","multiline","minRows","ProductMediaFields","mediaUrls","pick","display","gap","flexWrap","url","position","component","src","alt","height","objectFit","borderRadius","border","borderColor","aria-label","onClick","product","filter","_item","itemIndex","top","right","bgcolor","p","media","ProductOptionRow","onValues","setName","alignItems","color","ProductOptionsFields","COMMERCE_MAX_OPTIONS","alignSelf","ProductVariantRow","variant","stockApplies","onField","set","cell","field","compareAtPriceUsd","sku","barcode","inventory","weightGrams","stockInput","barcodeInput","input","endAdornment","onScan","code","whiteSpace","variantHasPrice","focused","slotProps","disabled","VARIANTS_HEAD","ProductVariantsTable","ProductSellingFields","giftsLocked","giftsPlanLabel","setOversellPolicy","oversellPolicy","setKind","giftCard","setTax","taxExempt","setLowStock","raw","trim","lowStockThreshold","Math","max","round","Number","kindMenu","ProductBillingFields","subscription","subscriptionOptional","subsLocked","replaceDraft","setBilling","interval","setBillingInterval","setTrialDays","trialDays","billingMenu","subsPlanLabel","DigitalFileRow","file","setVersion","version","slice","digitalFiles","noWrap","fileName","hostId","productId","kind","MemoMembersVideosField","MemoPaidDownloadAddButton","ProductDigitalFields","addFile","setDownloadLimit","downloadLimit","setVideos","gatedVideos","textAlign","onAdd","videos","ProductSeoFields","title","setTitle","seo","error","imageUrl","hasImage","ProductEditorDialog","draft","current","subs","gifts","seedFromCache","seedUnreadable","open","onClose","pos","ready","entitled","firestore","data","user","createHostResource","enqueueSnackbar","categoryDocs","idField","allProductDocs","supplierDocs","categories","relatedProducts","lifted","liftLegacyProduct","setDraft","slugTouched","setSlugTouched","pickMedia","apply","latest","build","patch","at","checkInVariantsKey","JSON","stringify","checkIn","checkInVariants","setTags","tags","tag","String","Boolean","setCategories","picked","categoryIds","setRelatedProducts","relatedProductIds","pickedCategories","rows","includes","relatedOptions","deletedAt","pickedRelated","WidgetSlot","proposeSeoValues","staged","keys","prior","base","proposeProductValues","productCopyPatch","zoneCategories","zoneProduct","seoTitle","seoDescription","shipping","lengthCm","widthCm","heightCm","hsCode","originCountry","channel","brand","gtin","mpn","condition","googleProductCategory","seoSubject","seoValues","validateProduct","stockTrackingApplies","strandedStock","productInventory","handleClearStockTracking","inventoryByLocation","_perLocation","rest","handleName","commerceSlug","handleSlug","handleOptionsChange","renameProductOptions","optionIndex","splice","previous","Map","fallback","expandVariantMatrix","combo","comboIndex","existing","get","Date","now","toString","setOptionValues","handleVariantField","numeric","handleSave","productSaveFields","verdict","subject","unreadable","fromCache","membership","productMembershipInput","productRef","stored","catch","Error","liveHolds","write","batch","productEditWrite","updatedAt","merge","resource","createdAtMs","ok","message","persist","saveError","console","allowDuplicate","maxWidth","flexDirection","slot","orgId","proposeValues","productPriceMissing","severity","action","planLabel","upgradeHref","posQuickKey","sellOnline","productSellsOnline","modifierGroups","orgSlug","fields","displayName"],"mappings":"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"}
@@ -2,9 +2,21 @@ import * as CommerceModel from '../../model';
2
2
  type Patch = Partial<CommerceModel.HostProduct>;
3
3
  export interface ProductRegisterFieldsProps {
4
4
  posQuickKey: boolean;
5
+ /** `productSellsOnline` of the product: absent reads as on. */
6
+ sellOnline: boolean;
5
7
  modifierGroups: readonly CommerceModel.ProductModifierGroup[];
6
8
  update: (patch: Patch) => void;
7
9
  }
10
+ export interface ProductSellOnlineFieldProps {
11
+ sellOnline: boolean;
12
+ update: (patch: Patch) => void;
13
+ }
14
+ /**
15
+ * The product's "Sell online" switch (AGL-4060). On (the default, and what
16
+ * every product stored before it reads as) the product sells on the site and
17
+ * its channels as it always has; off, it sells in person only.
18
+ */
19
+ export declare const ProductSellOnlineField: import("react").MemoExoticComponent<(props: ProductSellOnlineFieldProps) => import("react").JSX.Element>;
8
20
  /**
9
21
  * The product's register settings (AGL-3607): whether it is a quick key on
10
22
  * the register's first screen, and its modifier groups — choices such as