@aglyn/plugins-ai 1.0.0-beta.244 → 1.0.0-beta.246

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 (116) hide show
  1. package/package.json +17 -17
  2. package/src/lib/activity/ai-activity-actions.js +3 -1
  3. package/src/lib/activity/ai-activity-actions.js.map +1 -1
  4. package/src/lib/components/ai-job-links.js +7 -0
  5. package/src/lib/components/ai-job-links.js.map +1 -1
  6. package/src/lib/components/ai-product-zones.d.ts +3 -1
  7. package/src/lib/components/ai-product-zones.js.map +1 -1
  8. package/src/lib/components/ai-products-hub-card.component.js +1 -1
  9. package/src/lib/components/ai-products-hub-card.component.js.map +1 -1
  10. package/src/lib/components/ai-products-proposals.component.js +17 -9
  11. package/src/lib/components/ai-products-proposals.component.js.map +1 -1
  12. package/src/lib/components/ai-site-start-card.component.js +6 -4
  13. package/src/lib/components/ai-site-start-card.component.js.map +1 -1
  14. package/src/lib/components/ai-upsell-dialog.component.js +1 -1
  15. package/src/lib/components/ai-upsell-dialog.component.js.map +1 -1
  16. package/src/lib/jobs/ai-build-capabilities.js +162 -2
  17. package/src/lib/jobs/ai-build-capabilities.js.map +1 -1
  18. package/src/lib/jobs/ai-job-build-step.d.ts +7 -0
  19. package/src/lib/jobs/ai-job-build-step.js +85 -16
  20. package/src/lib/jobs/ai-job-build-step.js.map +1 -1
  21. package/src/lib/jobs/ai-job-duplicate-step.d.ts +123 -0
  22. package/src/lib/jobs/ai-job-duplicate-step.js +269 -0
  23. package/src/lib/jobs/ai-job-duplicate-step.js.map +1 -0
  24. package/src/lib/jobs/ai-job-layout-language.js +13 -0
  25. package/src/lib/jobs/ai-job-layout-language.js.map +1 -1
  26. package/src/lib/jobs/ai-job-navigation-step.d.ts +157 -0
  27. package/src/lib/jobs/ai-job-navigation-step.js +439 -0
  28. package/src/lib/jobs/ai-job-navigation-step.js.map +1 -0
  29. package/src/lib/jobs/ai-job-page-language.d.ts +2 -1
  30. package/src/lib/jobs/ai-job-page-language.js +21 -5
  31. package/src/lib/jobs/ai-job-page-language.js.map +1 -1
  32. package/src/lib/jobs/ai-job-page-sections.js +1 -1
  33. package/src/lib/jobs/ai-job-page-sections.js.map +1 -1
  34. package/src/lib/jobs/ai-job-plan-step.d.ts +4 -2
  35. package/src/lib/jobs/ai-job-plan-step.js +16 -7
  36. package/src/lib/jobs/ai-job-plan-step.js.map +1 -1
  37. package/src/lib/jobs/ai-job-products-step.d.ts +2 -2
  38. package/src/lib/jobs/ai-job-products-step.js +2 -2
  39. package/src/lib/jobs/ai-job-products-step.js.map +1 -1
  40. package/src/lib/jobs/ai-job-settings-step.d.ts +272 -0
  41. package/src/lib/jobs/ai-job-settings-step.js +695 -0
  42. package/src/lib/jobs/ai-job-settings-step.js.map +1 -0
  43. package/src/lib/jobs/ai-job-site-content.d.ts +20 -6
  44. package/src/lib/jobs/ai-job-site-content.js +28 -12
  45. package/src/lib/jobs/ai-job-site-content.js.map +1 -1
  46. package/src/lib/jobs/ai-job-site-datasets.d.ts +2 -0
  47. package/src/lib/jobs/ai-job-site-datasets.js +10 -3
  48. package/src/lib/jobs/ai-job-site-datasets.js.map +1 -1
  49. package/src/lib/jobs/ai-job-site-step.d.ts +3 -1
  50. package/src/lib/jobs/ai-job-site-step.js +70 -10
  51. package/src/lib/jobs/ai-job-site-step.js.map +1 -1
  52. package/src/lib/jobs/ai-site-publish.d.ts +62 -4
  53. package/src/lib/jobs/ai-site-publish.js +203 -56
  54. package/src/lib/jobs/ai-site-publish.js.map +1 -1
  55. package/src/lib/layout-language/ai-layout-compiler.d.ts +7 -4
  56. package/src/lib/layout-language/ai-layout-compiler.js +26 -25
  57. package/src/lib/layout-language/ai-layout-compiler.js.map +1 -1
  58. package/src/lib/layout-language/ai-layout-frame-hollows.d.ts +41 -0
  59. package/src/lib/layout-language/ai-layout-frame-hollows.js +330 -0
  60. package/src/lib/layout-language/ai-layout-frame-hollows.js.map +1 -0
  61. package/src/lib/layout-language/ai-layout-frame.d.ts +18 -1
  62. package/src/lib/layout-language/ai-layout-frame.js +83 -13
  63. package/src/lib/layout-language/ai-layout-frame.js.map +1 -1
  64. package/src/lib/layout-language/ai-layout-listings.d.ts +35 -0
  65. package/src/lib/layout-language/ai-layout-listings.js +34 -0
  66. package/src/lib/layout-language/ai-layout-listings.js.map +1 -1
  67. package/src/lib/layout-language/ai-layout-tree.d.ts +2 -0
  68. package/src/lib/layout-language/ai-layout-tree.js +17 -0
  69. package/src/lib/layout-language/ai-layout-tree.js.map +1 -1
  70. package/src/lib/model/ai-build-job.d.ts +23 -0
  71. package/src/lib/model/ai-build-job.js +102 -13
  72. package/src/lib/model/ai-build-job.js.map +1 -1
  73. package/src/lib/model/ai-build-plan.d.ts +25 -0
  74. package/src/lib/model/ai-build-plan.js +45 -1
  75. package/src/lib/model/ai-build-plan.js.map +1 -1
  76. package/src/lib/model/ai-credit-estimate.d.ts +52 -0
  77. package/src/lib/model/ai-credit-estimate.js +51 -0
  78. package/src/lib/model/ai-credit-estimate.js.map +1 -1
  79. package/src/lib/model/ai-job-activity.js +4 -1
  80. package/src/lib/model/ai-job-activity.js.map +1 -1
  81. package/src/lib/model/ai-jobs.types.d.ts +10 -2
  82. package/src/lib/model/ai-jobs.types.js +4 -1
  83. package/src/lib/model/ai-jobs.types.js.map +1 -1
  84. package/src/lib/model/ai-layout-menus.d.ts +104 -0
  85. package/src/lib/model/ai-layout-menus.js +518 -0
  86. package/src/lib/model/ai-layout-menus.js.map +1 -0
  87. package/src/lib/model/ai-products.d.ts +31 -1
  88. package/src/lib/model/ai-products.js +34 -1
  89. package/src/lib/model/ai-products.js.map +1 -1
  90. package/src/lib/model/ai-site-inventory.d.ts +15 -0
  91. package/src/lib/model/ai-site-inventory.js.map +1 -1
  92. package/src/lib/model/ai-site-job.d.ts +10 -0
  93. package/src/lib/model/ai-site-job.js +36 -9
  94. package/src/lib/model/ai-site-job.js.map +1 -1
  95. package/src/lib/model/ai-site-store-pages.js +1 -1
  96. package/src/lib/model/ai-site-store-pages.js.map +1 -1
  97. package/src/lib/runtime/ai-doctrine-validators.d.ts +53 -0
  98. package/src/lib/runtime/ai-doctrine-validators.js +166 -25
  99. package/src/lib/runtime/ai-doctrine-validators.js.map +1 -1
  100. package/src/lib/runtime/ai-doctrine.js +7 -2
  101. package/src/lib/runtime/ai-doctrine.js.map +1 -1
  102. package/src/lib/runtime/ai-palette.generated.js +1 -1
  103. package/src/lib/runtime/ai-palette.generated.js.map +1 -1
  104. package/src/lib/runtime/ai-products-generation.d.ts +4 -2
  105. package/src/lib/runtime/ai-products-generation.js +12 -6
  106. package/src/lib/runtime/ai-products-generation.js.map +1 -1
  107. package/src/lib/runtime/site-inventory.d.ts +12 -0
  108. package/src/lib/runtime/site-inventory.js +29 -1
  109. package/src/lib/runtime/site-inventory.js.map +1 -1
  110. package/src/lib/server.js +12 -0
  111. package/src/lib/server.js.map +1 -1
  112. package/src/lib/testing/stand-in-dataset-index.js +37 -3
  113. package/src/lib/testing/stand-in-dataset-index.js.map +1 -1
  114. package/src/lib/tools/ai-products-tool.d.ts +3 -1
  115. package/src/lib/tools/ai-products-tool.js +15 -5
  116. package/src/lib/tools/ai-products-tool.js.map +1 -1
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../../libs/plugins/ai/src/lib/components/ai-products-proposals.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 type { ConsoleProductsHubZoneProps } from './ai-product-zones'\nimport { ListTable, type ListTableProps } from '@aglyn/shared-ui-jsx/components/list-table.component'\nimport { Alert, Button, Chip, CircularProgress, Stack, Typography } from '@mui/material'\nimport { useCallback, useMemo, useState } from 'react'\nimport type { AiJobSummary } from '../model/ai-jobs.types'\nimport {\n aiProductCopyProposals,\n aiProductsBulkCount,\n aiProductsProposalOfKind,\n type AiProductCopyProposal,\n type AiProposedDiscount,\n} from '../model/ai-products'\nimport { aiProductCopyValues } from './ai-product-copy-card.component'\nimport { isAiJobMoving } from './use-ai-products-jobs'\n\n/**\n * The review tables of the products hub's AI card (AGL-2916): what a\n * `products` job proposed, row by row, before anything is written. Every\n * write is one the hub makes when a person asks for it — Apply, Apply to all,\n * Create drafts, Create selected — and the hub passes over what the site\n * already has, so a proposal applied twice creates nothing twice.\n *\n * Each table is one job's whole answer, held in hand and capped by the job\n * (`AI_PRODUCTS_BULK_MAX`, `AI_CATEGORIES_MAX`, `AI_DISCOUNTS_MAX`, a dozen\n * proposed products), so none offers a Filters panel or a search box: a\n * bounded readout is read whole, and a grid that filtered the rows it holds\n * is the pattern every list is leaving (AGL-3321).\n */\n\n/** A column of a review table, in the shared list table's own terms. */\ntype GridColDef = NonNullable<ListTableProps['columns']>[number]\n\nconst clip = (text: string, max: number) => (text.length > max ? `${text.slice(0, max - 1)}…` : text)\n\nconst messageOf = (error: unknown, fallback: string) =>\n error instanceof Error && error.message ? error.message : fallback\n\n/** A discount's offer, in the words the discounts card uses. */\nexport function aiDiscountOffer(discount: AiProposedDiscount): string {\n if (discount.kind === 'percent') return `${discount.valuePct ?? 0}% off`\n if (discount.kind === 'fixed') return `$${((discount.valueCents ?? 0) / 100).toFixed(2)} off`\n return 'Free shipping'\n}\n\nfunction JobState(props: { job: AiJobSummary; doing: string }) {\n const { job } = props\n if (isAiJobMoving(job)) {\n return (\n <Stack direction=\"row\" spacing={1} sx={{ alignItems: 'center' }}>\n <CircularProgress size={16} aria-label={props.doing} />\n <Typography variant=\"body2\" color=\"text.secondary\">\n {props.doing}\n </Typography>\n </Stack>\n )\n }\n return job.error ? <Alert severity={job.status === 'failed' ? 'error' : 'warning'}>{job.error}</Alert> : null\n}\n\n/* ------------------------------------------------------------------------ *\n * Copy for many products\n * ------------------------------------------------------------------------ */\n\ntype RowState = 'applying' | 'applied' | { error: string }\n\nexport function AiBulkCopyReview(props: {\n job: AiJobSummary\n applyProductCopy: ConsoleProductsHubZoneProps['applyProductCopy']\n}) {\n const { job, applyProductCopy } = props\n const proposals = aiProductCopyProposals(job)\n const asked = aiProductsBulkCount(job) ?? proposals.length\n const [rows, setRows] = useState<Record<string, RowState>>({})\n const [applyingAll, setApplyingAll] = useState(false)\n\n const ready = (proposal: AiProductCopyProposal) =>\n Boolean(proposal.values && proposal.product.id) && rows[proposal.product.id as string] !== 'applied'\n\n const apply = useCallback(\n async (proposal: AiProductCopyProposal) => {\n const id = proposal.product.id\n if (!id || !proposal.values) return\n setRows((current) => ({ ...current, [id]: 'applying' }))\n try {\n await applyProductCopy(id, aiProductCopyValues(proposal))\n setRows((current) => ({ ...current, [id]: 'applied' }))\n } catch (error) {\n setRows((current) => ({ ...current, [id]: { error: messageOf(error, 'The copy could not be saved.') } }))\n }\n },\n [applyProductCopy],\n )\n\n /** Applies each proposal in turn, so one refusal names its product and the rest still land. */\n const applyAll = useCallback(\n async (targets: readonly AiProductCopyProposal[]) => {\n setApplyingAll(true)\n try {\n for (const proposal of targets) await apply(proposal)\n } finally {\n setApplyingAll(false)\n }\n },\n [apply],\n )\n\n const columns = useMemo<GridColDef[]>(\n () => [\n { field: 'name', headerName: 'Product', flex: 1, minWidth: 160 },\n { field: 'description', headerName: 'Proposed description', flex: 2, minWidth: 220 },\n { field: 'seoTitle', headerName: 'Search title', flex: 1, minWidth: 160 },\n {\n field: 'actions',\n headerName: '',\n width: 170,\n sortable: false,\n renderCell: ({ row }: { row: { proposal: AiProductCopyProposal } }) => {\n const { proposal } = row\n if (proposal.skipped) return <Chip size=\"small\" variant=\"outlined\" label=\"Skipped\" title={proposal.skipped} />\n const state = proposal.product.id ? rows[proposal.product.id] : undefined\n if (state === 'applied') return <Chip size=\"small\" color=\"success\" variant=\"outlined\" label=\"Applied\" />\n if (typeof state === 'object') return <Chip size=\"small\" color=\"error\" variant=\"outlined\" label=\"Not saved\" title={state.error} />\n return (\n <Button size=\"small\" disabled={state === 'applying' || applyingAll} onClick={() => void apply(proposal)}>\n {'Apply'}\n </Button>\n )\n },\n },\n ],\n [rows, applyingAll, apply],\n )\n\n const tableRows = proposals.map((proposal) => ({\n $id: proposal.product.id ?? proposal.product.name,\n name: proposal.product.name,\n description: proposal.values ? clip(proposal.values.description, 140) : (proposal.skipped ?? ''),\n seoTitle: proposal.values?.seoTitle ?? '',\n proposal,\n }))\n const readyCount = proposals.filter(ready).length\n const errors = Object.values(rows).filter((state): state is { error: string } => typeof state === 'object')\n const gaps = proposals.filter((proposal) => proposal.gaps.length).length\n\n return (\n <Stack spacing={1} aria-label=\"Proposed product copy\">\n <Typography variant=\"subtitle2\">{`Product copy · ${proposals.length} of ${asked}`}</Typography>\n <JobState job={job} doing={`Writing copy: ${proposals.length} of ${asked}`} />\n {tableRows.length ? <ListTable rows={tableRows} columns={columns} hideFooter disableColumnFilter quickFilter={false} /> : null}\n {gaps ? (\n <Alert severity=\"warning\">\n {`${gaps} ${gaps === 1 ? 'description marks' : 'descriptions mark'} facts in [brackets] to fill in before you publish.`}\n </Alert>\n ) : null}\n {errors.length ? <Alert severity=\"error\">{errors[0].error}</Alert> : null}\n <Button\n size=\"small\"\n variant=\"contained\"\n sx={{ alignSelf: 'flex-start' }}\n disabled={!readyCount || applyingAll}\n onClick={() => void applyAll(proposals.filter(ready))}\n >\n {readyCount ? `Apply to all ${readyCount}` : 'Apply to all'}\n </Button>\n </Stack>\n )\n}\n\n/* ------------------------------------------------------------------------ *\n * A store's first products\n * ------------------------------------------------------------------------ */\n\nexport function AiCatalogReview(props: {\n job: AiJobSummary\n heldNames: ReadonlySet<string>\n createProductDrafts: ConsoleProductsHubZoneProps['createProductDrafts']\n}) {\n const { job, heldNames, createProductDrafts } = props\n const proposal = aiProductsProposalOfKind(job, 'catalog')\n const products = useMemo(() => proposal?.products ?? [], [proposal])\n const held = (name: string) => heldNames.has(name.replace(/\\s+/g, ' ').trim().toLowerCase())\n const [selected, setSelected] = useState<string[] | null>(null)\n const [busy, setBusy] = useState(false)\n const [result, setResult] = useState<{ severity: 'success' | 'error'; text: string } | null>(null)\n\n const rows = products.map((product, index) => ({\n $id: `p${index}`,\n name: product.name,\n type: product.type,\n options: product.options.map((option) => `${option.name}: ${option.values.join(', ')}`).join(' · ') || '—',\n photo: product.photo,\n inCatalog: held(product.name),\n product,\n }))\n const chosen = selected ?? rows.filter((row) => !row.inCatalog).map((row) => row.$id)\n\n const columns = useMemo<GridColDef[]>(\n () => [\n { field: 'name', headerName: 'Product', flex: 1, minWidth: 180 },\n { field: 'options', headerName: 'Options', flex: 1, minWidth: 160 },\n {\n field: 'price',\n headerName: 'Price',\n width: 130,\n sortable: false,\n // Never proposed: prices are the merchant's to set.\n renderCell: () => <Chip size=\"small\" color=\"warning\" variant=\"outlined\" label=\"Set a price\" />,\n },\n {\n field: 'photo',\n headerName: 'Photo',\n flex: 1,\n minWidth: 200,\n sortable: false,\n renderCell: ({ row }: { row: { photo: string; inCatalog: boolean } }) => (\n <Stack spacing={0.25} sx={{ py: 0.5 }}>\n <Chip size=\"small\" color=\"warning\" variant=\"outlined\" label=\"Needs a photo\" sx={{ alignSelf: 'flex-start' }} />\n <Typography variant=\"caption\" color=\"text.secondary\" sx={{ whiteSpace: 'normal' }}>\n {row.photo}\n </Typography>\n </Stack>\n ),\n },\n {\n field: 'inCatalog',\n headerName: '',\n width: 150,\n sortable: false,\n renderCell: ({ row }: { row: { inCatalog: boolean } }) =>\n row.inCatalog ? <Chip size=\"small\" variant=\"outlined\" label=\"In your catalog\" /> : null,\n },\n ],\n [],\n )\n\n const create = useCallback(async () => {\n const picks = rows.filter((row) => chosen.includes(row.$id)).map((row) => row.product)\n if (!picks.length) return\n setBusy(true)\n setResult(null)\n try {\n const created = await createProductDrafts(\n picks.map((product) => ({\n name: product.name,\n type: product.type,\n description: product.description,\n tags: product.tags,\n options: product.options,\n seoTitle: product.seoTitle,\n seoDescription: product.seoDescription,\n })),\n )\n const passed = picks.length - created.length\n setResult({\n severity: 'success',\n text:\n `Created ${created.length} draft ${created.length === 1 ? 'product' : 'products'}. ` +\n 'Each needs a price and a photo before you activate it.' +\n (passed ? ` ${passed} already in your catalog ${passed === 1 ? 'was' : 'were'} left as they are.` : ''),\n })\n setSelected([])\n } catch (error) {\n setResult({ severity: 'error', text: messageOf(error, 'The draft products could not be created.') })\n } finally {\n setBusy(false)\n }\n }, [rows, chosen, createProductDrafts])\n\n return (\n <Stack spacing={1} aria-label=\"Proposed products\">\n <Typography variant=\"subtitle2\">{'Proposed products'}</Typography>\n <JobState job={job} doing=\"Proposing products from your brief\" />\n {rows.length ? (\n <>\n <Typography variant=\"body2\" color=\"text.secondary\">\n {'Each is created as a draft with its price left empty and no photo. Set both in the product editor, ' +\n 'then activate it.'}\n </Typography>\n <ListTable\n rows={rows}\n columns={columns}\n hideFooter\n disableColumnFilter\n quickFilter={false}\n getRowHeight={() => 'auto'}\n selectable={{ selected: chosen, onChange: setSelected }}\n />\n <Button\n size=\"small\"\n variant=\"contained\"\n sx={{ alignSelf: 'flex-start' }}\n disabled={busy || !chosen.length}\n onClick={() => void create()}\n >\n {`Create ${chosen.length} ${chosen.length === 1 ? 'draft' : 'drafts'}`}\n </Button>\n </>\n ) : null}\n {result ? <Alert severity={result.severity}>{result.text}</Alert> : null}\n </Stack>\n )\n}\n\n/* ------------------------------------------------------------------------ *\n * Categories and discounts\n * ------------------------------------------------------------------------ */\n\nexport function AiCategoriesReview(props: {\n job: AiJobSummary\n createCategories: ConsoleProductsHubZoneProps['createCategories']\n createDiscountDrafts: ConsoleProductsHubZoneProps['createDiscountDrafts']\n}) {\n const { job, createCategories, createDiscountDrafts } = props\n const proposal = aiProductsProposalOfKind(job, 'categories')\n const categoryRows = (proposal?.categories ?? []).map((category, index) => ({\n $id: `c${index}`,\n name: category.name,\n why: category.why,\n }))\n const discountRows = (proposal?.discounts ?? []).map((discount, index) => ({\n $id: `d${index}`,\n name: discount.name,\n code: discount.code ?? 'Applies on its own',\n offer: aiDiscountOffer(discount),\n minimum: discount.minSubtotalCents ? `$${(discount.minSubtotalCents / 100).toFixed(2)}` : 'Any order',\n why: discount.why,\n discount,\n }))\n const [categories, setCategories] = useState<string[] | null>(null)\n const [discounts, setDiscounts] = useState<string[] | null>(null)\n const [busy, setBusy] = useState(false)\n const [result, setResult] = useState<{ severity: 'success' | 'error'; text: string } | null>(null)\n const chosenCategories = categories ?? categoryRows.map((row) => row.$id)\n const chosenDiscounts = discounts ?? discountRows.map((row) => row.$id)\n\n const categoryColumns = useMemo<GridColDef[]>(\n () => [\n { field: 'name', headerName: 'Category', flex: 1, minWidth: 160 },\n { field: 'why', headerName: 'Why', flex: 2, minWidth: 220 },\n ],\n [],\n )\n const discountColumns = useMemo<GridColDef[]>(\n () => [\n { field: 'name', headerName: 'Discount', flex: 1, minWidth: 150 },\n { field: 'code', headerName: 'Code', width: 150 },\n { field: 'offer', headerName: 'Offer', width: 120 },\n { field: 'minimum', headerName: 'Minimum order', width: 130 },\n { field: 'why', headerName: 'Why', flex: 2, minWidth: 200 },\n ],\n [],\n )\n\n const create = useCallback(async () => {\n setBusy(true)\n setResult(null)\n try {\n const madeCategories = await createCategories(\n categoryRows.filter((row) => chosenCategories.includes(row.$id)).map((row) => row.name),\n )\n const madeDiscounts = await createDiscountDrafts(\n discountRows\n .filter((row) => chosenDiscounts.includes(row.$id))\n .map(({ discount }) => ({\n name: discount.name,\n code: discount.code,\n kind: discount.kind,\n valuePct: discount.valuePct,\n valueCents: discount.valueCents,\n minSubtotalCents: discount.minSubtotalCents,\n })),\n )\n setResult({\n severity: 'success',\n text:\n `Created ${madeCategories} ${madeCategories === 1 ? 'category' : 'categories'} and ` +\n `${madeDiscounts} ${madeDiscounts === 1 ? 'discount' : 'discounts'}. ` +\n 'Discounts start switched off: switch each on under Promotions when you are ready. ' +\n 'Anything your store already had was left as it is.',\n })\n setCategories([])\n setDiscounts([])\n } catch (error) {\n setResult({ severity: 'error', text: messageOf(error, 'The categories and discounts could not be created.') })\n } finally {\n setBusy(false)\n }\n }, [categoryRows, discountRows, chosenCategories, chosenDiscounts, createCategories, createDiscountDrafts])\n\n const any = chosenCategories.length + chosenDiscounts.length\n return (\n <Stack spacing={1} aria-label=\"Proposed categories and discounts\">\n <Typography variant=\"subtitle2\">{'Proposed categories and discounts'}</Typography>\n <JobState job={job} doing=\"Proposing categories and discounts from your brief\" />\n {categoryRows.length ? (\n <ListTable\n rows={categoryRows}\n columns={categoryColumns}\n hideFooter\n disableColumnFilter\n quickFilter={false}\n selectable={{ selected: chosenCategories, onChange: setCategories }}\n />\n ) : null}\n {discountRows.length ? (\n <ListTable\n rows={discountRows}\n columns={discountColumns}\n hideFooter\n disableColumnFilter\n quickFilter={false}\n selectable={{ selected: chosenDiscounts, onChange: setDiscounts }}\n />\n ) : null}\n {categoryRows.length || discountRows.length ? (\n <Button\n size=\"small\"\n variant=\"contained\"\n sx={{ alignSelf: 'flex-start' }}\n disabled={busy || !any}\n onClick={() => void create()}\n >\n {'Create selected'}\n </Button>\n ) : null}\n {result ? <Alert severity={result.severity}>{result.text}</Alert> : null}\n </Stack>\n )\n}\n"],"names":["ListTable","Alert","Button","Chip","CircularProgress","Stack","Typography","useCallback","useMemo","useState","aiProductCopyProposals","aiProductsBulkCount","aiProductsProposalOfKind","aiProductCopyValues","isAiJobMoving","clip","text","max","length","slice","messageOf","error","fallback","Error","message","aiDiscountOffer","discount","kind","valuePct","valueCents","toFixed","JobState","props","job","direction","spacing","sx","alignItems","size","aria-label","doing","variant","color","severity","status","AiBulkCopyReview","applyProductCopy","proposals","asked","rows","setRows","applyingAll","setApplyingAll","ready","proposal","Boolean","values","product","id","apply","current","applyAll","targets","columns","field","headerName","flex","minWidth","width","sortable","renderCell","row","skipped","label","title","state","undefined","disabled","onClick","tableRows","map","$id","name","description","seoTitle","readyCount","filter","errors","Object","gaps","hideFooter","disableColumnFilter","quickFilter","alignSelf","AiCatalogReview","heldNames","createProductDrafts","products","held","has","replace","trim","toLowerCase","selected","setSelected","busy","setBusy","result","setResult","index","type","options","option","join","photo","inCatalog","chosen","py","whiteSpace","create","picks","includes","created","tags","seoDescription","passed","getRowHeight","selectable","onChange","AiCategoriesReview","createCategories","createDiscountDrafts","categoryRows","categories","category","why","discountRows","discounts","code","offer","minimum","minSubtotalCents","setCategories","setDiscounts","chosenCategories","chosenDiscounts","categoryColumns","discountColumns","madeCategories","madeDiscounts","any"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../../../../libs/plugins/ai/src/lib/components/ai-products-proposals.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 type { ConsoleProductsHubZoneProps } from './ai-product-zones'\nimport { ListTable, type ListTableProps } from '@aglyn/shared-ui-jsx/components/list-table.component'\nimport { Alert, Button, Chip, CircularProgress, Stack, Typography } from '@mui/material'\nimport { useCallback, useMemo, useState } from 'react'\nimport type { AiJobSummary } from '../model/ai-jobs.types'\nimport {\n aiCatalogPrice,\n aiProductCopyProposals,\n aiProductsBulkCount,\n aiProductsProposalOfKind,\n type AiProductCopyProposal,\n type AiProposedDiscount,\n} from '../model/ai-products'\nimport { aiProductCopyValues } from './ai-product-copy-card.component'\nimport { isAiJobMoving } from './use-ai-products-jobs'\n\n/**\n * The review tables of the products hub's AI card (AGL-2916): what a\n * `products` job proposed, row by row, before anything is written. Every\n * write is one the hub makes when a person asks for it — Apply, Apply to all,\n * Create drafts, Create selected — and the hub passes over what the site\n * already has, so a proposal applied twice creates nothing twice.\n *\n * Each table is one job's whole answer, held in hand and capped by the job\n * (`AI_PRODUCTS_BULK_MAX`, `AI_CATEGORIES_MAX`, `AI_DISCOUNTS_MAX`, a dozen\n * proposed products), so none offers a Filters panel or a search box: a\n * bounded readout is read whole, and a grid that filtered the rows it holds\n * is the pattern every list is leaving (AGL-3321).\n */\n\n/** A column of a review table, in the shared list table's own terms. */\ntype GridColDef = NonNullable<ListTableProps['columns']>[number]\n\nconst clip = (text: string, max: number) => (text.length > max ? `${text.slice(0, max - 1)}…` : text)\n\nconst messageOf = (error: unknown, fallback: string) =>\n error instanceof Error && error.message ? error.message : fallback\n\n/** A discount's offer, in the words the discounts card uses. */\nexport function aiDiscountOffer(discount: AiProposedDiscount): string {\n if (discount.kind === 'percent') return `${discount.valuePct ?? 0}% off`\n if (discount.kind === 'fixed') return `$${((discount.valueCents ?? 0) / 100).toFixed(2)} off`\n return 'Free shipping'\n}\n\nfunction JobState(props: { job: AiJobSummary; doing: string }) {\n const { job } = props\n if (isAiJobMoving(job)) {\n return (\n <Stack direction=\"row\" spacing={1} sx={{ alignItems: 'center' }}>\n <CircularProgress size={16} aria-label={props.doing} />\n <Typography variant=\"body2\" color=\"text.secondary\">\n {props.doing}\n </Typography>\n </Stack>\n )\n }\n return job.error ? <Alert severity={job.status === 'failed' ? 'error' : 'warning'}>{job.error}</Alert> : null\n}\n\n/* ------------------------------------------------------------------------ *\n * Copy for many products\n * ------------------------------------------------------------------------ */\n\ntype RowState = 'applying' | 'applied' | { error: string }\n\nexport function AiBulkCopyReview(props: {\n job: AiJobSummary\n applyProductCopy: ConsoleProductsHubZoneProps['applyProductCopy']\n}) {\n const { job, applyProductCopy } = props\n const proposals = aiProductCopyProposals(job)\n const asked = aiProductsBulkCount(job) ?? proposals.length\n const [rows, setRows] = useState<Record<string, RowState>>({})\n const [applyingAll, setApplyingAll] = useState(false)\n\n const ready = (proposal: AiProductCopyProposal) =>\n Boolean(proposal.values && proposal.product.id) && rows[proposal.product.id as string] !== 'applied'\n\n const apply = useCallback(\n async (proposal: AiProductCopyProposal) => {\n const id = proposal.product.id\n if (!id || !proposal.values) return\n setRows((current) => ({ ...current, [id]: 'applying' }))\n try {\n await applyProductCopy(id, aiProductCopyValues(proposal))\n setRows((current) => ({ ...current, [id]: 'applied' }))\n } catch (error) {\n setRows((current) => ({ ...current, [id]: { error: messageOf(error, 'The copy could not be saved.') } }))\n }\n },\n [applyProductCopy],\n )\n\n /** Applies each proposal in turn, so one refusal names its product and the rest still land. */\n const applyAll = useCallback(\n async (targets: readonly AiProductCopyProposal[]) => {\n setApplyingAll(true)\n try {\n for (const proposal of targets) await apply(proposal)\n } finally {\n setApplyingAll(false)\n }\n },\n [apply],\n )\n\n const columns = useMemo<GridColDef[]>(\n () => [\n { field: 'name', headerName: 'Product', flex: 1, minWidth: 160 },\n { field: 'description', headerName: 'Proposed description', flex: 2, minWidth: 220 },\n { field: 'seoTitle', headerName: 'Search title', flex: 1, minWidth: 160 },\n {\n field: 'actions',\n headerName: '',\n width: 170,\n sortable: false,\n renderCell: ({ row }: { row: { proposal: AiProductCopyProposal } }) => {\n const { proposal } = row\n if (proposal.skipped) return <Chip size=\"small\" variant=\"outlined\" label=\"Skipped\" title={proposal.skipped} />\n const state = proposal.product.id ? rows[proposal.product.id] : undefined\n if (state === 'applied') return <Chip size=\"small\" color=\"success\" variant=\"outlined\" label=\"Applied\" />\n if (typeof state === 'object') return <Chip size=\"small\" color=\"error\" variant=\"outlined\" label=\"Not saved\" title={state.error} />\n return (\n <Button size=\"small\" disabled={state === 'applying' || applyingAll} onClick={() => void apply(proposal)}>\n {'Apply'}\n </Button>\n )\n },\n },\n ],\n [rows, applyingAll, apply],\n )\n\n const tableRows = proposals.map((proposal) => ({\n $id: proposal.product.id ?? proposal.product.name,\n name: proposal.product.name,\n description: proposal.values ? clip(proposal.values.description, 140) : (proposal.skipped ?? ''),\n seoTitle: proposal.values?.seoTitle ?? '',\n proposal,\n }))\n const readyCount = proposals.filter(ready).length\n const errors = Object.values(rows).filter((state): state is { error: string } => typeof state === 'object')\n const gaps = proposals.filter((proposal) => proposal.gaps.length).length\n\n return (\n <Stack spacing={1} aria-label=\"Proposed product copy\">\n <Typography variant=\"subtitle2\">{`Product copy · ${proposals.length} of ${asked}`}</Typography>\n <JobState job={job} doing={`Writing copy: ${proposals.length} of ${asked}`} />\n {tableRows.length ? <ListTable rows={tableRows} columns={columns} hideFooter disableColumnFilter quickFilter={false} /> : null}\n {gaps ? (\n <Alert severity=\"warning\">\n {`${gaps} ${gaps === 1 ? 'description marks' : 'descriptions mark'} facts in [brackets] to fill in before you publish.`}\n </Alert>\n ) : null}\n {errors.length ? <Alert severity=\"error\">{errors[0].error}</Alert> : null}\n <Button\n size=\"small\"\n variant=\"contained\"\n sx={{ alignSelf: 'flex-start' }}\n disabled={!readyCount || applyingAll}\n onClick={() => void applyAll(proposals.filter(ready))}\n >\n {readyCount ? `Apply to all ${readyCount}` : 'Apply to all'}\n </Button>\n </Stack>\n )\n}\n\n/* ------------------------------------------------------------------------ *\n * A store's first products\n * ------------------------------------------------------------------------ */\n\nexport function AiCatalogReview(props: {\n job: AiJobSummary\n heldNames: ReadonlySet<string>\n createProductDrafts: ConsoleProductsHubZoneProps['createProductDrafts']\n}) {\n const { job, heldNames, createProductDrafts } = props\n const proposal = aiProductsProposalOfKind(job, 'catalog')\n const products = useMemo(() => proposal?.products ?? [], [proposal])\n const held = (name: string) => heldNames.has(name.replace(/\\s+/g, ' ').trim().toLowerCase())\n const [selected, setSelected] = useState<string[] | null>(null)\n const [busy, setBusy] = useState(false)\n const [result, setResult] = useState<{ severity: 'success' | 'error'; text: string } | null>(null)\n\n const rows = products.map((product, index) => ({\n $id: `p${index}`,\n name: product.name,\n type: product.type,\n options: product.options.map((option) => `${option.name}: ${option.values.join(', ')}`).join(' · ') || '—',\n photo: product.photo,\n inCatalog: held(product.name),\n product,\n }))\n const chosen = selected ?? rows.filter((row) => !row.inCatalog).map((row) => row.$id)\n\n const columns = useMemo<GridColDef[]>(\n () => [\n { field: 'name', headerName: 'Product', flex: 1, minWidth: 180 },\n { field: 'options', headerName: 'Options', flex: 1, minWidth: 160 },\n {\n field: 'price',\n headerName: 'Price',\n width: 130,\n sortable: false,\n // A suggested price by what the product is (Zach, 2026-10-12), the\n // merchant's to change; a proposal without one takes the default.\n renderCell: ({ row }: { row: { product: { price?: number | null } } }) => {\n const price = aiCatalogPrice(row.product.price)\n return price === null ? (\n <Chip size=\"small\" variant=\"outlined\" label=\"Default price\" />\n ) : (\n <Chip size=\"small\" variant=\"outlined\" label={`$${price.toFixed(2)} suggested`} />\n )\n },\n },\n {\n field: 'photo',\n headerName: 'Photo',\n flex: 1,\n minWidth: 200,\n sortable: false,\n renderCell: ({ row }: { row: { photo: string; inCatalog: boolean } }) => (\n <Stack spacing={0.25} sx={{ py: 0.5 }}>\n <Chip size=\"small\" color=\"warning\" variant=\"outlined\" label=\"Needs a photo\" sx={{ alignSelf: 'flex-start' }} />\n <Typography variant=\"caption\" color=\"text.secondary\" sx={{ whiteSpace: 'normal' }}>\n {row.photo}\n </Typography>\n </Stack>\n ),\n },\n {\n field: 'inCatalog',\n headerName: '',\n width: 150,\n sortable: false,\n renderCell: ({ row }: { row: { inCatalog: boolean } }) =>\n row.inCatalog ? <Chip size=\"small\" variant=\"outlined\" label=\"In your catalog\" /> : null,\n },\n ],\n [],\n )\n\n const create = useCallback(async () => {\n const picks = rows.filter((row) => chosen.includes(row.$id)).map((row) => row.product)\n if (!picks.length) return\n setBusy(true)\n setResult(null)\n try {\n const created = await createProductDrafts(\n picks.map((product) => ({\n name: product.name,\n type: product.type,\n description: product.description,\n tags: product.tags,\n options: product.options,\n seoTitle: product.seoTitle,\n seoDescription: product.seoDescription,\n priceUsd: aiCatalogPrice(product.price),\n })),\n )\n const passed = picks.length - created.length\n setResult({\n severity: 'success',\n text:\n `Created ${created.length} draft ${created.length === 1 ? 'product' : 'products'}. ` +\n 'Review each price and add a photo before you activate it.' +\n (passed ? ` ${passed} already in your catalog ${passed === 1 ? 'was' : 'were'} left as they are.` : ''),\n })\n setSelected([])\n } catch (error) {\n setResult({ severity: 'error', text: messageOf(error, 'The draft products could not be created.') })\n } finally {\n setBusy(false)\n }\n }, [rows, chosen, createProductDrafts])\n\n return (\n <Stack spacing={1} aria-label=\"Proposed products\">\n <Typography variant=\"subtitle2\">{'Proposed products'}</Typography>\n <JobState job={job} doing=\"Proposing products from your brief\" />\n {rows.length ? (\n <>\n <Typography variant=\"body2\" color=\"text.secondary\">\n {'Each is created as a draft at its suggested price, with no photo. Review the price and add a photo ' +\n 'in the product editor, then activate it.'}\n </Typography>\n <ListTable\n rows={rows}\n columns={columns}\n hideFooter\n disableColumnFilter\n quickFilter={false}\n getRowHeight={() => 'auto'}\n selectable={{ selected: chosen, onChange: setSelected }}\n />\n <Button\n size=\"small\"\n variant=\"contained\"\n sx={{ alignSelf: 'flex-start' }}\n disabled={busy || !chosen.length}\n onClick={() => void create()}\n >\n {`Create ${chosen.length} ${chosen.length === 1 ? 'draft' : 'drafts'}`}\n </Button>\n </>\n ) : null}\n {result ? <Alert severity={result.severity}>{result.text}</Alert> : null}\n </Stack>\n )\n}\n\n/* ------------------------------------------------------------------------ *\n * Categories and discounts\n * ------------------------------------------------------------------------ */\n\nexport function AiCategoriesReview(props: {\n job: AiJobSummary\n createCategories: ConsoleProductsHubZoneProps['createCategories']\n createDiscountDrafts: ConsoleProductsHubZoneProps['createDiscountDrafts']\n}) {\n const { job, createCategories, createDiscountDrafts } = props\n const proposal = aiProductsProposalOfKind(job, 'categories')\n const categoryRows = (proposal?.categories ?? []).map((category, index) => ({\n $id: `c${index}`,\n name: category.name,\n why: category.why,\n }))\n const discountRows = (proposal?.discounts ?? []).map((discount, index) => ({\n $id: `d${index}`,\n name: discount.name,\n code: discount.code ?? 'Applies on its own',\n offer: aiDiscountOffer(discount),\n minimum: discount.minSubtotalCents ? `$${(discount.minSubtotalCents / 100).toFixed(2)}` : 'Any order',\n why: discount.why,\n discount,\n }))\n const [categories, setCategories] = useState<string[] | null>(null)\n const [discounts, setDiscounts] = useState<string[] | null>(null)\n const [busy, setBusy] = useState(false)\n const [result, setResult] = useState<{ severity: 'success' | 'error'; text: string } | null>(null)\n const chosenCategories = categories ?? categoryRows.map((row) => row.$id)\n const chosenDiscounts = discounts ?? discountRows.map((row) => row.$id)\n\n const categoryColumns = useMemo<GridColDef[]>(\n () => [\n { field: 'name', headerName: 'Category', flex: 1, minWidth: 160 },\n { field: 'why', headerName: 'Why', flex: 2, minWidth: 220 },\n ],\n [],\n )\n const discountColumns = useMemo<GridColDef[]>(\n () => [\n { field: 'name', headerName: 'Discount', flex: 1, minWidth: 150 },\n { field: 'code', headerName: 'Code', width: 150 },\n { field: 'offer', headerName: 'Offer', width: 120 },\n { field: 'minimum', headerName: 'Minimum order', width: 130 },\n { field: 'why', headerName: 'Why', flex: 2, minWidth: 200 },\n ],\n [],\n )\n\n const create = useCallback(async () => {\n setBusy(true)\n setResult(null)\n try {\n const madeCategories = await createCategories(\n categoryRows.filter((row) => chosenCategories.includes(row.$id)).map((row) => row.name),\n )\n const madeDiscounts = await createDiscountDrafts(\n discountRows\n .filter((row) => chosenDiscounts.includes(row.$id))\n .map(({ discount }) => ({\n name: discount.name,\n code: discount.code,\n kind: discount.kind,\n valuePct: discount.valuePct,\n valueCents: discount.valueCents,\n minSubtotalCents: discount.minSubtotalCents,\n })),\n )\n setResult({\n severity: 'success',\n text:\n `Created ${madeCategories} ${madeCategories === 1 ? 'category' : 'categories'} and ` +\n `${madeDiscounts} ${madeDiscounts === 1 ? 'discount' : 'discounts'}. ` +\n 'Discounts start switched off: switch each on under Promotions when you are ready. ' +\n 'Anything your store already had was left as it is.',\n })\n setCategories([])\n setDiscounts([])\n } catch (error) {\n setResult({ severity: 'error', text: messageOf(error, 'The categories and discounts could not be created.') })\n } finally {\n setBusy(false)\n }\n }, [categoryRows, discountRows, chosenCategories, chosenDiscounts, createCategories, createDiscountDrafts])\n\n const any = chosenCategories.length + chosenDiscounts.length\n return (\n <Stack spacing={1} aria-label=\"Proposed categories and discounts\">\n <Typography variant=\"subtitle2\">{'Proposed categories and discounts'}</Typography>\n <JobState job={job} doing=\"Proposing categories and discounts from your brief\" />\n {categoryRows.length ? (\n <ListTable\n rows={categoryRows}\n columns={categoryColumns}\n hideFooter\n disableColumnFilter\n quickFilter={false}\n selectable={{ selected: chosenCategories, onChange: setCategories }}\n />\n ) : null}\n {discountRows.length ? (\n <ListTable\n rows={discountRows}\n columns={discountColumns}\n hideFooter\n disableColumnFilter\n quickFilter={false}\n selectable={{ selected: chosenDiscounts, onChange: setDiscounts }}\n />\n ) : null}\n {categoryRows.length || discountRows.length ? (\n <Button\n size=\"small\"\n variant=\"contained\"\n sx={{ alignSelf: 'flex-start' }}\n disabled={busy || !any}\n onClick={() => void create()}\n >\n {'Create selected'}\n </Button>\n ) : null}\n {result ? <Alert severity={result.severity}>{result.text}</Alert> : null}\n </Stack>\n )\n}\n"],"names":["ListTable","Alert","Button","Chip","CircularProgress","Stack","Typography","useCallback","useMemo","useState","aiCatalogPrice","aiProductCopyProposals","aiProductsBulkCount","aiProductsProposalOfKind","aiProductCopyValues","isAiJobMoving","clip","text","max","length","slice","messageOf","error","fallback","Error","message","aiDiscountOffer","discount","kind","valuePct","valueCents","toFixed","JobState","props","job","direction","spacing","sx","alignItems","size","aria-label","doing","variant","color","severity","status","AiBulkCopyReview","applyProductCopy","proposals","asked","rows","setRows","applyingAll","setApplyingAll","ready","proposal","Boolean","values","product","id","apply","current","applyAll","targets","columns","field","headerName","flex","minWidth","width","sortable","renderCell","row","skipped","label","title","state","undefined","disabled","onClick","tableRows","map","$id","name","description","seoTitle","readyCount","filter","errors","Object","gaps","hideFooter","disableColumnFilter","quickFilter","alignSelf","AiCatalogReview","heldNames","createProductDrafts","products","held","has","replace","trim","toLowerCase","selected","setSelected","busy","setBusy","result","setResult","index","type","options","option","join","photo","inCatalog","chosen","price","py","whiteSpace","create","picks","includes","created","tags","seoDescription","priceUsd","passed","getRowHeight","selectable","onChange","AiCategoriesReview","createCategories","createDiscountDrafts","categoryRows","categories","category","why","discountRows","discounts","code","offer","minimum","minSubtotalCents","setCategories","setDiscounts","chosenCategories","chosenDiscounts","categoryColumns","discountColumns","madeCategories","madeDiscounts","any"],"mappings":"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"}
@@ -34,7 +34,7 @@ import { FREE_AI_TASTE_CREDITS_PER_MONTH } from "../plan-entitlements.js";
34
34
  import { AI_CREDITS_CONFIRM_CODE, aiCreditRangeText } from "../model/ai-credit-estimate.js";
35
35
  import { AiCreditsPromptNotice } from "./ai-credits-prompt.component.js";
36
36
  import { AI_SITE_START_ANSWERS, AI_SITE_START_TYPES, aiSiteStartBrief, aiSiteStartKind, aiSiteStartInputs, aiSiteStartRefusal } from "../model/ai-site-start.js";
37
- import { AI_SITE_KINDS } from "../model/ai-site-kinds.js";
37
+ import { AI_SITE_KINDS, aiSiteKindOfInputs } from "../model/ai-site-kinds.js";
38
38
  /** The icon each kind of site's card shows. */ const AI_SITE_KIND_ICONS = {
39
39
  business: mdiBriefcaseOutline.path,
40
40
  trades: mdiWrench.path,
@@ -218,8 +218,8 @@ function SectionLabel({ children, help }) {
218
218
  });
219
219
  }
220
220
  export function AiSiteStartCard({ hostId, orgId, orgSlug, host, startBlank, leave, initialAnswers = null }) {
221
- var _ref, _aiFreeSitePrompt;
222
- var _modelChoice_options_options_find, _modelChoice_options;
221
+ var _ref, _aiFreeSitePrompt, _ref1;
222
+ var _modelChoice_options_options_find, _modelChoice_options, _aiSiteKindOfInputs;
223
223
  const { data: user } = useUser();
224
224
  const router = useRouter();
225
225
  // Held in a ref so a request reads WHO is signed in, never the identity of
@@ -451,7 +451,9 @@ export function AiSiteStartCard({ hostId, orgId, orgSlug, host, startBlank, leav
451
451
  ceiling: Math.round(range.ceiling * modelMultiplier)
452
452
  });
453
453
  const estimate = freeTaste ? aiFreeSiteCreditRange(answers.pages) : scaled(aiSiteCreditRange(answers.pages, {
454
- welcomeEmail: answers.welcomeEmail
454
+ welcomeEmail: answers.welcomeEmail,
455
+ // A store's first products and a blog's first posts are part of the start (AGL-3676).
456
+ siteKind: (_ref1 = (_aiSiteKindOfInputs = aiSiteKindOfInputs(aiSiteStartInputs(answers))) == null ? void 0 : _aiSiteKindOfInputs.id) != null ? _ref1 : null
455
457
  }));
456
458
  // A Free start quotes what is LEFT (AGL-3660), shared across the owner's
457
459
  // Free workspaces — never the month's whole allowance as if none were spent.
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../../libs/plugins/ai/src/lib/components/ai-site-start-card.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\n'use client'\n\nimport { lockdownRefusalText, parseLockdownRefusal, PLATFORM_BRAND_NAME } from '@aglyn/aglyn'\nimport { trackEvent } from '@aglyn/aglyn/app-utils/analytics-events'\nimport type { ConsoleHostFirstRunZoneProps } from '@aglyn/aglyn/plugin-manager/feature-plugins'\nimport { ICON_VARIANT_CLOSE } from '@aglyn/shared-data-enums'\nimport {\n mdiAccount,\n mdiBookOpenPageVariant,\n mdiBriefcaseOutline,\n mdiCalendarHeart,\n mdiCamera,\n mdiClockOutline,\n mdiContentCut,\n mdiCreation,\n mdiDumbbell,\n mdiHandHeart,\n mdiHeartPulse,\n mdiHomeCity,\n mdiMusic,\n mdiPaletteOutline,\n mdiRocketLaunch,\n mdiScaleBalance,\n mdiSchool,\n mdiShopping,\n mdiSilverwareForkKnife,\n mdiViewGridOutline,\n mdiWrench,\n mdiYoga,\n mdiPageLayoutHeaderFooter,\n} from '@aglyn/shared-data-mdi'\nimport { pluginDocsHelp } from '@aglyn/aglyn/app-utils/docs-help'\nimport { HelpTip, MdiIcon } from '@aglyn/shared-ui-jsx'\nimport { OptionCardGrid } from '@aglyn/shared-ui-jsx/components/option-card-grid.component'\nimport { authorizedFetch } from '@aglyn/shared-util-http/authorized-token'\nimport { useUser } from '@aglyn/tenant-feature-instance'\nimport {\n Alert,\n AppBar,\n Box,\n Button,\n Card,\n CardActionArea,\n Chip,\n CircularProgress,\n Container,\n Dialog,\n DialogActions,\n DialogContent,\n DialogContentText,\n DialogTitle,\n IconButton,\n MenuItem,\n Stack,\n Step,\n StepLabel,\n Stepper,\n TextField,\n Toolbar,\n Typography,\n} from '@mui/material'\nimport { alpha, type Theme } from '@mui/material/styles'\nimport { useRouter } from 'next/navigation'\nimport {\n useCallback,\n useEffect,\n useId,\n useRef,\n useState,\n type ReactNode,\n type SyntheticEvent,\n} from 'react'\nimport {\n AI_JOB_AUTO_CONFIRM_INPUT,\n AI_SITE_FREE_PAGES,\n AI_SITE_FREE_PAGES_NOTE,\n AI_SITE_SUBMISSION_CHOICES,\n aiFreeCreditsNoneLeftText,\n aiFreeCreditsResetLabel,\n aiFreeSiteCreditRange,\n aiFreeSitePrompt,\n aiSiteCreditRange,\n type AiFreeCreditsLeft,\n aiSitePagesBand,\n type AiSiteSubmissions,\n} from '../model/ai-site-job'\nimport { FREE_AI_TASTE_CREDITS_PER_MONTH } from '../plan-entitlements'\nimport {\n AI_CREDITS_CONFIRM_CODE,\n aiCreditRangeText,\n type AiCreditRange,\n type AiCreditsPrompt,\n} from '../model/ai-credit-estimate'\nimport { AiCreditsPromptNotice } from './ai-credits-prompt.component'\nimport {\n AI_SITE_START_ANSWERS,\n AI_SITE_START_TYPES,\n aiSiteStartBrief,\n aiSiteStartKind,\n aiSiteStartInputs,\n aiSiteStartRefusal,\n type AiSiteStartAnswers,\n} from '../model/ai-site-start'\nimport type { AiJobSummary } from '../model/ai-jobs.types'\nimport { AI_SITE_KINDS } from '../model/ai-site-kinds'\n\n/** The icon each kind of site's card shows. */\nconst AI_SITE_KIND_ICONS: Record<string, string> = {\n business: mdiBriefcaseOutline.path,\n trades: mdiWrench.path,\n professional: mdiScaleBalance.path,\n wellness: mdiHeartPulse.path,\n restaurant: mdiSilverwareForkKnife.path,\n store: mdiShopping.path,\n portfolio: mdiViewGridOutline.path,\n studio: mdiPaletteOutline.path,\n photography: mdiCamera.path,\n blog: mdiBookOpenPageVariant.path,\n events: mdiCalendarHeart.path,\n fitness: mdiDumbbell.path,\n yoga: mdiYoga.path,\n beauty: mdiContentCut.path,\n realestate: mdiHomeCity.path,\n education: mdiSchool.path,\n nonprofit: mdiHandHeart.path,\n music: mdiMusic.path,\n personal: mdiAccount.path,\n landing: mdiRocketLaunch.path,\n 'coming-soon': mdiClockOutline.path,\n}\nimport { AiJobFollow } from './ai-job-follow.component'\nimport { AiModelSelector } from './ai-model-selector.component'\nimport { useAiModelChoice } from './use-ai-model-choice'\nimport { aiCreditsBillingHref, aiSiteBuildHref } from './ai-job-links'\nimport { publishAiJob } from './ai-jobs-store'\n\n/**\n * The guided start (AGL-2918), on the `hostFirstRun` zone of the page a newly\n * created site lands on: a choice, a few questions, and the site scaffold they\n * become.\n *\n * ── Two steps (AGL-3594) ─────────────────────────────────────────────────\n *\n * Step 1 asks how to start, as two equal cards: the starter site — a\n * ready-made home page with a header and footer — or AI. The starter card is\n * the zone's `startBlank`, which gives a site born for the guided start the\n * starter every other new site is born with. The AI card moves to step 2, the\n * questions, which have a Back to step 1.\n *\n * ── A full screen dialog, and therefore three ways out ───────────────────\n *\n * The questions take the whole screen, which is the only presentation that\n * gets them read — but a surface that takes the screen and cannot be left is\n * a funnel, so leaving is drawn first and works three ways on both steps:\n *\n * - the close control at the start of the header,\n * - \"Skip\" at the end of it, named \"Skip and start blank\",\n * - Escape, which `Dialog` reports through `onClose`.\n *\n * Before a job is started all three are the zone's own `startBlank`: the\n * starter site, and no job, no draft, no record of a site half begun. After,\n * they close through `leave`, and the job builds the site.\n *\n * Escape and the close control are DISMISSALS, though, and Skip is a choice\n * (AGL-3660, 2026-10-08). Once anything is typed or picked, a dismissal asks\n * \"Leave without your answers?\" first, focused on Keep editing, so a stray\n * Escape — the second press after closing the model menu was the one in\n * production — can never trade a brief for the starter. Escape that reached\n * the dialog from a portal it does not contain (a menu, a select's list) is\n * that popup's, and the dialog ignores it.\n *\n * The header is the dialog's own chrome rather than part of its body, so the\n * way out cannot be scrolled off, and it is never disabled — least of all\n * while a request is in flight, which is the moment a person most wants it.\n * Nothing is focused ahead of the dialog's own frame, so the first thing a\n * keyboard reaches is the close control.\n *\n * ── It is absent until the route has answered ────────────────────────────\n *\n * The dialog covers the page, so being drawn on a guess is worse here than it\n * is for a card: it would be a takeover every flag-off workspace watches\n * disappear. Nothing renders at all — no `Dialog`, no portal — until the jobs\n * route has admitted this workspace, and a 404, a 403 or an unreachable route\n * is this widget staying absent and the ordinary blank page being all there\n * is. That the widget is mounted is itself the last of a stack of gates: the\n * shell held the plan's `aiGenerative` entitlement, the site's AI switch and\n * the reader's `ai.generate` first. A lockdown is the start door's to say,\n * here, in its own words.\n *\n * ── It builds and publishes for you ──────────────────────────────────────\n *\n * \"Plan my site\" starts a `site` job, which PLANS first: the pages, their\n * addresses, the navigation, the layout, the contact form and a palette. The\n * guided start confirms its own plan (AGL-3594), so the build follows with no\n * approval to make, and the site is published, indexable, when it is done.\n * The person edits or unpublishes it afterwards.\n *\n * ── It stays with the job (AGL-3593) ─────────────────────────────────────\n *\n * Once the job exists the dialog follows it live — planning, the plan with\n * its Confirm, building, then the draft pages to open — so a person never has\n * to leave it to get their site built. \"Open AI jobs\" follows the job in the\n * Assist panel instead; it leaves the guided start the way every other exit\n * does, because the dialog covers the panel it opens.\n */\n\ntype Verdict = 'checking' | 'ready' | 'hidden'\n\ntype Step = 'choose' | 'describe'\n\n/** Labels the dialog for a reader, from its own heading. */\nconst TITLE_ID = 'ai-site-start-title'\n\n/**\n * The takeover's surface, for its paper, its bar and its footer alike: the\n * console page's own background (AGL-3596). The paper sits at elevation 0,\n * which is what keeps MUI's dark-mode elevation overlay off it.\n */\nexport const AI_SITE_START_SURFACE_SX = { bgcolor: 'background.default' } as const\n\n/** The two steps, as the indicator under the header names them. */\nconst STEP_LABELS = ['Choose', 'Describe'] as const\n\n/** The soft round badge an icon sits in, in its accent's tint. */\nfunction IconBadge({ accent, children }: { accent: 'primary' | 'secondary'; children: ReactNode }) {\n return (\n <Box\n aria-hidden\n sx={(theme: Theme) => ({\n width: theme.spacing(9),\n height: theme.spacing(9),\n borderRadius: '50%',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n bgcolor: alpha(theme.palette[accent].main, theme.palette.mode === 'dark' ? 0.24 : 0.12),\n color: `${accent}.main`,\n fontSize: theme.spacing(5.5),\n })}\n >\n {children}\n </Box>\n )\n}\n\n/**\n * One way to start, as a card the whole of which is the button. Its accessible\n * name is its title; its description describes it.\n */\nfunction ChoiceCard({\n accent,\n icon,\n iconId,\n title,\n description,\n busy = false,\n onChoose,\n children,\n}: {\n accent: 'primary' | 'secondary'\n icon: string\n /** Names the icon for a reader of the markup; the icon itself is decorative. */\n iconId: string\n title: string\n description: string\n busy?: boolean\n onChoose: () => void\n children?: ReactNode\n}) {\n const id = useId()\n return (\n <Card\n variant=\"outlined\"\n sx={(theme: Theme) => ({\n borderRadius: 2,\n height: '100%',\n transition: theme.transitions.create(['border-color', 'box-shadow', 'transform'], {\n duration: theme.transitions.duration.shorter,\n }),\n '&:hover, &:focus-within': {\n borderColor: `${accent}.main`,\n boxShadow: theme.shadows[4],\n transform: `translateY(-${theme.spacing(0.25)})`,\n },\n '@media (prefers-reduced-motion: reduce)': {\n transition: 'none',\n '&:hover, &:focus-within': { transform: 'none' },\n },\n })}\n >\n <CardActionArea\n onClick={onChoose}\n disabled={busy}\n aria-labelledby={`${id}-title`}\n aria-describedby={`${id}-description`}\n aria-busy={busy || undefined}\n sx={{ height: '100%', p: { xs: 3, sm: 4 } }}\n >\n <Stack spacing={2} sx={{ alignItems: 'center', textAlign: 'center' }}>\n <IconBadge accent={accent}>\n {busy ? (\n <CircularProgress size=\"1em\" color={accent} aria-label={`${title}…`} />\n ) : (\n <MdiIcon path={icon} data-icon={iconId} aria-hidden />\n )}\n </IconBadge>\n <Typography id={`${id}-title`} variant=\"h6\" component=\"h2\">\n {title}\n </Typography>\n <Typography id={`${id}-description`} variant=\"body2\" color=\"text.secondary\">\n {description}\n </Typography>\n {children}\n </Stack>\n </CardActionArea>\n </Card>\n )\n}\n\n/** A small label above a group of questions. */\n/**\n * Each part of the guided start links its own section of the Start with AI\n * guide (AGL-3660), so a `?` says what that one group of answers changes.\n */\nconst START_HELP = {\n choose: pluginDocsHelp('aiStart', {\n anchor: '#how-do-you-want-to-start',\n excerpt:\n 'The starter site gives you a ready-made home page to edit. Start with AI asks a few questions, then plans, writes and publishes your pages.',\n }),\n business: pluginDocsHelp('aiStart', {\n anchor: '#your-business',\n excerpt:\n 'What kind of site it is picks its style and pages; who it is for is who every page and the contact form are written for.',\n }),\n style: pluginDocsHelp('aiSiteLooks', {\n anchor: '#choose-a-style',\n excerpt:\n 'The style decides the look — theme, colors, fonts, buttons — and which pages the site usually has. Every site gets its own variation.',\n }),\n details: pluginDocsHelp('aiStart', {\n anchor: '#details',\n excerpt:\n 'Where contact form messages go, how many pages to write, and on paid plans whether to draft a welcome email. All can be changed later.',\n }),\n estimate: pluginDocsHelp('aiCredits', {\n anchor: '#before-a-job-starts',\n excerpt:\n 'About what a start like this costs, measured on real builds, and the most it can cost. What it really costs is what each step spends, and you can watch that add up while it runs.',\n }),\n}\n\nfunction SectionLabel({ children, help }: { children: ReactNode; help?: ReturnType<typeof pluginDocsHelp> }) {\n return (\n <Stack direction=\"row\" spacing={0.5} sx={{ alignItems: 'center' }}>\n <Typography variant=\"overline\" color=\"text.secondary\" component=\"h2\" sx={{ display: 'block' }}>\n {children}\n </Typography>\n {help ? <HelpTip {...help} /> : null}\n </Stack>\n )\n}\n\n/**\n * The guided start, as the `hostFirstRun` zone draws it, or reopened on a\n * failed start's own answers (AGL-3596): `initialAnswers` opens it on the\n * questions, filled in, for the person to adjust and start a fresh job.\n */\nexport type AiSiteStartCardProps = ConsoleHostFirstRunZoneProps & {\n initialAnswers?: AiSiteStartAnswers | null\n}\n\nexport function AiSiteStartCard({\n hostId,\n orgId,\n orgSlug,\n host,\n startBlank,\n leave,\n initialAnswers = null,\n}: AiSiteStartCardProps) {\n const { data: user } = useUser()\n const router = useRouter()\n // Held in a ref so a request reads WHO is signed in, never the identity of\n // the object that says so.\n const userRef = useRef(user)\n userRef.current = user\n const uid = user?.uid ?? null\n const [verdict, setVerdict] = useState<Verdict>('checking')\n // Read once: a start reopened on its answers stays one while it is open.\n const reopened = useRef(initialAnswers !== null)\n const [step, setStep] = useState<Step>(initialAnswers ? 'describe' : 'choose')\n const [answers, setAnswers] = useState<AiSiteStartAnswers>(initialAnswers ?? AI_SITE_START_ANSWERS)\n const [busy, setBusy] = useState(false)\n // The starter card's own busy state while `startBlank` runs (AGL-3594).\n const [startingStarter, setStartingStarter] = useState(false)\n const [notice, setNotice] = useState<string | null>(null)\n /** The site job \"Plan my site\" started, as the create door answered with it. */\n const [started, setStarted] = useState<AiJobSummary | null>(null)\n // The Free taste's page band (AGL-3594), read off the verdict request.\n const [freeTaste, setFreeTaste] = useState(false)\n // What the Free workspace has left this month (AGL-3660), as the same read\n // the create door refuses on: the less of its own band and its owner's\n // allowance across their Free workspaces. `null` when the route said none.\n const [freeCredits, setFreeCredits] = useState<AiFreeCreditsLeft | null>(null)\n // \"Leave without your answers?\" (AGL-3660): a dismissal with a brief typed.\n const [confirmingLeave, setConfirmingLeave] = useState(false)\n // The dialog's own root, to tell its Escape from a nested popup's.\n const dialogRef = useRef<HTMLDivElement | null>(null)\n\n useEffect(() => {\n if (!orgId || !uid) return\n let active = true\n void (async () => {\n try {\n const response = await authorizedFetch(\n userRef.current,\n `/api/ai/jobs?orgId=${encodeURIComponent(orgId)}&limit=1`,\n )\n const payload = response.ok ? await response.json().catch(() => null) : null\n if (active) {\n if (payload?.freeTaste === true) {\n setFreeTaste(true)\n const credits = payload?.freeCredits as AiFreeCreditsLeft | undefined\n if (credits && Number.isFinite(credits.left)) setFreeCredits(credits)\n // A reopened start keeps the pages it asked for, within the band.\n setAnswers((current) => ({\n ...current,\n pages: reopened.current ? Math.min(current.pages, AI_SITE_FREE_PAGES.max) : AI_SITE_FREE_PAGES.max,\n welcomeEmail: false,\n }))\n }\n setVerdict(response.status === 404 || response.status === 403 ? 'hidden' : 'ready')\n }\n } catch {\n if (active) setVerdict('hidden')\n }\n })()\n return () => {\n active = false\n }\n }, [orgId, uid])\n\n const answer = useCallback(\n (patch: Partial<AiSiteStartAnswers>) =>\n setAnswers((current) => ({ ...current, ...patch })),\n [],\n )\n\n // A Free start past what is left asks first (AGL-3722): it is admitted on\n // its measured p90, and one past what is left starts only on \"Build what\n // fits\" (pausing with Resume where the credits run out), or smaller as the\n // home page alone. The create door asks the same, so a stale dialog meets\n // the prompt there too (`serverPrompt`). Nothing at all left is a dead\n // stop until the credits renew or the workspace upgrades.\n const [serverPrompt, setServerPrompt] = useState<AiCreditsPrompt | null>(null)\n // The door's prompt was for the pages it was asked with.\n useEffect(() => setServerPrompt(null), [answers.pages])\n const prompt = freeTaste ? (aiFreeSitePrompt(freeCredits, answers.pages) ?? serverPrompt) : null\n const noneLeft = freeTaste && freeCredits !== null && freeCredits.left <= 0\n const refusal = aiSiteStartRefusal(answers, { freeTaste })\n const band = aiSitePagesBand(freeTaste)\n // On a paid plan the person picks the model that builds the site (AGL-3660),\n // Auto by default, from the models their plan allows; every step of the job\n // runs on it. A Free workspace builds on the default and is offered none.\n const modelChoice = useAiModelChoice({ orgId, hostId, surface: 'jobs', kind: 'job.page' })\n // A pick remembered from before needs its cost to estimate by; Auto does not,\n // and the list is otherwise read when the picker opens.\n const { load: loadModels, model: rememberedModel } = modelChoice\n useEffect(() => {\n if (!freeTaste && step === 'describe' && rememberedModel) loadModels()\n }, [freeTaste, step, rememberedModel, loadModels])\n const pickedModel = freeTaste ? null : modelChoice.model\n\n const plan = useCallback(async (options: { creditsConfirmed?: boolean; pages?: number } = {}) => {\n const asked = options.pages ? { ...answers, pages: options.pages } : answers\n if (!orgId || aiSiteStartRefusal(asked, { freeTaste }) || noneLeft) return\n // Past what is left, only an explicit go-ahead starts it.\n if (freeTaste && !options.creditsConfirmed && aiFreeSitePrompt(freeCredits, asked.pages)) return\n if (options.pages) answer({ pages: options.pages })\n setBusy(true)\n setNotice(null)\n setServerPrompt(null)\n try {\n const response = await authorizedFetch(userRef.current, '/api/ai/jobs', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n orgId,\n hostId,\n kind: 'site',\n brief: aiSiteStartBrief(asked),\n // The guided start confirms its own plan (AGL-3594): the build\n // follows the plan with no approval to make.\n inputs: { ...aiSiteStartInputs(asked), [AI_JOB_AUTO_CONFIRM_INPUT]: true },\n ...(pickedModel ? { model: pickedModel } : {}),\n ...(options.creditsConfirmed ? { creditsConfirmed: true } : {}),\n }),\n })\n const payload = await response.json().catch(() => null)\n if (!response.ok) {\n if (response.status === 409 && payload?.code === AI_CREDITS_CONFIRM_CODE && payload?.credits) {\n setServerPrompt(payload.credits as AiCreditsPrompt)\n return\n }\n const locked = parseLockdownRefusal(response.status, payload)\n setNotice(\n locked\n ? lockdownRefusalText(locked)\n : String(payload?.error ?? 'The site could not be started. Try again.'),\n )\n return\n }\n const created = (payload?.job as AiJobSummary | undefined) ?? null\n if (!created) {\n setNotice('The site could not be started. Try again.')\n return\n }\n // The indicator and the launcher count it from the moment it exists.\n publishAiJob(created)\n // Where the next step is (AGL-3594): the site's \"Building your site\"\n // page for this job. The zone closes without the starter first, so the\n // setup page does not ask again behind it.\n const href = aiSiteBuildHref(orgSlug, host, created.id)\n if (href) {\n ;(leave ?? (() => undefined))()\n router.push(href)\n return\n }\n setStarted(created)\n } catch {\n setNotice('The site could not be started. Try again.')\n } finally {\n setBusy(false)\n }\n }, [orgId, hostId, answers, answer, freeTaste, freeCredits, noneLeft, orgSlug, host, leave, router, pickedModel])\n\n const chooseStarter = useCallback(() => {\n setStartingStarter(true)\n trackEvent('site_start_choice', { choice: 'starter' })\n startBlank()\n }, [startBlank])\n\n const chooseAi = useCallback(() => {\n trackEvent('site_start_choice', { choice: 'ai' })\n setStep('describe')\n }, [])\n\n if (verdict !== 'ready') return null\n\n // Before a job is started every way out is the blank site, which writes the\n // starter (AGL-3594); after, it only closes — the job builds the site.\n const exit = started ? (leave ?? startBlank) : startBlank\n // Anything the person typed or picked, which a dismissal must not discard\n // silently (AGL-3660). After a job starts there is nothing left to lose.\n const drafted =\n !started &&\n Boolean(answers.siteType.trim() || answers.audience.trim() || answers.kind !== null)\n // Escape and the close control: a dismissal, never a choice. Escape that\n // bubbled here through React from a portal outside this dialog's own DOM is\n // a nested menu's, already handled there, and is not this dialog's to act on.\n const dismiss = (event?: SyntheticEvent | object, reason?: string) => {\n if (reason === 'escapeKeyDown') {\n const target = (event as SyntheticEvent | undefined)?.target\n const root = dialogRef.current\n if (root && target instanceof Node && !root.contains(target)) return\n }\n if (drafted) setConfirmingLeave(true)\n else exit()\n }\n const leaveDraft = () => {\n setConfirmingLeave(false)\n exit()\n }\n\n // The chosen model's cost against Auto's, as the model list states it.\n const modelMultiplier =\n (pickedModel && modelChoice.options?.options.find((option) => option.id === pickedModel)?.multiplier) || 1\n // What the start is likely to cost and at most (AGL-3722): \"About 137\n // credits (up to 282)\", the measured figures scaled by the chosen model.\n const scaled = (range: AiCreditRange): AiCreditRange => ({\n likely: Math.round(range.likely * modelMultiplier),\n p90: Math.round(range.p90 * modelMultiplier),\n ceiling: Math.round(range.ceiling * modelMultiplier),\n })\n const estimate = freeTaste\n ? aiFreeSiteCreditRange(answers.pages)\n : scaled(aiSiteCreditRange(answers.pages, { welcomeEmail: answers.welcomeEmail }))\n // A Free start quotes what is LEFT (AGL-3660), shared across the owner's\n // Free workspaces — never the month's whole allowance as if none were spent.\n const estimateText = freeTaste\n ? freeCredits\n ? `${aiCreditRangeText(estimate)}. You have ${freeCredits.left.toLocaleString('en-US')} of your ${freeCredits.total.toLocaleString('en-US')} free AI credits left this month, until ${aiFreeCreditsResetLabel(freeCredits.resetsOn)}`\n : `${aiCreditRangeText(estimate)}, of the ${FREE_AI_TASTE_CREDITS_PER_MONTH} AI credits you get free each month`\n : `${aiCreditRangeText(estimate)}, estimated`\n\n const choosing = step === 'choose' && !started\n\n return (\n <Dialog\n open\n fullScreen\n ref={dialogRef}\n onClose={dismiss}\n aria-labelledby={TITLE_ID}\n // The console's own page surface, in both modes. A Dialog's paper sits\n // at elevation 24 by default, and in dark mode MUI lightens an elevated\n // paper with a white overlay, which turned the whole takeover a\n // washed-out gray; the overlay is for floating surfaces, and this one\n // fills the screen, so its paper is flat.\n slotProps={{ paper: { elevation: 0, sx: AI_SITE_START_SURFACE_SX } }}\n >\n {/*\n The way out, before anything it is a way out of: a slim header on the\n paper surface. On a narrow screen it is the TITLE that gives way, so\n the exits keep their words at every width.\n */}\n <AppBar\n position=\"relative\"\n color=\"inherit\"\n elevation={0}\n enableColorOnDark\n sx={{ ...AI_SITE_START_SURFACE_SX, borderBottom: 1, borderColor: 'divider' }}\n >\n <Toolbar variant=\"dense\" sx={{ gap: 1 }}>\n <IconButton\n edge=\"start\"\n color=\"inherit\"\n onClick={() => dismiss()}\n aria-label=\"Close the guided start\"\n >\n <MdiIcon path={ICON_VARIANT_CLOSE.path} />\n </IconButton>\n <Typography\n id={TITLE_ID}\n variant=\"subtitle1\"\n component=\"div\"\n noWrap\n sx={{ textOverflow: 'ellipsis', flex: 1 }}\n >\n {'Start your site'}\n </Typography>\n <Button color=\"inherit\" onClick={exit} aria-label={started ? 'Close' : 'Skip and start blank'}>\n {started ? 'Close' : 'Skip'}\n </Button>\n </Toolbar>\n </AppBar>\n <DialogContent sx={{ px: { xs: 2, sm: 3 } }}>\n <Container maxWidth={choosing ? 'md' : 'sm'} disableGutters sx={{ py: { xs: 3, sm: 5 } }}>\n <Stack spacing={4}>\n <Stepper\n activeStep={choosing ? 0 : 1}\n aria-label={choosing ? 'Step 1 of 2' : 'Step 2 of 2'}\n sx={{ maxWidth: (theme: Theme) => theme.spacing(40), width: '100%', mx: 'auto' }}\n >\n {STEP_LABELS.map((label) => (\n <Step key={label}>\n <StepLabel>{label}</StepLabel>\n </Step>\n ))}\n </Stepper>\n <Stack spacing={1} sx={{ textAlign: choosing ? 'center' : 'left' }}>\n <Typography variant=\"h4\" component=\"h1\">\n {choosing ? 'How do you want to start?' : 'Tell us about your site'}\n </Typography>\n <Typography variant=\"body1\" color=\"text.secondary\">\n {choosing ? <HelpTip sx={{ float: 'right' }} {...START_HELP.choose} /> : null}\n {choosing\n ? 'You can change everything later.'\n : `A few answers and ${PLATFORM_BRAND_NAME} AI plans and writes your pages, then publishes your site.`}\n </Typography>\n </Stack>\n {notice && <Alert severity=\"info\">{notice}</Alert>}\n {step === 'describe' && !started && noneLeft && freeCredits && (\n <Alert\n severity=\"warning\"\n action={\n orgSlug ? (\n <Button color=\"inherit\" size=\"small\" href={aiCreditsBillingHref(orgSlug)}>\n {'Upgrade'}\n </Button>\n ) : undefined\n }\n >\n {aiFreeCreditsNoneLeftText(freeCredits.resetsOn)}\n </Alert>\n )}\n {step === 'describe' && !started && !noneLeft && prompt && (\n <AiCreditsPromptNotice\n prompt={prompt}\n noun=\"site\"\n orgSlug={orgSlug}\n busy={busy}\n onBuildWhatFits={() => void plan({ creditsConfirmed: true })}\n onSmaller={() => void plan({ creditsConfirmed: true, pages: 1 })}\n />\n )}\n {choosing ? (\n <Box\n sx={{\n display: 'grid',\n gridTemplateColumns: { xs: '1fr', sm: '1fr 1fr' },\n gap: 3,\n }}\n >\n <ChoiceCard\n accent=\"secondary\"\n icon={mdiPageLayoutHeaderFooter.path}\n iconId=\"page-layout-header-footer\"\n title=\"Start from the starter site\"\n description=\"A ready-made home page with a header, footer and contact form you can edit.\"\n busy={startingStarter}\n onChoose={chooseStarter}\n />\n <ChoiceCard\n accent=\"primary\"\n icon={mdiCreation.path}\n iconId=\"creation\"\n title=\"Start with AI\"\n description={`Answer a few questions and ${PLATFORM_BRAND_NAME} AI plans your pages.`}\n onChoose={chooseAi}\n >\n <Chip size=\"small\" color=\"primary\" label=\"Recommended\" />\n {freeTaste && (\n <Typography variant=\"caption\" color=\"text.secondary\">\n {`Up to ${AI_SITE_FREE_PAGES.max} pages on the Free plan`}\n </Typography>\n )}\n </ChoiceCard>\n </Box>\n ) : started && orgId ? (\n <Card variant=\"outlined\" sx={{ borderRadius: 2, p: { xs: 2, sm: 3 } }}>\n <AiJobFollow\n job={started}\n orgId={orgId}\n orgSlug={orgSlug}\n user={user}\n intro={\n 'Your site is being planned. It is then built and published for you, with ' +\n 'nothing to approve. You can edit or unpublish it afterwards.'\n }\n // Full screen: AI jobs opens in the panel this dialog covers.\n onOpenJobs={exit}\n />\n </Card>\n ) : (\n <>\n <Stack spacing={2} component=\"section\" aria-label=\"Your business\">\n <SectionLabel help={START_HELP.business}>{'Your business'}</SectionLabel>\n <TextField\n fullWidth\n required\n label=\"What kind of site are you creating?\"\n placeholder=\"a neighborhood dog groomer that takes bookings\"\n value={answers.siteType}\n onChange={(event) => answer({ siteType: event.target.value })}\n helperText=\"A few words is enough, or pick one below.\"\n />\n <Box sx={{ display: 'flex', flexWrap: 'wrap', gap: 1 }}>\n {AI_SITE_START_TYPES.map((type) => (\n <Chip\n key={type}\n label={type}\n size=\"small\"\n color={answers.siteType === type ? 'primary' : 'default'}\n variant={answers.siteType === type ? 'filled' : 'outlined'}\n onClick={() => answer({ siteType: type })}\n />\n ))}\n </Box>\n <TextField\n fullWidth\n label=\"Who is it for?\"\n placeholder=\"local dog owners who want a regular groom booked online\"\n value={answers.audience}\n onChange={(event) => answer({ audience: event.target.value })}\n helperText=\"Optional. It narrows who the pages are written for.\"\n />\n </Stack>\n <Stack spacing={2} component=\"section\" aria-label=\"Style\">\n <SectionLabel help={START_HELP.style}>{'Style'}</SectionLabel>\n <Typography variant=\"body2\" color=\"text.secondary\">\n {answers.kind\n ? 'This decides how your site looks and which pages it usually has.'\n : 'Picked from your answer above. Choose another to change how your site looks and which pages it usually has.'}\n </Typography>\n <OptionCardGrid\n label=\"Style of site\"\n options={AI_SITE_KINDS.map((kind) => ({\n id: kind.id,\n title: kind.label,\n description: kind.blurb,\n icon: AI_SITE_KIND_ICONS[kind.id],\n }))}\n value={aiSiteStartKind(answers).id}\n onChange={(kind) => answer({ kind })}\n />\n </Stack>\n <Stack spacing={2} component=\"section\" aria-label=\"Details\">\n <SectionLabel help={START_HELP.details}>{'Details'}</SectionLabel>\n {/*\n The one setting a new site owner has to make, asked where\n they are already answering: a contact form nobody routed\n files its messages somewhere the person has not looked.\n */}\n <TextField\n select\n fullWidth\n label=\"Where do form submissions go?\"\n value={answers.submissions}\n onChange={(event) =>\n answer({ submissions: event.target.value as AiSiteSubmissions })\n }\n helperText=\"You can change this on the form itself afterwards.\"\n >\n {AI_SITE_SUBMISSION_CHOICES.map((option) => (\n <MenuItem key={option.id} value={option.id}>\n {`${option.label} — ${option.blurb}`}\n </MenuItem>\n ))}\n </TextField>\n <Stack direction={{ xs: 'column', sm: 'row' }} spacing={2}>\n <TextField\n select\n fullWidth\n label=\"Pages\"\n value={answers.pages}\n onChange={(event) => answer({ pages: Number(event.target.value) })}\n helperText={freeTaste ? AI_SITE_FREE_PAGES_NOTE : undefined}\n >\n {Array.from(\n { length: band.max - band.min + 1 },\n (_, index) => band.min + index,\n ).map((count) => (\n <MenuItem key={count} value={count}>\n {count}\n </MenuItem>\n ))}\n </TextField>\n {!freeTaste && (\n <TextField\n select\n fullWidth\n label=\"Welcome email\"\n value={answers.welcomeEmail ? 'yes' : 'no'}\n onChange={(event) => answer({ welcomeEmail: event.target.value === 'yes' })}\n >\n <MenuItem value=\"yes\">{'Draft one'}</MenuItem>\n <MenuItem value=\"no\">{'No'}</MenuItem>\n </TextField>\n )}\n </Stack>\n </Stack>\n </>\n )}\n </Stack>\n </Container>\n </DialogContent>\n {step === 'describe' && !started && (\n /* The footer stays put while the questions scroll. It wraps, because\n the estimate, the reason and the buttons are wider than a phone. */\n <DialogActions\n sx={{\n px: { xs: 2, sm: 3 },\n py: 2,\n flexWrap: 'wrap',\n rowGap: 1,\n columnGap: 2,\n borderTop: 1,\n borderColor: 'divider',\n ...AI_SITE_START_SURFACE_SX,\n }}\n >\n <Stack direction=\"row\" spacing={0.5} sx={{ alignItems: 'center', mr: 'auto', minWidth: 0 }}>\n <Typography variant=\"body2\" color=\"text.secondary\">\n {`${estimateText}.`}\n </Typography>\n <HelpTip {...START_HELP.estimate} ariaLabel=\"How the estimate works\" />\n </Stack>\n {refusal && (\n <Typography variant=\"body2\" color=\"text.secondary\">\n {refusal}\n </Typography>\n )}\n {!freeTaste && <AiModelSelector choice={modelChoice} disabled={busy} />}\n <Button onClick={() => setStep('choose')}>{'Back'}</Button>\n <Button\n variant=\"contained\"\n size=\"large\"\n disabled={busy || Boolean(refusal) || Boolean(prompt) || noneLeft}\n onClick={() => void plan()}\n startIcon={<MdiIcon path={mdiCreation.path} />}\n >\n {busy ? 'Starting…' : 'Plan my site'}\n </Button>\n </DialogActions>\n )}\n <Dialog\n open={confirmingLeave}\n onClose={() => setConfirmingLeave(false)}\n aria-labelledby={`${TITLE_ID}-leave`}\n aria-describedby={`${TITLE_ID}-leave-text`}\n maxWidth=\"xs\"\n >\n <DialogTitle id={`${TITLE_ID}-leave`}>{'Leave without your answers?'}</DialogTitle>\n <DialogContent>\n <DialogContentText id={`${TITLE_ID}-leave-text`}>\n {'What you typed is not saved. Leaving starts your site from the starter site instead.'}\n </DialogContentText>\n </DialogContent>\n <DialogActions>\n <Button color=\"inherit\" onClick={leaveDraft}>\n {'Leave and start blank'}\n </Button>\n <Button variant=\"contained\" autoFocus onClick={() => setConfirmingLeave(false)}>\n {'Keep editing'}\n </Button>\n </DialogActions>\n </Dialog>\n </Dialog>\n )\n}\n\nexport default AiSiteStartCard\n"],"names":["lockdownRefusalText","parseLockdownRefusal","PLATFORM_BRAND_NAME","trackEvent","ICON_VARIANT_CLOSE","mdiAccount","mdiBookOpenPageVariant","mdiBriefcaseOutline","mdiCalendarHeart","mdiCamera","mdiClockOutline","mdiContentCut","mdiCreation","mdiDumbbell","mdiHandHeart","mdiHeartPulse","mdiHomeCity","mdiMusic","mdiPaletteOutline","mdiRocketLaunch","mdiScaleBalance","mdiSchool","mdiShopping","mdiSilverwareForkKnife","mdiViewGridOutline","mdiWrench","mdiYoga","mdiPageLayoutHeaderFooter","pluginDocsHelp","HelpTip","MdiIcon","OptionCardGrid","authorizedFetch","useUser","Alert","AppBar","Box","Button","Card","CardActionArea","Chip","CircularProgress","Container","Dialog","DialogActions","DialogContent","DialogContentText","DialogTitle","IconButton","MenuItem","Stack","Step","StepLabel","Stepper","TextField","Toolbar","Typography","alpha","useRouter","useCallback","useEffect","useId","useRef","useState","AI_JOB_AUTO_CONFIRM_INPUT","AI_SITE_FREE_PAGES","AI_SITE_FREE_PAGES_NOTE","AI_SITE_SUBMISSION_CHOICES","aiFreeCreditsNoneLeftText","aiFreeCreditsResetLabel","aiFreeSiteCreditRange","aiFreeSitePrompt","aiSiteCreditRange","aiSitePagesBand","FREE_AI_TASTE_CREDITS_PER_MONTH","AI_CREDITS_CONFIRM_CODE","aiCreditRangeText","AiCreditsPromptNotice","AI_SITE_START_ANSWERS","AI_SITE_START_TYPES","aiSiteStartBrief","aiSiteStartKind","aiSiteStartInputs","aiSiteStartRefusal","AI_SITE_KINDS","AI_SITE_KIND_ICONS","business","path","trades","professional","wellness","restaurant","store","portfolio","studio","photography","blog","events","fitness","yoga","beauty","realestate","education","nonprofit","music","personal","landing","AiJobFollow","AiModelSelector","useAiModelChoice","aiCreditsBillingHref","aiSiteBuildHref","publishAiJob","TITLE_ID","AI_SITE_START_SURFACE_SX","bgcolor","STEP_LABELS","IconBadge","accent","children","aria-hidden","sx","theme","width","spacing","height","borderRadius","display","alignItems","justifyContent","palette","main","mode","color","fontSize","ChoiceCard","icon","iconId","title","description","busy","onChoose","id","variant","transition","transitions","create","duration","shorter","borderColor","boxShadow","shadows","transform","onClick","disabled","aria-labelledby","aria-describedby","aria-busy","undefined","p","xs","sm","textAlign","size","aria-label","data-icon","component","START_HELP","choose","anchor","excerpt","style","details","estimate","SectionLabel","help","direction","AiSiteStartCard","hostId","orgId","orgSlug","host","startBlank","leave","initialAnswers","modelChoice","data","user","router","userRef","current","uid","verdict","setVerdict","reopened","step","setStep","answers","setAnswers","setBusy","startingStarter","setStartingStarter","notice","setNotice","started","setStarted","freeTaste","setFreeTaste","freeCredits","setFreeCredits","confirmingLeave","setConfirmingLeave","dialogRef","active","response","encodeURIComponent","payload","ok","json","catch","credits","Number","isFinite","left","pages","Math","min","max","welcomeEmail","status","answer","patch","serverPrompt","setServerPrompt","prompt","noneLeft","refusal","band","surface","kind","load","loadModels","model","rememberedModel","pickedModel","plan","options","asked","creditsConfirmed","method","headers","body","JSON","stringify","brief","inputs","code","locked","String","error","created","job","href","push","chooseStarter","choice","chooseAi","exit","drafted","Boolean","siteType","trim","audience","dismiss","event","reason","target","root","Node","contains","leaveDraft","modelMultiplier","find","option","multiplier","scaled","range","likely","round","p90","ceiling","estimateText","toLocaleString","total","resetsOn","choosing","open","fullScreen","ref","onClose","slotProps","paper","elevation","position","enableColorOnDark","borderBottom","gap","edge","noWrap","textOverflow","flex","px","maxWidth","disableGutters","py","activeStep","mx","map","label","float","severity","action","noun","onBuildWhatFits","onSmaller","gridTemplateColumns","intro","onOpenJobs","fullWidth","required","placeholder","value","onChange","helperText","flexWrap","type","blurb","select","submissions","Array","from","length","_","index","count","rowGap","columnGap","borderTop","mr","minWidth","ariaLabel","startIcon","autoFocus"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../../../../libs/plugins/ai/src/lib/components/ai-site-start-card.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\n'use client'\n\nimport { lockdownRefusalText, parseLockdownRefusal, PLATFORM_BRAND_NAME } from '@aglyn/aglyn'\nimport { trackEvent } from '@aglyn/aglyn/app-utils/analytics-events'\nimport type { ConsoleHostFirstRunZoneProps } from '@aglyn/aglyn/plugin-manager/feature-plugins'\nimport { ICON_VARIANT_CLOSE } from '@aglyn/shared-data-enums'\nimport {\n mdiAccount,\n mdiBookOpenPageVariant,\n mdiBriefcaseOutline,\n mdiCalendarHeart,\n mdiCamera,\n mdiClockOutline,\n mdiContentCut,\n mdiCreation,\n mdiDumbbell,\n mdiHandHeart,\n mdiHeartPulse,\n mdiHomeCity,\n mdiMusic,\n mdiPaletteOutline,\n mdiRocketLaunch,\n mdiScaleBalance,\n mdiSchool,\n mdiShopping,\n mdiSilverwareForkKnife,\n mdiViewGridOutline,\n mdiWrench,\n mdiYoga,\n mdiPageLayoutHeaderFooter,\n} from '@aglyn/shared-data-mdi'\nimport { pluginDocsHelp } from '@aglyn/aglyn/app-utils/docs-help'\nimport { HelpTip, MdiIcon } from '@aglyn/shared-ui-jsx'\nimport { OptionCardGrid } from '@aglyn/shared-ui-jsx/components/option-card-grid.component'\nimport { authorizedFetch } from '@aglyn/shared-util-http/authorized-token'\nimport { useUser } from '@aglyn/tenant-feature-instance'\nimport {\n Alert,\n AppBar,\n Box,\n Button,\n Card,\n CardActionArea,\n Chip,\n CircularProgress,\n Container,\n Dialog,\n DialogActions,\n DialogContent,\n DialogContentText,\n DialogTitle,\n IconButton,\n MenuItem,\n Stack,\n Step,\n StepLabel,\n Stepper,\n TextField,\n Toolbar,\n Typography,\n} from '@mui/material'\nimport { alpha, type Theme } from '@mui/material/styles'\nimport { useRouter } from 'next/navigation'\nimport {\n useCallback,\n useEffect,\n useId,\n useRef,\n useState,\n type ReactNode,\n type SyntheticEvent,\n} from 'react'\nimport {\n AI_JOB_AUTO_CONFIRM_INPUT,\n AI_SITE_FREE_PAGES,\n AI_SITE_FREE_PAGES_NOTE,\n AI_SITE_SUBMISSION_CHOICES,\n aiFreeCreditsNoneLeftText,\n aiFreeCreditsResetLabel,\n aiFreeSiteCreditRange,\n aiFreeSitePrompt,\n aiSiteCreditRange,\n type AiFreeCreditsLeft,\n aiSitePagesBand,\n type AiSiteSubmissions,\n} from '../model/ai-site-job'\nimport { FREE_AI_TASTE_CREDITS_PER_MONTH } from '../plan-entitlements'\nimport {\n AI_CREDITS_CONFIRM_CODE,\n aiCreditRangeText,\n type AiCreditRange,\n type AiCreditsPrompt,\n} from '../model/ai-credit-estimate'\nimport { AiCreditsPromptNotice } from './ai-credits-prompt.component'\nimport {\n AI_SITE_START_ANSWERS,\n AI_SITE_START_TYPES,\n aiSiteStartBrief,\n aiSiteStartKind,\n aiSiteStartInputs,\n aiSiteStartRefusal,\n type AiSiteStartAnswers,\n} from '../model/ai-site-start'\nimport type { AiJobSummary } from '../model/ai-jobs.types'\nimport { AI_SITE_KINDS, aiSiteKindOfInputs } from '../model/ai-site-kinds'\n\n/** The icon each kind of site's card shows. */\nconst AI_SITE_KIND_ICONS: Record<string, string> = {\n business: mdiBriefcaseOutline.path,\n trades: mdiWrench.path,\n professional: mdiScaleBalance.path,\n wellness: mdiHeartPulse.path,\n restaurant: mdiSilverwareForkKnife.path,\n store: mdiShopping.path,\n portfolio: mdiViewGridOutline.path,\n studio: mdiPaletteOutline.path,\n photography: mdiCamera.path,\n blog: mdiBookOpenPageVariant.path,\n events: mdiCalendarHeart.path,\n fitness: mdiDumbbell.path,\n yoga: mdiYoga.path,\n beauty: mdiContentCut.path,\n realestate: mdiHomeCity.path,\n education: mdiSchool.path,\n nonprofit: mdiHandHeart.path,\n music: mdiMusic.path,\n personal: mdiAccount.path,\n landing: mdiRocketLaunch.path,\n 'coming-soon': mdiClockOutline.path,\n}\nimport { AiJobFollow } from './ai-job-follow.component'\nimport { AiModelSelector } from './ai-model-selector.component'\nimport { useAiModelChoice } from './use-ai-model-choice'\nimport { aiCreditsBillingHref, aiSiteBuildHref } from './ai-job-links'\nimport { publishAiJob } from './ai-jobs-store'\n\n/**\n * The guided start (AGL-2918), on the `hostFirstRun` zone of the page a newly\n * created site lands on: a choice, a few questions, and the site scaffold they\n * become.\n *\n * ── Two steps (AGL-3594) ─────────────────────────────────────────────────\n *\n * Step 1 asks how to start, as two equal cards: the starter site — a\n * ready-made home page with a header and footer — or AI. The starter card is\n * the zone's `startBlank`, which gives a site born for the guided start the\n * starter every other new site is born with. The AI card moves to step 2, the\n * questions, which have a Back to step 1.\n *\n * ── A full screen dialog, and therefore three ways out ───────────────────\n *\n * The questions take the whole screen, which is the only presentation that\n * gets them read — but a surface that takes the screen and cannot be left is\n * a funnel, so leaving is drawn first and works three ways on both steps:\n *\n * - the close control at the start of the header,\n * - \"Skip\" at the end of it, named \"Skip and start blank\",\n * - Escape, which `Dialog` reports through `onClose`.\n *\n * Before a job is started all three are the zone's own `startBlank`: the\n * starter site, and no job, no draft, no record of a site half begun. After,\n * they close through `leave`, and the job builds the site.\n *\n * Escape and the close control are DISMISSALS, though, and Skip is a choice\n * (AGL-3660, 2026-10-08). Once anything is typed or picked, a dismissal asks\n * \"Leave without your answers?\" first, focused on Keep editing, so a stray\n * Escape — the second press after closing the model menu was the one in\n * production — can never trade a brief for the starter. Escape that reached\n * the dialog from a portal it does not contain (a menu, a select's list) is\n * that popup's, and the dialog ignores it.\n *\n * The header is the dialog's own chrome rather than part of its body, so the\n * way out cannot be scrolled off, and it is never disabled — least of all\n * while a request is in flight, which is the moment a person most wants it.\n * Nothing is focused ahead of the dialog's own frame, so the first thing a\n * keyboard reaches is the close control.\n *\n * ── It is absent until the route has answered ────────────────────────────\n *\n * The dialog covers the page, so being drawn on a guess is worse here than it\n * is for a card: it would be a takeover every flag-off workspace watches\n * disappear. Nothing renders at all — no `Dialog`, no portal — until the jobs\n * route has admitted this workspace, and a 404, a 403 or an unreachable route\n * is this widget staying absent and the ordinary blank page being all there\n * is. That the widget is mounted is itself the last of a stack of gates: the\n * shell held the plan's `aiGenerative` entitlement, the site's AI switch and\n * the reader's `ai.generate` first. A lockdown is the start door's to say,\n * here, in its own words.\n *\n * ── It builds and publishes for you ──────────────────────────────────────\n *\n * \"Plan my site\" starts a `site` job, which PLANS first: the pages, their\n * addresses, the navigation, the layout, the contact form and a palette. The\n * guided start confirms its own plan (AGL-3594), so the build follows with no\n * approval to make, and the site is published, indexable, when it is done.\n * The person edits or unpublishes it afterwards.\n *\n * ── It stays with the job (AGL-3593) ─────────────────────────────────────\n *\n * Once the job exists the dialog follows it live — planning, the plan with\n * its Confirm, building, then the draft pages to open — so a person never has\n * to leave it to get their site built. \"Open AI jobs\" follows the job in the\n * Assist panel instead; it leaves the guided start the way every other exit\n * does, because the dialog covers the panel it opens.\n */\n\ntype Verdict = 'checking' | 'ready' | 'hidden'\n\ntype Step = 'choose' | 'describe'\n\n/** Labels the dialog for a reader, from its own heading. */\nconst TITLE_ID = 'ai-site-start-title'\n\n/**\n * The takeover's surface, for its paper, its bar and its footer alike: the\n * console page's own background (AGL-3596). The paper sits at elevation 0,\n * which is what keeps MUI's dark-mode elevation overlay off it.\n */\nexport const AI_SITE_START_SURFACE_SX = { bgcolor: 'background.default' } as const\n\n/** The two steps, as the indicator under the header names them. */\nconst STEP_LABELS = ['Choose', 'Describe'] as const\n\n/** The soft round badge an icon sits in, in its accent's tint. */\nfunction IconBadge({ accent, children }: { accent: 'primary' | 'secondary'; children: ReactNode }) {\n return (\n <Box\n aria-hidden\n sx={(theme: Theme) => ({\n width: theme.spacing(9),\n height: theme.spacing(9),\n borderRadius: '50%',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n bgcolor: alpha(theme.palette[accent].main, theme.palette.mode === 'dark' ? 0.24 : 0.12),\n color: `${accent}.main`,\n fontSize: theme.spacing(5.5),\n })}\n >\n {children}\n </Box>\n )\n}\n\n/**\n * One way to start, as a card the whole of which is the button. Its accessible\n * name is its title; its description describes it.\n */\nfunction ChoiceCard({\n accent,\n icon,\n iconId,\n title,\n description,\n busy = false,\n onChoose,\n children,\n}: {\n accent: 'primary' | 'secondary'\n icon: string\n /** Names the icon for a reader of the markup; the icon itself is decorative. */\n iconId: string\n title: string\n description: string\n busy?: boolean\n onChoose: () => void\n children?: ReactNode\n}) {\n const id = useId()\n return (\n <Card\n variant=\"outlined\"\n sx={(theme: Theme) => ({\n borderRadius: 2,\n height: '100%',\n transition: theme.transitions.create(['border-color', 'box-shadow', 'transform'], {\n duration: theme.transitions.duration.shorter,\n }),\n '&:hover, &:focus-within': {\n borderColor: `${accent}.main`,\n boxShadow: theme.shadows[4],\n transform: `translateY(-${theme.spacing(0.25)})`,\n },\n '@media (prefers-reduced-motion: reduce)': {\n transition: 'none',\n '&:hover, &:focus-within': { transform: 'none' },\n },\n })}\n >\n <CardActionArea\n onClick={onChoose}\n disabled={busy}\n aria-labelledby={`${id}-title`}\n aria-describedby={`${id}-description`}\n aria-busy={busy || undefined}\n sx={{ height: '100%', p: { xs: 3, sm: 4 } }}\n >\n <Stack spacing={2} sx={{ alignItems: 'center', textAlign: 'center' }}>\n <IconBadge accent={accent}>\n {busy ? (\n <CircularProgress size=\"1em\" color={accent} aria-label={`${title}…`} />\n ) : (\n <MdiIcon path={icon} data-icon={iconId} aria-hidden />\n )}\n </IconBadge>\n <Typography id={`${id}-title`} variant=\"h6\" component=\"h2\">\n {title}\n </Typography>\n <Typography id={`${id}-description`} variant=\"body2\" color=\"text.secondary\">\n {description}\n </Typography>\n {children}\n </Stack>\n </CardActionArea>\n </Card>\n )\n}\n\n/** A small label above a group of questions. */\n/**\n * Each part of the guided start links its own section of the Start with AI\n * guide (AGL-3660), so a `?` says what that one group of answers changes.\n */\nconst START_HELP = {\n choose: pluginDocsHelp('aiStart', {\n anchor: '#how-do-you-want-to-start',\n excerpt:\n 'The starter site gives you a ready-made home page to edit. Start with AI asks a few questions, then plans, writes and publishes your pages.',\n }),\n business: pluginDocsHelp('aiStart', {\n anchor: '#your-business',\n excerpt:\n 'What kind of site it is picks its style and pages; who it is for is who every page and the contact form are written for.',\n }),\n style: pluginDocsHelp('aiSiteLooks', {\n anchor: '#choose-a-style',\n excerpt:\n 'The style decides the look — theme, colors, fonts, buttons — and which pages the site usually has. Every site gets its own variation.',\n }),\n details: pluginDocsHelp('aiStart', {\n anchor: '#details',\n excerpt:\n 'Where contact form messages go, how many pages to write, and on paid plans whether to draft a welcome email. All can be changed later.',\n }),\n estimate: pluginDocsHelp('aiCredits', {\n anchor: '#before-a-job-starts',\n excerpt:\n 'About what a start like this costs, measured on real builds, and the most it can cost. What it really costs is what each step spends, and you can watch that add up while it runs.',\n }),\n}\n\nfunction SectionLabel({ children, help }: { children: ReactNode; help?: ReturnType<typeof pluginDocsHelp> }) {\n return (\n <Stack direction=\"row\" spacing={0.5} sx={{ alignItems: 'center' }}>\n <Typography variant=\"overline\" color=\"text.secondary\" component=\"h2\" sx={{ display: 'block' }}>\n {children}\n </Typography>\n {help ? <HelpTip {...help} /> : null}\n </Stack>\n )\n}\n\n/**\n * The guided start, as the `hostFirstRun` zone draws it, or reopened on a\n * failed start's own answers (AGL-3596): `initialAnswers` opens it on the\n * questions, filled in, for the person to adjust and start a fresh job.\n */\nexport type AiSiteStartCardProps = ConsoleHostFirstRunZoneProps & {\n initialAnswers?: AiSiteStartAnswers | null\n}\n\nexport function AiSiteStartCard({\n hostId,\n orgId,\n orgSlug,\n host,\n startBlank,\n leave,\n initialAnswers = null,\n}: AiSiteStartCardProps) {\n const { data: user } = useUser()\n const router = useRouter()\n // Held in a ref so a request reads WHO is signed in, never the identity of\n // the object that says so.\n const userRef = useRef(user)\n userRef.current = user\n const uid = user?.uid ?? null\n const [verdict, setVerdict] = useState<Verdict>('checking')\n // Read once: a start reopened on its answers stays one while it is open.\n const reopened = useRef(initialAnswers !== null)\n const [step, setStep] = useState<Step>(initialAnswers ? 'describe' : 'choose')\n const [answers, setAnswers] = useState<AiSiteStartAnswers>(initialAnswers ?? AI_SITE_START_ANSWERS)\n const [busy, setBusy] = useState(false)\n // The starter card's own busy state while `startBlank` runs (AGL-3594).\n const [startingStarter, setStartingStarter] = useState(false)\n const [notice, setNotice] = useState<string | null>(null)\n /** The site job \"Plan my site\" started, as the create door answered with it. */\n const [started, setStarted] = useState<AiJobSummary | null>(null)\n // The Free taste's page band (AGL-3594), read off the verdict request.\n const [freeTaste, setFreeTaste] = useState(false)\n // What the Free workspace has left this month (AGL-3660), as the same read\n // the create door refuses on: the less of its own band and its owner's\n // allowance across their Free workspaces. `null` when the route said none.\n const [freeCredits, setFreeCredits] = useState<AiFreeCreditsLeft | null>(null)\n // \"Leave without your answers?\" (AGL-3660): a dismissal with a brief typed.\n const [confirmingLeave, setConfirmingLeave] = useState(false)\n // The dialog's own root, to tell its Escape from a nested popup's.\n const dialogRef = useRef<HTMLDivElement | null>(null)\n\n useEffect(() => {\n if (!orgId || !uid) return\n let active = true\n void (async () => {\n try {\n const response = await authorizedFetch(\n userRef.current,\n `/api/ai/jobs?orgId=${encodeURIComponent(orgId)}&limit=1`,\n )\n const payload = response.ok ? await response.json().catch(() => null) : null\n if (active) {\n if (payload?.freeTaste === true) {\n setFreeTaste(true)\n const credits = payload?.freeCredits as AiFreeCreditsLeft | undefined\n if (credits && Number.isFinite(credits.left)) setFreeCredits(credits)\n // A reopened start keeps the pages it asked for, within the band.\n setAnswers((current) => ({\n ...current,\n pages: reopened.current ? Math.min(current.pages, AI_SITE_FREE_PAGES.max) : AI_SITE_FREE_PAGES.max,\n welcomeEmail: false,\n }))\n }\n setVerdict(response.status === 404 || response.status === 403 ? 'hidden' : 'ready')\n }\n } catch {\n if (active) setVerdict('hidden')\n }\n })()\n return () => {\n active = false\n }\n }, [orgId, uid])\n\n const answer = useCallback(\n (patch: Partial<AiSiteStartAnswers>) =>\n setAnswers((current) => ({ ...current, ...patch })),\n [],\n )\n\n // A Free start past what is left asks first (AGL-3722): it is admitted on\n // its measured p90, and one past what is left starts only on \"Build what\n // fits\" (pausing with Resume where the credits run out), or smaller as the\n // home page alone. The create door asks the same, so a stale dialog meets\n // the prompt there too (`serverPrompt`). Nothing at all left is a dead\n // stop until the credits renew or the workspace upgrades.\n const [serverPrompt, setServerPrompt] = useState<AiCreditsPrompt | null>(null)\n // The door's prompt was for the pages it was asked with.\n useEffect(() => setServerPrompt(null), [answers.pages])\n const prompt = freeTaste ? (aiFreeSitePrompt(freeCredits, answers.pages) ?? serverPrompt) : null\n const noneLeft = freeTaste && freeCredits !== null && freeCredits.left <= 0\n const refusal = aiSiteStartRefusal(answers, { freeTaste })\n const band = aiSitePagesBand(freeTaste)\n // On a paid plan the person picks the model that builds the site (AGL-3660),\n // Auto by default, from the models their plan allows; every step of the job\n // runs on it. A Free workspace builds on the default and is offered none.\n const modelChoice = useAiModelChoice({ orgId, hostId, surface: 'jobs', kind: 'job.page' })\n // A pick remembered from before needs its cost to estimate by; Auto does not,\n // and the list is otherwise read when the picker opens.\n const { load: loadModels, model: rememberedModel } = modelChoice\n useEffect(() => {\n if (!freeTaste && step === 'describe' && rememberedModel) loadModels()\n }, [freeTaste, step, rememberedModel, loadModels])\n const pickedModel = freeTaste ? null : modelChoice.model\n\n const plan = useCallback(async (options: { creditsConfirmed?: boolean; pages?: number } = {}) => {\n const asked = options.pages ? { ...answers, pages: options.pages } : answers\n if (!orgId || aiSiteStartRefusal(asked, { freeTaste }) || noneLeft) return\n // Past what is left, only an explicit go-ahead starts it.\n if (freeTaste && !options.creditsConfirmed && aiFreeSitePrompt(freeCredits, asked.pages)) return\n if (options.pages) answer({ pages: options.pages })\n setBusy(true)\n setNotice(null)\n setServerPrompt(null)\n try {\n const response = await authorizedFetch(userRef.current, '/api/ai/jobs', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n orgId,\n hostId,\n kind: 'site',\n brief: aiSiteStartBrief(asked),\n // The guided start confirms its own plan (AGL-3594): the build\n // follows the plan with no approval to make.\n inputs: { ...aiSiteStartInputs(asked), [AI_JOB_AUTO_CONFIRM_INPUT]: true },\n ...(pickedModel ? { model: pickedModel } : {}),\n ...(options.creditsConfirmed ? { creditsConfirmed: true } : {}),\n }),\n })\n const payload = await response.json().catch(() => null)\n if (!response.ok) {\n if (response.status === 409 && payload?.code === AI_CREDITS_CONFIRM_CODE && payload?.credits) {\n setServerPrompt(payload.credits as AiCreditsPrompt)\n return\n }\n const locked = parseLockdownRefusal(response.status, payload)\n setNotice(\n locked\n ? lockdownRefusalText(locked)\n : String(payload?.error ?? 'The site could not be started. Try again.'),\n )\n return\n }\n const created = (payload?.job as AiJobSummary | undefined) ?? null\n if (!created) {\n setNotice('The site could not be started. Try again.')\n return\n }\n // The indicator and the launcher count it from the moment it exists.\n publishAiJob(created)\n // Where the next step is (AGL-3594): the site's \"Building your site\"\n // page for this job. The zone closes without the starter first, so the\n // setup page does not ask again behind it.\n const href = aiSiteBuildHref(orgSlug, host, created.id)\n if (href) {\n ;(leave ?? (() => undefined))()\n router.push(href)\n return\n }\n setStarted(created)\n } catch {\n setNotice('The site could not be started. Try again.')\n } finally {\n setBusy(false)\n }\n }, [orgId, hostId, answers, answer, freeTaste, freeCredits, noneLeft, orgSlug, host, leave, router, pickedModel])\n\n const chooseStarter = useCallback(() => {\n setStartingStarter(true)\n trackEvent('site_start_choice', { choice: 'starter' })\n startBlank()\n }, [startBlank])\n\n const chooseAi = useCallback(() => {\n trackEvent('site_start_choice', { choice: 'ai' })\n setStep('describe')\n }, [])\n\n if (verdict !== 'ready') return null\n\n // Before a job is started every way out is the blank site, which writes the\n // starter (AGL-3594); after, it only closes — the job builds the site.\n const exit = started ? (leave ?? startBlank) : startBlank\n // Anything the person typed or picked, which a dismissal must not discard\n // silently (AGL-3660). After a job starts there is nothing left to lose.\n const drafted =\n !started &&\n Boolean(answers.siteType.trim() || answers.audience.trim() || answers.kind !== null)\n // Escape and the close control: a dismissal, never a choice. Escape that\n // bubbled here through React from a portal outside this dialog's own DOM is\n // a nested menu's, already handled there, and is not this dialog's to act on.\n const dismiss = (event?: SyntheticEvent | object, reason?: string) => {\n if (reason === 'escapeKeyDown') {\n const target = (event as SyntheticEvent | undefined)?.target\n const root = dialogRef.current\n if (root && target instanceof Node && !root.contains(target)) return\n }\n if (drafted) setConfirmingLeave(true)\n else exit()\n }\n const leaveDraft = () => {\n setConfirmingLeave(false)\n exit()\n }\n\n // The chosen model's cost against Auto's, as the model list states it.\n const modelMultiplier =\n (pickedModel && modelChoice.options?.options.find((option) => option.id === pickedModel)?.multiplier) || 1\n // What the start is likely to cost and at most (AGL-3722): \"About 137\n // credits (up to 282)\", the measured figures scaled by the chosen model.\n const scaled = (range: AiCreditRange): AiCreditRange => ({\n likely: Math.round(range.likely * modelMultiplier),\n p90: Math.round(range.p90 * modelMultiplier),\n ceiling: Math.round(range.ceiling * modelMultiplier),\n })\n const estimate = freeTaste\n ? aiFreeSiteCreditRange(answers.pages)\n : scaled(\n aiSiteCreditRange(answers.pages, {\n welcomeEmail: answers.welcomeEmail,\n // A store's first products and a blog's first posts are part of the start (AGL-3676).\n siteKind: aiSiteKindOfInputs(aiSiteStartInputs(answers))?.id ?? null,\n }),\n )\n // A Free start quotes what is LEFT (AGL-3660), shared across the owner's\n // Free workspaces — never the month's whole allowance as if none were spent.\n const estimateText = freeTaste\n ? freeCredits\n ? `${aiCreditRangeText(estimate)}. You have ${freeCredits.left.toLocaleString('en-US')} of your ${freeCredits.total.toLocaleString('en-US')} free AI credits left this month, until ${aiFreeCreditsResetLabel(freeCredits.resetsOn)}`\n : `${aiCreditRangeText(estimate)}, of the ${FREE_AI_TASTE_CREDITS_PER_MONTH} AI credits you get free each month`\n : `${aiCreditRangeText(estimate)}, estimated`\n\n const choosing = step === 'choose' && !started\n\n return (\n <Dialog\n open\n fullScreen\n ref={dialogRef}\n onClose={dismiss}\n aria-labelledby={TITLE_ID}\n // The console's own page surface, in both modes. A Dialog's paper sits\n // at elevation 24 by default, and in dark mode MUI lightens an elevated\n // paper with a white overlay, which turned the whole takeover a\n // washed-out gray; the overlay is for floating surfaces, and this one\n // fills the screen, so its paper is flat.\n slotProps={{ paper: { elevation: 0, sx: AI_SITE_START_SURFACE_SX } }}\n >\n {/*\n The way out, before anything it is a way out of: a slim header on the\n paper surface. On a narrow screen it is the TITLE that gives way, so\n the exits keep their words at every width.\n */}\n <AppBar\n position=\"relative\"\n color=\"inherit\"\n elevation={0}\n enableColorOnDark\n sx={{ ...AI_SITE_START_SURFACE_SX, borderBottom: 1, borderColor: 'divider' }}\n >\n <Toolbar variant=\"dense\" sx={{ gap: 1 }}>\n <IconButton\n edge=\"start\"\n color=\"inherit\"\n onClick={() => dismiss()}\n aria-label=\"Close the guided start\"\n >\n <MdiIcon path={ICON_VARIANT_CLOSE.path} />\n </IconButton>\n <Typography\n id={TITLE_ID}\n variant=\"subtitle1\"\n component=\"div\"\n noWrap\n sx={{ textOverflow: 'ellipsis', flex: 1 }}\n >\n {'Start your site'}\n </Typography>\n <Button color=\"inherit\" onClick={exit} aria-label={started ? 'Close' : 'Skip and start blank'}>\n {started ? 'Close' : 'Skip'}\n </Button>\n </Toolbar>\n </AppBar>\n <DialogContent sx={{ px: { xs: 2, sm: 3 } }}>\n <Container maxWidth={choosing ? 'md' : 'sm'} disableGutters sx={{ py: { xs: 3, sm: 5 } }}>\n <Stack spacing={4}>\n <Stepper\n activeStep={choosing ? 0 : 1}\n aria-label={choosing ? 'Step 1 of 2' : 'Step 2 of 2'}\n sx={{ maxWidth: (theme: Theme) => theme.spacing(40), width: '100%', mx: 'auto' }}\n >\n {STEP_LABELS.map((label) => (\n <Step key={label}>\n <StepLabel>{label}</StepLabel>\n </Step>\n ))}\n </Stepper>\n <Stack spacing={1} sx={{ textAlign: choosing ? 'center' : 'left' }}>\n <Typography variant=\"h4\" component=\"h1\">\n {choosing ? 'How do you want to start?' : 'Tell us about your site'}\n </Typography>\n <Typography variant=\"body1\" color=\"text.secondary\">\n {choosing ? <HelpTip sx={{ float: 'right' }} {...START_HELP.choose} /> : null}\n {choosing\n ? 'You can change everything later.'\n : `A few answers and ${PLATFORM_BRAND_NAME} AI plans and writes your pages, then publishes your site.`}\n </Typography>\n </Stack>\n {notice && <Alert severity=\"info\">{notice}</Alert>}\n {step === 'describe' && !started && noneLeft && freeCredits && (\n <Alert\n severity=\"warning\"\n action={\n orgSlug ? (\n <Button color=\"inherit\" size=\"small\" href={aiCreditsBillingHref(orgSlug)}>\n {'Upgrade'}\n </Button>\n ) : undefined\n }\n >\n {aiFreeCreditsNoneLeftText(freeCredits.resetsOn)}\n </Alert>\n )}\n {step === 'describe' && !started && !noneLeft && prompt && (\n <AiCreditsPromptNotice\n prompt={prompt}\n noun=\"site\"\n orgSlug={orgSlug}\n busy={busy}\n onBuildWhatFits={() => void plan({ creditsConfirmed: true })}\n onSmaller={() => void plan({ creditsConfirmed: true, pages: 1 })}\n />\n )}\n {choosing ? (\n <Box\n sx={{\n display: 'grid',\n gridTemplateColumns: { xs: '1fr', sm: '1fr 1fr' },\n gap: 3,\n }}\n >\n <ChoiceCard\n accent=\"secondary\"\n icon={mdiPageLayoutHeaderFooter.path}\n iconId=\"page-layout-header-footer\"\n title=\"Start from the starter site\"\n description=\"A ready-made home page with a header, footer and contact form you can edit.\"\n busy={startingStarter}\n onChoose={chooseStarter}\n />\n <ChoiceCard\n accent=\"primary\"\n icon={mdiCreation.path}\n iconId=\"creation\"\n title=\"Start with AI\"\n description={`Answer a few questions and ${PLATFORM_BRAND_NAME} AI plans your pages.`}\n onChoose={chooseAi}\n >\n <Chip size=\"small\" color=\"primary\" label=\"Recommended\" />\n {freeTaste && (\n <Typography variant=\"caption\" color=\"text.secondary\">\n {`Up to ${AI_SITE_FREE_PAGES.max} pages on the Free plan`}\n </Typography>\n )}\n </ChoiceCard>\n </Box>\n ) : started && orgId ? (\n <Card variant=\"outlined\" sx={{ borderRadius: 2, p: { xs: 2, sm: 3 } }}>\n <AiJobFollow\n job={started}\n orgId={orgId}\n orgSlug={orgSlug}\n user={user}\n intro={\n 'Your site is being planned. It is then built and published for you, with ' +\n 'nothing to approve. You can edit or unpublish it afterwards.'\n }\n // Full screen: AI jobs opens in the panel this dialog covers.\n onOpenJobs={exit}\n />\n </Card>\n ) : (\n <>\n <Stack spacing={2} component=\"section\" aria-label=\"Your business\">\n <SectionLabel help={START_HELP.business}>{'Your business'}</SectionLabel>\n <TextField\n fullWidth\n required\n label=\"What kind of site are you creating?\"\n placeholder=\"a neighborhood dog groomer that takes bookings\"\n value={answers.siteType}\n onChange={(event) => answer({ siteType: event.target.value })}\n helperText=\"A few words is enough, or pick one below.\"\n />\n <Box sx={{ display: 'flex', flexWrap: 'wrap', gap: 1 }}>\n {AI_SITE_START_TYPES.map((type) => (\n <Chip\n key={type}\n label={type}\n size=\"small\"\n color={answers.siteType === type ? 'primary' : 'default'}\n variant={answers.siteType === type ? 'filled' : 'outlined'}\n onClick={() => answer({ siteType: type })}\n />\n ))}\n </Box>\n <TextField\n fullWidth\n label=\"Who is it for?\"\n placeholder=\"local dog owners who want a regular groom booked online\"\n value={answers.audience}\n onChange={(event) => answer({ audience: event.target.value })}\n helperText=\"Optional. It narrows who the pages are written for.\"\n />\n </Stack>\n <Stack spacing={2} component=\"section\" aria-label=\"Style\">\n <SectionLabel help={START_HELP.style}>{'Style'}</SectionLabel>\n <Typography variant=\"body2\" color=\"text.secondary\">\n {answers.kind\n ? 'This decides how your site looks and which pages it usually has.'\n : 'Picked from your answer above. Choose another to change how your site looks and which pages it usually has.'}\n </Typography>\n <OptionCardGrid\n label=\"Style of site\"\n options={AI_SITE_KINDS.map((kind) => ({\n id: kind.id,\n title: kind.label,\n description: kind.blurb,\n icon: AI_SITE_KIND_ICONS[kind.id],\n }))}\n value={aiSiteStartKind(answers).id}\n onChange={(kind) => answer({ kind })}\n />\n </Stack>\n <Stack spacing={2} component=\"section\" aria-label=\"Details\">\n <SectionLabel help={START_HELP.details}>{'Details'}</SectionLabel>\n {/*\n The one setting a new site owner has to make, asked where\n they are already answering: a contact form nobody routed\n files its messages somewhere the person has not looked.\n */}\n <TextField\n select\n fullWidth\n label=\"Where do form submissions go?\"\n value={answers.submissions}\n onChange={(event) =>\n answer({ submissions: event.target.value as AiSiteSubmissions })\n }\n helperText=\"You can change this on the form itself afterwards.\"\n >\n {AI_SITE_SUBMISSION_CHOICES.map((option) => (\n <MenuItem key={option.id} value={option.id}>\n {`${option.label} — ${option.blurb}`}\n </MenuItem>\n ))}\n </TextField>\n <Stack direction={{ xs: 'column', sm: 'row' }} spacing={2}>\n <TextField\n select\n fullWidth\n label=\"Pages\"\n value={answers.pages}\n onChange={(event) => answer({ pages: Number(event.target.value) })}\n helperText={freeTaste ? AI_SITE_FREE_PAGES_NOTE : undefined}\n >\n {Array.from(\n { length: band.max - band.min + 1 },\n (_, index) => band.min + index,\n ).map((count) => (\n <MenuItem key={count} value={count}>\n {count}\n </MenuItem>\n ))}\n </TextField>\n {!freeTaste && (\n <TextField\n select\n fullWidth\n label=\"Welcome email\"\n value={answers.welcomeEmail ? 'yes' : 'no'}\n onChange={(event) => answer({ welcomeEmail: event.target.value === 'yes' })}\n >\n <MenuItem value=\"yes\">{'Draft one'}</MenuItem>\n <MenuItem value=\"no\">{'No'}</MenuItem>\n </TextField>\n )}\n </Stack>\n </Stack>\n </>\n )}\n </Stack>\n </Container>\n </DialogContent>\n {step === 'describe' && !started && (\n /* The footer stays put while the questions scroll. It wraps, because\n the estimate, the reason and the buttons are wider than a phone. */\n <DialogActions\n sx={{\n px: { xs: 2, sm: 3 },\n py: 2,\n flexWrap: 'wrap',\n rowGap: 1,\n columnGap: 2,\n borderTop: 1,\n borderColor: 'divider',\n ...AI_SITE_START_SURFACE_SX,\n }}\n >\n <Stack direction=\"row\" spacing={0.5} sx={{ alignItems: 'center', mr: 'auto', minWidth: 0 }}>\n <Typography variant=\"body2\" color=\"text.secondary\">\n {`${estimateText}.`}\n </Typography>\n <HelpTip {...START_HELP.estimate} ariaLabel=\"How the estimate works\" />\n </Stack>\n {refusal && (\n <Typography variant=\"body2\" color=\"text.secondary\">\n {refusal}\n </Typography>\n )}\n {!freeTaste && <AiModelSelector choice={modelChoice} disabled={busy} />}\n <Button onClick={() => setStep('choose')}>{'Back'}</Button>\n <Button\n variant=\"contained\"\n size=\"large\"\n disabled={busy || Boolean(refusal) || Boolean(prompt) || noneLeft}\n onClick={() => void plan()}\n startIcon={<MdiIcon path={mdiCreation.path} />}\n >\n {busy ? 'Starting…' : 'Plan my site'}\n </Button>\n </DialogActions>\n )}\n <Dialog\n open={confirmingLeave}\n onClose={() => setConfirmingLeave(false)}\n aria-labelledby={`${TITLE_ID}-leave`}\n aria-describedby={`${TITLE_ID}-leave-text`}\n maxWidth=\"xs\"\n >\n <DialogTitle id={`${TITLE_ID}-leave`}>{'Leave without your answers?'}</DialogTitle>\n <DialogContent>\n <DialogContentText id={`${TITLE_ID}-leave-text`}>\n {'What you typed is not saved. Leaving starts your site from the starter site instead.'}\n </DialogContentText>\n </DialogContent>\n <DialogActions>\n <Button color=\"inherit\" onClick={leaveDraft}>\n {'Leave and start blank'}\n </Button>\n <Button variant=\"contained\" autoFocus onClick={() => setConfirmingLeave(false)}>\n {'Keep editing'}\n </Button>\n </DialogActions>\n </Dialog>\n </Dialog>\n )\n}\n\nexport default AiSiteStartCard\n"],"names":["lockdownRefusalText","parseLockdownRefusal","PLATFORM_BRAND_NAME","trackEvent","ICON_VARIANT_CLOSE","mdiAccount","mdiBookOpenPageVariant","mdiBriefcaseOutline","mdiCalendarHeart","mdiCamera","mdiClockOutline","mdiContentCut","mdiCreation","mdiDumbbell","mdiHandHeart","mdiHeartPulse","mdiHomeCity","mdiMusic","mdiPaletteOutline","mdiRocketLaunch","mdiScaleBalance","mdiSchool","mdiShopping","mdiSilverwareForkKnife","mdiViewGridOutline","mdiWrench","mdiYoga","mdiPageLayoutHeaderFooter","pluginDocsHelp","HelpTip","MdiIcon","OptionCardGrid","authorizedFetch","useUser","Alert","AppBar","Box","Button","Card","CardActionArea","Chip","CircularProgress","Container","Dialog","DialogActions","DialogContent","DialogContentText","DialogTitle","IconButton","MenuItem","Stack","Step","StepLabel","Stepper","TextField","Toolbar","Typography","alpha","useRouter","useCallback","useEffect","useId","useRef","useState","AI_JOB_AUTO_CONFIRM_INPUT","AI_SITE_FREE_PAGES","AI_SITE_FREE_PAGES_NOTE","AI_SITE_SUBMISSION_CHOICES","aiFreeCreditsNoneLeftText","aiFreeCreditsResetLabel","aiFreeSiteCreditRange","aiFreeSitePrompt","aiSiteCreditRange","aiSitePagesBand","FREE_AI_TASTE_CREDITS_PER_MONTH","AI_CREDITS_CONFIRM_CODE","aiCreditRangeText","AiCreditsPromptNotice","AI_SITE_START_ANSWERS","AI_SITE_START_TYPES","aiSiteStartBrief","aiSiteStartKind","aiSiteStartInputs","aiSiteStartRefusal","AI_SITE_KINDS","aiSiteKindOfInputs","AI_SITE_KIND_ICONS","business","path","trades","professional","wellness","restaurant","store","portfolio","studio","photography","blog","events","fitness","yoga","beauty","realestate","education","nonprofit","music","personal","landing","AiJobFollow","AiModelSelector","useAiModelChoice","aiCreditsBillingHref","aiSiteBuildHref","publishAiJob","TITLE_ID","AI_SITE_START_SURFACE_SX","bgcolor","STEP_LABELS","IconBadge","accent","children","aria-hidden","sx","theme","width","spacing","height","borderRadius","display","alignItems","justifyContent","palette","main","mode","color","fontSize","ChoiceCard","icon","iconId","title","description","busy","onChoose","id","variant","transition","transitions","create","duration","shorter","borderColor","boxShadow","shadows","transform","onClick","disabled","aria-labelledby","aria-describedby","aria-busy","undefined","p","xs","sm","textAlign","size","aria-label","data-icon","component","START_HELP","choose","anchor","excerpt","style","details","estimate","SectionLabel","help","direction","AiSiteStartCard","hostId","orgId","orgSlug","host","startBlank","leave","initialAnswers","modelChoice","data","user","router","userRef","current","uid","verdict","setVerdict","reopened","step","setStep","answers","setAnswers","setBusy","startingStarter","setStartingStarter","notice","setNotice","started","setStarted","freeTaste","setFreeTaste","freeCredits","setFreeCredits","confirmingLeave","setConfirmingLeave","dialogRef","active","response","encodeURIComponent","payload","ok","json","catch","credits","Number","isFinite","left","pages","Math","min","max","welcomeEmail","status","answer","patch","serverPrompt","setServerPrompt","prompt","noneLeft","refusal","band","surface","kind","load","loadModels","model","rememberedModel","pickedModel","plan","options","asked","creditsConfirmed","method","headers","body","JSON","stringify","brief","inputs","code","locked","String","error","created","job","href","push","chooseStarter","choice","chooseAi","exit","drafted","Boolean","siteType","trim","audience","dismiss","event","reason","target","root","Node","contains","leaveDraft","modelMultiplier","find","option","multiplier","scaled","range","likely","round","p90","ceiling","siteKind","estimateText","toLocaleString","total","resetsOn","choosing","open","fullScreen","ref","onClose","slotProps","paper","elevation","position","enableColorOnDark","borderBottom","gap","edge","noWrap","textOverflow","flex","px","maxWidth","disableGutters","py","activeStep","mx","map","label","float","severity","action","noun","onBuildWhatFits","onSmaller","gridTemplateColumns","intro","onOpenJobs","fullWidth","required","placeholder","value","onChange","helperText","flexWrap","type","blurb","select","submissions","Array","from","length","_","index","count","rowGap","columnGap","borderTop","mr","minWidth","ariaLabel","startIcon","autoFocus"],"mappings":"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"}
@@ -59,7 +59,7 @@ import { useEffect, useState } from "react";
59
59
  },
60
60
  product: {
61
61
  title: 'Create products with AI',
62
- does: 'Describe what the store sells and AI proposes up to twelve products. You review them ' + 'before any is created, and each is created as a draft that is not on your storefront ' + 'until you price it and activate it.'
62
+ does: 'Describe what the store sells and AI proposes up to twelve products. You review them ' + 'before any is created, and each is created as a draft at a suggested price that is not on ' + 'your storefront until you review it and activate it.'
63
63
  },
64
64
  logic: {
65
65
  title: 'Create a function or variable with AI',