@aglyn/plugins-ai 1.0.0-beta.264 → 1.0.0-beta.268
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +18 -18
- package/src/lib/assets/site-styles/beauty.webp +0 -0
- package/src/lib/assets/site-styles/blog.webp +0 -0
- package/src/lib/assets/site-styles/business.webp +0 -0
- package/src/lib/assets/site-styles/coming-soon.webp +0 -0
- package/src/lib/assets/site-styles/education.webp +0 -0
- package/src/lib/assets/site-styles/events.webp +0 -0
- package/src/lib/assets/site-styles/fitness.webp +0 -0
- package/src/lib/assets/site-styles/landing.webp +0 -0
- package/src/lib/assets/site-styles/music.webp +0 -0
- package/src/lib/assets/site-styles/nonprofit.webp +0 -0
- package/src/lib/assets/site-styles/personal.webp +0 -0
- package/src/lib/assets/site-styles/photography.webp +0 -0
- package/src/lib/assets/site-styles/portfolio.webp +0 -0
- package/src/lib/assets/site-styles/professional.webp +0 -0
- package/src/lib/assets/site-styles/realestate.webp +0 -0
- package/src/lib/assets/site-styles/restaurant.webp +0 -0
- package/src/lib/assets/site-styles/store.webp +0 -0
- package/src/lib/assets/site-styles/studio.webp +0 -0
- package/src/lib/assets/site-styles/trades.webp +0 -0
- package/src/lib/assets/site-styles/wellness.webp +0 -0
- package/src/lib/assets/site-styles/yoga.webp +0 -0
- package/src/lib/components/ai-job-site.d.ts +8 -1
- package/src/lib/components/ai-job-site.js +7 -0
- package/src/lib/components/ai-job-site.js.map +1 -1
- package/src/lib/components/ai-site-build-page.component.js +37 -0
- package/src/lib/components/ai-site-build-page.component.js.map +1 -1
- package/src/lib/components/ai-site-start-card.component.d.ts +12 -0
- package/src/lib/components/ai-site-start-card.component.js +279 -240
- package/src/lib/components/ai-site-start-card.component.js.map +1 -1
- package/src/lib/components/ai-site-start-steps.component.d.ts +114 -0
- package/src/lib/components/ai-site-start-steps.component.js +480 -0
- package/src/lib/components/ai-site-start-steps.component.js.map +1 -0
- package/src/lib/components/ai-site-start-tracking.d.ts +122 -0
- package/src/lib/components/ai-site-start-tracking.js +296 -0
- package/src/lib/components/ai-site-start-tracking.js.map +1 -0
- package/src/lib/components/ai-site-style-previews.d.ts +26 -0
- package/src/lib/components/ai-site-style-previews.js +115 -0
- package/src/lib/components/ai-site-style-previews.js.map +1 -0
- package/src/lib/components/assist-jobs-drawer.component.js +24 -2
- package/src/lib/components/assist-jobs-drawer.component.js.map +1 -1
- package/src/lib/insights/ai-insight-digest.d.ts +9 -0
- package/src/lib/insights/ai-insight-digest.js +35 -11
- package/src/lib/insights/ai-insight-digest.js.map +1 -1
- package/src/lib/jobs/ai-empty-site-sweep.d.ts +154 -0
- package/src/lib/jobs/ai-empty-site-sweep.js +346 -0
- package/src/lib/jobs/ai-empty-site-sweep.js.map +1 -0
- package/src/lib/jobs/ai-job-page-language.d.ts +9 -0
- package/src/lib/jobs/ai-job-page-language.js +20 -2
- package/src/lib/jobs/ai-job-page-language.js.map +1 -1
- package/src/lib/jobs/ai-job-plan-step.d.ts +43 -8
- package/src/lib/jobs/ai-job-plan-step.js +99 -18
- package/src/lib/jobs/ai-job-plan-step.js.map +1 -1
- package/src/lib/jobs/ai-job-site-datasets.d.ts +82 -1
- package/src/lib/jobs/ai-job-site-datasets.js +276 -14
- package/src/lib/jobs/ai-job-site-datasets.js.map +1 -1
- package/src/lib/jobs/ai-jobs-beat.d.ts +11 -3
- package/src/lib/jobs/ai-jobs-beat.js +23 -6
- package/src/lib/jobs/ai-jobs-beat.js.map +1 -1
- package/src/lib/jobs/ai-jobs.js +46 -7
- package/src/lib/jobs/ai-jobs.js.map +1 -1
- package/src/lib/jobs/ai-layout-stock-photos.d.ts +143 -10
- package/src/lib/jobs/ai-layout-stock-photos.js +1046 -102
- package/src/lib/jobs/ai-layout-stock-photos.js.map +1 -1
- package/src/lib/jobs/fixtures/ai-site-foreign-datasets-recording.d.ts +58 -0
- package/src/lib/jobs/fixtures/ai-site-foreign-datasets-recording.js +678 -0
- package/src/lib/jobs/fixtures/ai-site-foreign-datasets-recording.js.map +1 -0
- package/src/lib/jobs/fixtures/ai-stock-photo-agl3856-beta265-recordings.d.ts +33 -0
- package/src/lib/jobs/fixtures/ai-stock-photo-agl3856-beta265-recordings.js +270 -0
- package/src/lib/jobs/fixtures/ai-stock-photo-agl3856-beta265-recordings.js.map +1 -0
- package/src/lib/jobs/fixtures/ai-stock-photo-agl3856-people-recordings.d.ts +33 -0
- package/src/lib/jobs/fixtures/ai-stock-photo-agl3856-people-recordings.js +277 -0
- package/src/lib/jobs/fixtures/ai-stock-photo-agl3856-people-recordings.js.map +1 -0
- package/src/lib/jobs/fixtures/ai-stock-photo-agl3923-recordings.d.ts +35 -0
- package/src/lib/jobs/fixtures/ai-stock-photo-agl3923-recordings.js +379 -0
- package/src/lib/jobs/fixtures/ai-stock-photo-agl3923-recordings.js.map +1 -0
- package/src/lib/jobs/fixtures/ai-stock-photo-brightvale-recordings.d.ts +31 -0
- package/src/lib/jobs/fixtures/ai-stock-photo-brightvale-recordings.js +208 -0
- package/src/lib/jobs/fixtures/ai-stock-photo-brightvale-recordings.js.map +1 -0
- package/src/lib/layout-language/ai-layout-compiler.js +49 -12
- package/src/lib/layout-language/ai-layout-compiler.js.map +1 -1
- package/src/lib/layout-language/ai-layout-design.d.ts +6 -3
- package/src/lib/layout-language/ai-layout-design.js +19 -13
- package/src/lib/layout-language/ai-layout-design.js.map +1 -1
- package/src/lib/layout-language/ai-layout-listings.d.ts +48 -0
- package/src/lib/layout-language/ai-layout-listings.js +91 -5
- package/src/lib/layout-language/ai-layout-listings.js.map +1 -1
- package/src/lib/layout-language/ai-layout-pictures.d.ts +15 -0
- package/src/lib/layout-language/ai-layout-pictures.js +6 -2
- package/src/lib/layout-language/ai-layout-pictures.js.map +1 -1
- package/src/lib/model/ai-jobs.types.d.ts +20 -0
- package/src/lib/model/ai-jobs.types.js.map +1 -1
- package/src/lib/model/ai-site-home-arcs.d.ts +75 -0
- package/src/lib/model/ai-site-home-arcs.js +741 -0
- package/src/lib/model/ai-site-home-arcs.js.map +1 -0
- package/src/lib/model/ai-site-inventory.d.ts +18 -0
- package/src/lib/model/ai-site-inventory.js.map +1 -1
- package/src/lib/model/ai-site-job.d.ts +9 -6
- package/src/lib/model/ai-site-job.js +8 -5
- package/src/lib/model/ai-site-job.js.map +1 -1
- package/src/lib/model/ai-site-kinds.js +24 -24
- package/src/lib/model/ai-site-kinds.js.map +1 -1
- package/src/lib/model/ai-site-start-handoff.d.ts +49 -0
- package/src/lib/model/ai-site-start-handoff.js +88 -0
- package/src/lib/model/ai-site-start-handoff.js.map +1 -0
- package/src/lib/model/ai-site-start-steps.d.ts +67 -0
- package/src/lib/model/ai-site-start-steps.js +127 -0
- package/src/lib/model/ai-site-start-steps.js.map +1 -0
- package/src/lib/model/ai-site-start.js +4 -1
- package/src/lib/model/ai-site-start.js.map +1 -1
- package/src/lib/runtime/ai-doctrine-validators.d.ts +32 -0
- package/src/lib/runtime/ai-doctrine-validators.js +119 -2
- package/src/lib/runtime/ai-doctrine-validators.js.map +1 -1
- package/src/lib/runtime/ai-doctrine.d.ts +6 -1
- package/src/lib/runtime/ai-doctrine.js +9 -5
- package/src/lib/runtime/ai-doctrine.js.map +1 -1
- package/src/lib/runtime/ai-palette.generated.js +5 -2
- package/src/lib/runtime/ai-palette.generated.js.map +1 -1
- package/src/lib/runtime/site-inventory.js +6 -0
- package/src/lib/runtime/site-inventory.js.map +1 -1
- package/src/lib/server/ai-insight-digest-route.js +2 -2
- package/src/lib/server/ai-insight-digest-route.js.map +1 -1
- package/src/lib/usage/assist-free-taste.js +3 -0
- package/src/lib/usage/assist-free-taste.js.map +1 -1
|
@@ -15,54 +15,34 @@
|
|
|
15
15
|
* limitations under the License.
|
|
16
16
|
*/ 'use client';
|
|
17
17
|
import { _ as _extends } from "@swc/helpers/_/_extends";
|
|
18
|
-
import { jsx as _jsx, jsxs as _jsxs
|
|
18
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
19
19
|
import { lockdownRefusalText, parseLockdownRefusal, PLATFORM_BRAND_NAME } from "@aglyn/aglyn";
|
|
20
20
|
import { trackEvent } from "@aglyn/aglyn/app-utils/analytics-events";
|
|
21
21
|
import { ICON_VARIANT_CLOSE } from "@aglyn/shared-data-enums";
|
|
22
|
-
import {
|
|
22
|
+
import { mdiCreation, mdiPageLayoutHeaderFooter } from "@aglyn/shared-data-mdi";
|
|
23
23
|
import { pluginDocsHelp } from "@aglyn/aglyn/app-utils/docs-help";
|
|
24
24
|
import { HelpTip, MdiIcon } from "@aglyn/shared-ui-jsx";
|
|
25
|
-
import { OptionCardGrid } from "@aglyn/shared-ui-jsx/components/option-card-grid.component";
|
|
26
25
|
import { authorizedFetch } from "@aglyn/shared-util-http/authorized-token";
|
|
27
26
|
import { useUser } from "@aglyn/tenant-feature-instance";
|
|
28
|
-
import { Alert, AppBar, Box, Button, Card, CardActionArea, Chip, CircularProgress, Container, Dialog, DialogActions, DialogContent, DialogContentText, DialogTitle, IconButton,
|
|
29
|
-
import { alpha } from "@mui/material/styles";
|
|
27
|
+
import { Alert, AppBar, Box, Button, Card, CardActionArea, Chip, CircularProgress, Container, Dialog, DialogActions, DialogContent, DialogContentText, DialogTitle, IconButton, Stack, Toolbar, Typography, useMediaQuery } from "@mui/material";
|
|
28
|
+
import { alpha, useTheme } from "@mui/material/styles";
|
|
30
29
|
import { useRouter } from "next/navigation";
|
|
31
30
|
import { useCallback, useEffect, useId, useRef, useState } from "react";
|
|
32
|
-
import { AI_JOB_AUTO_CONFIRM_INPUT, AI_SITE_FREE_PAGES,
|
|
31
|
+
import { AI_JOB_AUTO_CONFIRM_INPUT, AI_SITE_FREE_PAGES, aiFreeCreditsNoneLeftText, aiFreeCreditsResetLabel, aiFreeSiteCreditRange, aiFreeSitePrompt, aiSiteCreditRange, aiSitePagesBand } from "../model/ai-site-job.js";
|
|
33
32
|
import { FREE_AI_TASTE_CREDITS_PER_MONTH } from "../plan-entitlements.js";
|
|
34
33
|
import { AI_CREDITS_CONFIRM_CODE, aiCreditRangeText } from "../model/ai-credit-estimate.js";
|
|
35
34
|
import { AiCreditsPromptNotice } from "./ai-credits-prompt.component.js";
|
|
36
|
-
import { AI_SITE_START_ANSWERS,
|
|
37
|
-
import {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
professional: mdiScaleBalance.path,
|
|
42
|
-
wellness: mdiHeartPulse.path,
|
|
43
|
-
restaurant: mdiSilverwareForkKnife.path,
|
|
44
|
-
store: mdiShopping.path,
|
|
45
|
-
portfolio: mdiViewGridOutline.path,
|
|
46
|
-
studio: mdiPaletteOutline.path,
|
|
47
|
-
photography: mdiCamera.path,
|
|
48
|
-
blog: mdiBookOpenPageVariant.path,
|
|
49
|
-
events: mdiCalendarHeart.path,
|
|
50
|
-
fitness: mdiDumbbell.path,
|
|
51
|
-
yoga: mdiYoga.path,
|
|
52
|
-
beauty: mdiContentCut.path,
|
|
53
|
-
realestate: mdiHomeCity.path,
|
|
54
|
-
education: mdiSchool.path,
|
|
55
|
-
nonprofit: mdiHandHeart.path,
|
|
56
|
-
music: mdiMusic.path,
|
|
57
|
-
personal: mdiAccount.path,
|
|
58
|
-
landing: mdiRocketLaunch.path,
|
|
59
|
-
'coming-soon': mdiClockOutline.path
|
|
60
|
-
};
|
|
35
|
+
import { AI_SITE_START_ANSWERS, aiSiteStartBrief, aiSiteStartInputs, aiSiteStartRefusal } from "../model/ai-site-start.js";
|
|
36
|
+
import { aiSiteStartFieldErrors, aiSiteStartFirstInvalidStep, aiSiteStartNextStep, aiSiteStartPreviousStep, aiSiteStartStepErrors, aiSiteStartStepIndex, AI_SITE_START_STEP_FIELDS } from "../model/ai-site-start-steps.js";
|
|
37
|
+
import { aiSiteKindOfInputs } from "../model/ai-site-kinds.js";
|
|
38
|
+
import { aiSiteStartClickOf, useAiSiteStartTracking } from "./ai-site-start-tracking.js";
|
|
39
|
+
import { AudienceStep, DetailsStep, KindStep, ReviewStep, StartProgress, StepHelp, StyleStep } from "./ai-site-start-steps.component.js";
|
|
61
40
|
import { AiJobFollow } from "./ai-job-follow.component.js";
|
|
62
41
|
import { AiModelSelector } from "./ai-model-selector.component.js";
|
|
63
42
|
import { useAiModelChoice } from "./use-ai-model-choice.js";
|
|
64
43
|
import { aiCreditsBillingHref, aiSiteBuildHref } from "./ai-job-links.js";
|
|
65
44
|
import { publishAiJob } from "./ai-jobs-store.js";
|
|
45
|
+
import { clearAiSiteStartAnswers, readAiSiteStartAnswers } from "../model/ai-site-start-handoff.js";
|
|
66
46
|
/** Labels the dialog for a reader, from its own heading. */ const TITLE_ID = 'ai-site-start-title';
|
|
67
47
|
/**
|
|
68
48
|
* The takeover's surface, for its paper, its bar and its footer alike: the
|
|
@@ -71,10 +51,6 @@ import { publishAiJob } from "./ai-jobs-store.js";
|
|
|
71
51
|
*/ export const AI_SITE_START_SURFACE_SX = {
|
|
72
52
|
bgcolor: 'background.default'
|
|
73
53
|
};
|
|
74
|
-
/** The two steps, as the indicator under the header names them. */ const STEP_LABELS = [
|
|
75
|
-
'Choose',
|
|
76
|
-
'Describe'
|
|
77
|
-
];
|
|
78
54
|
/** The soft round badge an icon sits in, in its accent's tint. */ function IconBadge({ accent, children }) {
|
|
79
55
|
return /*#__PURE__*/ _jsx(Box, {
|
|
80
56
|
"aria-hidden": true,
|
|
@@ -179,18 +155,6 @@ import { publishAiJob } from "./ai-jobs-store.js";
|
|
|
179
155
|
anchor: '#how-do-you-want-to-start',
|
|
180
156
|
excerpt: '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.'
|
|
181
157
|
}),
|
|
182
|
-
business: pluginDocsHelp('aiStart', {
|
|
183
|
-
anchor: '#your-business',
|
|
184
|
-
excerpt: '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.'
|
|
185
|
-
}),
|
|
186
|
-
style: pluginDocsHelp('aiSiteLooks', {
|
|
187
|
-
anchor: '#choose-a-style',
|
|
188
|
-
excerpt: 'The style decides the look — theme, colors, fonts, buttons — and which pages the site usually has. Every site gets its own variation.'
|
|
189
|
-
}),
|
|
190
|
-
details: pluginDocsHelp('aiStart', {
|
|
191
|
-
anchor: '#details',
|
|
192
|
-
excerpt: '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.'
|
|
193
|
-
}),
|
|
194
158
|
estimate: pluginDocsHelp('aiCredits', {
|
|
195
159
|
anchor: '#before-a-job-starts',
|
|
196
160
|
excerpt: '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.'
|
|
@@ -217,8 +181,19 @@ function SectionLabel({ children, help }) {
|
|
|
217
181
|
]
|
|
218
182
|
});
|
|
219
183
|
}
|
|
220
|
-
|
|
221
|
-
|
|
184
|
+
/**
|
|
185
|
+
* The questions are one decision a step (AGL-3898): what kind of site it is
|
|
186
|
+
* (typed, or a card), who it is for, the style (cards that show each one,
|
|
187
|
+
* "Pick for me" first and picked), the details, and a review that plans the
|
|
188
|
+
* site (`ai-site-start-steps.component.tsx`). Back and Next keep every
|
|
189
|
+
* answer; Enter in a text answer is Next; each step's heading takes the focus
|
|
190
|
+
* when it is drawn; a step that cannot go forward says why beside the field
|
|
191
|
+
* and puts the cursor in it. The answers are the same object the single form
|
|
192
|
+
* held, and only the review turns them into the job, through the same
|
|
193
|
+
* `aiSiteStartBrief` and `aiSiteStartInputs`. Each step is reported as a
|
|
194
|
+
* funnel, with where people struggle (`ai-site-start-tracking.ts`).
|
|
195
|
+
*/ export function AiSiteStartCard({ hostId, orgId, orgSlug, host, startBlank, leave, pendingSite, initialAnswers = null }) {
|
|
196
|
+
var _ref, _ref1, _ref2, _aiFreeSitePrompt;
|
|
222
197
|
var _aiSiteKindOfInputs, _modelChoice_options_options_find, _modelChoice_options;
|
|
223
198
|
const { data: user } = useUser();
|
|
224
199
|
const router = useRouter();
|
|
@@ -228,10 +203,28 @@ export function AiSiteStartCard({ hostId, orgId, orgSlug, host, startBlank, leav
|
|
|
228
203
|
userRef.current = user;
|
|
229
204
|
const uid = (_ref = user == null ? void 0 : user.uid) != null ? _ref : null;
|
|
230
205
|
const [verdict, setVerdict] = useState('checking');
|
|
206
|
+
// "Start again" on a start whose empty site was removed (AGL-3936) opens
|
|
207
|
+
// Create site with that start's answers: read once, and only here, where
|
|
208
|
+
// the site does not exist yet. It opens on the first question, where the
|
|
209
|
+
// site's name and address are asked, with every answer after it filled in.
|
|
210
|
+
const [handedOff] = useState(()=>pendingSite && !initialAnswers ? readAiSiteStartAnswers() : null);
|
|
231
211
|
// Read once: a start reopened on its answers stays one while it is open.
|
|
232
|
-
const reopened = useRef(initialAnswers !== null);
|
|
233
|
-
|
|
234
|
-
const [
|
|
212
|
+
const reopened = useRef(initialAnswers !== null || handedOff !== null);
|
|
213
|
+
// A start reopened on its answers opens on the review, every answer there to change.
|
|
214
|
+
const [step, setStep] = useState(initialAnswers ? 'review' : 'choose');
|
|
215
|
+
const [answers, setAnswers] = useState((_ref1 = initialAnswers != null ? initialAnswers : handedOff) != null ? _ref1 : AI_SITE_START_ANSWERS);
|
|
216
|
+
// The steps whose reasons not to go forward are shown: the ones Next was refused on.
|
|
217
|
+
const [checked, setChecked] = useState(()=>new Set());
|
|
218
|
+
// A step opened from the review's Edit goes back to the review on Next.
|
|
219
|
+
const [returnTo, setReturnTo] = useState(null);
|
|
220
|
+
// Each step's heading takes the focus when the step changes, never on the first draw.
|
|
221
|
+
const headingRef = useRef(null);
|
|
222
|
+
const drawnStep = useRef(null);
|
|
223
|
+
const fieldRefs = useRef({});
|
|
224
|
+
const theme = useTheme();
|
|
225
|
+
const compact = useMediaQuery(theme.breakpoints.down('sm'), {
|
|
226
|
+
noSsr: true
|
|
227
|
+
});
|
|
235
228
|
const [busy, setBusy] = useState(false);
|
|
236
229
|
// The starter card's own busy state while `startBlank` runs (AGL-3594).
|
|
237
230
|
const [startingStarter, setStartingStarter] = useState(false);
|
|
@@ -254,6 +247,8 @@ export function AiSiteStartCard({ hostId, orgId, orgSlug, host, startBlank, leav
|
|
|
254
247
|
const pendingRef = useRef(pendingSite);
|
|
255
248
|
pendingRef.current = pendingSite;
|
|
256
249
|
const creating = Boolean(pendingSite) && !(pendingSite == null ? void 0 : pendingSite.created);
|
|
250
|
+
// The funnel (AGL-3898): each step drawn, left and abandoned, and where people struggle.
|
|
251
|
+
const tracker = useAiSiteStartTracking(step, verdict === 'ready');
|
|
257
252
|
useEffect(()=>{
|
|
258
253
|
if (!orgId || !uid) return;
|
|
259
254
|
let active = true;
|
|
@@ -306,7 +301,7 @@ export function AiSiteStartCard({ hostId, orgId, orgSlug, host, startBlank, leav
|
|
|
306
301
|
answers.pages
|
|
307
302
|
]);
|
|
308
303
|
// A store's first products and a blog's first posts are part of the start (AGL-3676, AGL-3798).
|
|
309
|
-
const siteKind = (
|
|
304
|
+
const siteKind = (_ref2 = (_aiSiteKindOfInputs = aiSiteKindOfInputs(aiSiteStartInputs(answers))) == null ? void 0 : _aiSiteKindOfInputs.id) != null ? _ref2 : null;
|
|
310
305
|
const prompt = freeTaste ? (_aiFreeSitePrompt = aiFreeSitePrompt(freeCredits, answers.pages, {
|
|
311
306
|
siteKind
|
|
312
307
|
})) != null ? _aiFreeSitePrompt : serverPrompt : null;
|
|
@@ -328,7 +323,7 @@ export function AiSiteStartCard({ hostId, orgId, orgSlug, host, startBlank, leav
|
|
|
328
323
|
// and the list is otherwise read when the picker opens.
|
|
329
324
|
const { load: loadModels, model: rememberedModel } = modelChoice;
|
|
330
325
|
useEffect(()=>{
|
|
331
|
-
if (!freeTaste && step === '
|
|
326
|
+
if (!freeTaste && step === 'review' && rememberedModel) loadModels();
|
|
332
327
|
}, [
|
|
333
328
|
freeTaste,
|
|
334
329
|
step,
|
|
@@ -425,6 +420,11 @@ export function AiSiteStartCard({ hostId, orgId, orgSlug, host, startBlank, leav
|
|
|
425
420
|
}
|
|
426
421
|
// The indicator and the launcher count it from the moment it exists.
|
|
427
422
|
publishAiJob(created);
|
|
423
|
+
// A removed start's answers have been used (AGL-3936).
|
|
424
|
+
clearAiSiteStartAnswers();
|
|
425
|
+
// The funnel's last step: the site is started, and nothing after is leaving it.
|
|
426
|
+
tracker.complete();
|
|
427
|
+
tracker.finish();
|
|
428
428
|
// Where the next step is (AGL-3594): the site's "Building your site"
|
|
429
429
|
// page for this job. The zone closes without the starter first, so the
|
|
430
430
|
// setup page does not ask again behind it.
|
|
@@ -455,7 +455,8 @@ export function AiSiteStartCard({ hostId, orgId, orgSlug, host, startBlank, leav
|
|
|
455
455
|
router,
|
|
456
456
|
pickedModel,
|
|
457
457
|
pendingSite,
|
|
458
|
-
siteKind
|
|
458
|
+
siteKind,
|
|
459
|
+
tracker
|
|
459
460
|
]);
|
|
460
461
|
// The zone's `startBlank`. Before the site exists it creates it with the
|
|
461
462
|
// starter, and answers `false` when it could not — most often a name or
|
|
@@ -478,24 +479,106 @@ export function AiSiteStartCard({ hostId, orgId, orgSlug, host, startBlank, leav
|
|
|
478
479
|
trackEvent('site_start_choice', {
|
|
479
480
|
choice: 'starter'
|
|
480
481
|
});
|
|
482
|
+
// The starter is a way to start, not a way to leave: no abandonment after it.
|
|
483
|
+
tracker.finish();
|
|
481
484
|
runStartBlank();
|
|
482
485
|
}, [
|
|
483
486
|
pendingSite,
|
|
484
|
-
runStartBlank
|
|
487
|
+
runStartBlank,
|
|
488
|
+
tracker
|
|
485
489
|
]);
|
|
486
490
|
const chooseAi = useCallback(()=>{
|
|
487
491
|
if (pendingSite && !pendingSite.created && !pendingSite.check()) return;
|
|
488
492
|
trackEvent('site_start_choice', {
|
|
489
493
|
choice: 'ai'
|
|
490
494
|
});
|
|
491
|
-
|
|
495
|
+
tracker.complete();
|
|
496
|
+
setStep('kind');
|
|
492
497
|
}, [
|
|
493
|
-
pendingSite
|
|
498
|
+
pendingSite,
|
|
499
|
+
tracker
|
|
494
500
|
]);
|
|
501
|
+
// The heading of each step takes the focus as the step is drawn, so a
|
|
502
|
+
// keyboard and a screen reader start where the new question does.
|
|
503
|
+
useEffect(()=>{
|
|
504
|
+
var _headingRef_current;
|
|
505
|
+
if (verdict !== 'ready') return;
|
|
506
|
+
if (drawnStep.current !== null && drawnStep.current !== step) (_headingRef_current = headingRef.current) == null ? void 0 : _headingRef_current.focus();
|
|
507
|
+
drawnStep.current = step;
|
|
508
|
+
}, [
|
|
509
|
+
step,
|
|
510
|
+
verdict
|
|
511
|
+
]);
|
|
512
|
+
/** Forward from a question step, when its answers may go forward. */ const next = useCallback(()=>{
|
|
513
|
+
if (step === 'choose' || step === 'review') return;
|
|
514
|
+
const errors = aiSiteStartStepErrors(step, answers, {
|
|
515
|
+
freeTaste
|
|
516
|
+
});
|
|
517
|
+
if (errors.length) {
|
|
518
|
+
var _fieldRefs_current_errors__field;
|
|
519
|
+
setChecked((current)=>new Set(current).add(step));
|
|
520
|
+
for (const error of errors)tracker.fieldError(error.field, error.code);
|
|
521
|
+
(_fieldRefs_current_errors__field = fieldRefs.current[errors[0].field]) == null ? void 0 : _fieldRefs_current_errors__field.focus();
|
|
522
|
+
return;
|
|
523
|
+
}
|
|
524
|
+
tracker.complete();
|
|
525
|
+
const target = returnTo != null ? returnTo : aiSiteStartNextStep(step);
|
|
526
|
+
setReturnTo(null);
|
|
527
|
+
// A review reached with an answer that cannot go forward opens on that answer instead.
|
|
528
|
+
if (target === 'review') {
|
|
529
|
+
const invalid = aiSiteStartFirstInvalidStep(answers, {
|
|
530
|
+
freeTaste
|
|
531
|
+
});
|
|
532
|
+
if (invalid && invalid !== 'review') {
|
|
533
|
+
setChecked((current)=>new Set(current).add(invalid));
|
|
534
|
+
setStep(invalid);
|
|
535
|
+
return;
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
if (target) setStep(target);
|
|
539
|
+
}, [
|
|
540
|
+
step,
|
|
541
|
+
answers,
|
|
542
|
+
freeTaste,
|
|
543
|
+
returnTo,
|
|
544
|
+
tracker
|
|
545
|
+
]);
|
|
546
|
+
/** Back one step, keeping every answer. */ const back = useCallback(()=>{
|
|
547
|
+
const target = aiSiteStartPreviousStep(step);
|
|
548
|
+
if (!target) return;
|
|
549
|
+
tracker.back();
|
|
550
|
+
setReturnTo(null);
|
|
551
|
+
setStep(target);
|
|
552
|
+
}, [
|
|
553
|
+
step,
|
|
554
|
+
tracker
|
|
555
|
+
]);
|
|
556
|
+
/** From the review, to the step that asks an answer, and back to the review on Next. */ const edit = useCallback((target)=>{
|
|
557
|
+
tracker.back();
|
|
558
|
+
setReturnTo('review');
|
|
559
|
+
setStep(target);
|
|
560
|
+
}, [
|
|
561
|
+
tracker
|
|
562
|
+
]);
|
|
563
|
+
/** From the progress, back to a step already answered: from the review it is Edit. */ const goBackTo = (target)=>{
|
|
564
|
+
if (aiSiteStartStepIndex(target) >= aiSiteStartStepIndex(step)) return;
|
|
565
|
+
if (step === 'review') {
|
|
566
|
+
edit(target);
|
|
567
|
+
return;
|
|
568
|
+
}
|
|
569
|
+
tracker.back();
|
|
570
|
+
setReturnTo(null);
|
|
571
|
+
setStep(target);
|
|
572
|
+
};
|
|
495
573
|
if (verdict !== 'ready') return null;
|
|
496
574
|
// Before a job is started Skip is the blank site, which writes the starter
|
|
497
575
|
// (AGL-3594); after, it only closes — the job builds the site.
|
|
498
576
|
const exit = started ? leave != null ? leave : runStartBlank : runStartBlank;
|
|
577
|
+
// Skip, as the header draws it: before a site is started it is leaving the questions.
|
|
578
|
+
const skip = ()=>{
|
|
579
|
+
if (!started) tracker.abandon('skip');
|
|
580
|
+
exit();
|
|
581
|
+
};
|
|
499
582
|
// Escape and the close control. Before "Create site" has made the site
|
|
500
583
|
// (AGL-3761) there is nothing to give a starter to, so they only close,
|
|
501
584
|
// and nothing is created; otherwise they are the same way out as Skip.
|
|
@@ -513,11 +596,16 @@ export function AiSiteStartCard({ hostId, orgId, orgSlug, host, startBlank, leav
|
|
|
513
596
|
if (root && target instanceof Node && !root.contains(target)) return;
|
|
514
597
|
}
|
|
515
598
|
if (drafted) setConfirmingLeave(true);
|
|
516
|
-
else
|
|
599
|
+
else closeTo();
|
|
600
|
+
};
|
|
601
|
+
// The dismissal itself, once nothing typed is in the way of it.
|
|
602
|
+
const closeTo = ()=>{
|
|
603
|
+
if (!started) tracker.abandon('close');
|
|
604
|
+
dismissTo();
|
|
517
605
|
};
|
|
518
606
|
const leaveDraft = ()=>{
|
|
519
607
|
setConfirmingLeave(false);
|
|
520
|
-
|
|
608
|
+
closeTo();
|
|
521
609
|
};
|
|
522
610
|
// The chosen model's cost against Auto's, as the model list states it.
|
|
523
611
|
const modelMultiplier = pickedModel && ((_modelChoice_options = modelChoice.options) == null ? void 0 : (_modelChoice_options_options_find = _modelChoice_options.options.find((option)=>option.id === pickedModel)) == null ? void 0 : _modelChoice_options_options_find.multiplier) || 1;
|
|
@@ -538,12 +626,71 @@ export function AiSiteStartCard({ hostId, orgId, orgSlug, host, startBlank, leav
|
|
|
538
626
|
// Free workspaces — never the month's whole allowance as if none were spent.
|
|
539
627
|
const estimateText = freeTaste ? freeCredits ? `${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)}` : `${aiCreditRangeText(estimate)}, of the ${FREE_AI_TASTE_CREDITS_PER_MONTH} AI credits you get free each month` : `${aiCreditRangeText(estimate)}, estimated`;
|
|
540
628
|
const choosing = step === 'choose' && !started;
|
|
629
|
+
const reviewing = step === 'review' && !started;
|
|
630
|
+
const asking = step !== 'choose' && !started;
|
|
631
|
+
// Each answer's reason not to go forward, shown on a step once Next was refused there.
|
|
632
|
+
const fieldErrors = aiSiteStartFieldErrors(answers, {
|
|
633
|
+
freeTaste
|
|
634
|
+
});
|
|
635
|
+
const shownErrors = Object.fromEntries(AI_SITE_START_STEP_FIELDS[step].filter((field)=>checked.has(step) && fieldErrors[field]).map((field)=>[
|
|
636
|
+
field,
|
|
637
|
+
fieldErrors[field]
|
|
638
|
+
]));
|
|
639
|
+
const stepProps = {
|
|
640
|
+
answers,
|
|
641
|
+
answer,
|
|
642
|
+
tracker,
|
|
643
|
+
errors: shownErrors,
|
|
644
|
+
fieldRef: (field)=>(node)=>{
|
|
645
|
+
fieldRefs.current[field] = node;
|
|
646
|
+
}
|
|
647
|
+
};
|
|
648
|
+
const HEADINGS = {
|
|
649
|
+
choose: {
|
|
650
|
+
title: 'How do you want to start?',
|
|
651
|
+
lede: creating ? 'Name your site, then choose how it starts. You can change everything later.' : 'You can change everything later.'
|
|
652
|
+
},
|
|
653
|
+
kind: {
|
|
654
|
+
title: 'What are you building?',
|
|
655
|
+
lede: `Say it in a few words, or pick the closest. ${PLATFORM_BRAND_NAME} AI plans and writes your pages from it.`
|
|
656
|
+
},
|
|
657
|
+
audience: {
|
|
658
|
+
title: 'Who is it for?',
|
|
659
|
+
lede: 'The pages and the contact form are written for them.'
|
|
660
|
+
},
|
|
661
|
+
style: {
|
|
662
|
+
title: 'Choose a style',
|
|
663
|
+
lede: 'Each picture is an example home page in that style. Yours is written for your business, with its own colors and fonts within the style you pick.'
|
|
664
|
+
},
|
|
665
|
+
details: {
|
|
666
|
+
title: 'A few details',
|
|
667
|
+
lede: 'Where messages go, how many pages, and what else to draft. All can be changed later.'
|
|
668
|
+
},
|
|
669
|
+
review: {
|
|
670
|
+
title: 'Review your site',
|
|
671
|
+
lede: started ? `${PLATFORM_BRAND_NAME} AI is on it.` : `${PLATFORM_BRAND_NAME} AI plans and writes your pages from these answers, then publishes your site.`
|
|
672
|
+
}
|
|
673
|
+
};
|
|
674
|
+
const heading = HEADINGS[step];
|
|
675
|
+
// Enter in a text answer is Next. A select, a card or a button keeps its own Enter.
|
|
676
|
+
const onStepKeyDown = (event)=>{
|
|
677
|
+
if (event.key !== 'Enter' || event.nativeEvent.isComposing || !asking || reviewing) return;
|
|
678
|
+
const target = event.target;
|
|
679
|
+
if (target.tagName !== 'INPUT' || target.type === 'hidden') return;
|
|
680
|
+
event.preventDefault();
|
|
681
|
+
next();
|
|
682
|
+
};
|
|
541
683
|
return /*#__PURE__*/ _jsxs(Dialog, {
|
|
542
684
|
open: true,
|
|
543
685
|
fullScreen: true,
|
|
544
686
|
ref: dialogRef,
|
|
545
687
|
onClose: dismiss,
|
|
546
688
|
"aria-labelledby": TITLE_ID,
|
|
689
|
+
// Where people get lost (AGL-3898): any input puts off the idle signal,
|
|
690
|
+
// and every click is read for rage and dead clicks.
|
|
691
|
+
onClickCapture: (event)=>tracker.click(aiSiteStartClickOf(event)),
|
|
692
|
+
onKeyDownCapture: ()=>tracker.activity(),
|
|
693
|
+
onInputCapture: ()=>tracker.activity(),
|
|
547
694
|
// The console's own page surface, in both modes. A Dialog's paper sits
|
|
548
695
|
// at elevation 24 by default, and in dark mode MUI lightens an elevated
|
|
549
696
|
// paper with a white overlay, which turned the whole takeover a
|
|
@@ -561,6 +708,7 @@ export function AiSiteStartCard({ hostId, orgId, orgSlug, host, startBlank, leav
|
|
|
561
708
|
color: "inherit",
|
|
562
709
|
elevation: 0,
|
|
563
710
|
enableColorOnDark: true,
|
|
711
|
+
"data-start-area": "header",
|
|
564
712
|
sx: _extends({}, AI_SITE_START_SURFACE_SX, {
|
|
565
713
|
borderBottom: 1,
|
|
566
714
|
borderColor: 'divider'
|
|
@@ -593,7 +741,7 @@ export function AiSiteStartCard({ hostId, orgId, orgSlug, host, startBlank, leav
|
|
|
593
741
|
}),
|
|
594
742
|
/*#__PURE__*/ _jsx(Button, {
|
|
595
743
|
color: "inherit",
|
|
596
|
-
onClick:
|
|
744
|
+
onClick: skip,
|
|
597
745
|
"aria-label": started ? 'Close' : 'Skip and start blank',
|
|
598
746
|
children: started ? 'Close' : 'Skip'
|
|
599
747
|
})
|
|
@@ -607,8 +755,9 @@ export function AiSiteStartCard({ hostId, orgId, orgSlug, host, startBlank, leav
|
|
|
607
755
|
sm: 3
|
|
608
756
|
}
|
|
609
757
|
},
|
|
758
|
+
onKeyDown: onStepKeyDown,
|
|
610
759
|
children: /*#__PURE__*/ _jsx(Container, {
|
|
611
|
-
maxWidth: choosing ? 'md' : 'sm',
|
|
760
|
+
maxWidth: choosing || step === 'kind' || step === 'style' ? 'md' : 'sm',
|
|
612
761
|
disableGutters: true,
|
|
613
762
|
sx: {
|
|
614
763
|
py: {
|
|
@@ -619,30 +768,39 @@ export function AiSiteStartCard({ hostId, orgId, orgSlug, host, startBlank, leav
|
|
|
619
768
|
children: /*#__PURE__*/ _jsxs(Stack, {
|
|
620
769
|
spacing: 4,
|
|
621
770
|
children: [
|
|
622
|
-
/*#__PURE__*/ _jsx(
|
|
623
|
-
activeStep: choosing ? 0 : 1,
|
|
624
|
-
"aria-label": choosing ? 'Step 1 of 2' : 'Step 2 of 2',
|
|
771
|
+
/*#__PURE__*/ _jsx(Box, {
|
|
625
772
|
sx: {
|
|
626
|
-
maxWidth: (
|
|
773
|
+
maxWidth: (t)=>t.spacing(80),
|
|
627
774
|
width: '100%',
|
|
628
775
|
mx: 'auto'
|
|
629
776
|
},
|
|
630
|
-
children:
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
777
|
+
children: /*#__PURE__*/ _jsx(StartProgress, {
|
|
778
|
+
step: step,
|
|
779
|
+
compact: compact,
|
|
780
|
+
onStep: started ? undefined : goBackTo
|
|
781
|
+
})
|
|
635
782
|
}),
|
|
636
783
|
/*#__PURE__*/ _jsxs(Stack, {
|
|
637
784
|
spacing: 1,
|
|
638
785
|
sx: {
|
|
639
786
|
textAlign: choosing ? 'center' : 'left'
|
|
640
787
|
},
|
|
788
|
+
"data-start-area": "heading",
|
|
641
789
|
children: [
|
|
642
790
|
/*#__PURE__*/ _jsx(Typography, {
|
|
791
|
+
ref: headingRef,
|
|
792
|
+
tabIndex: -1,
|
|
643
793
|
variant: "h4",
|
|
644
794
|
component: "h1",
|
|
645
|
-
|
|
795
|
+
sx: {
|
|
796
|
+
'&:focus': {
|
|
797
|
+
outline: 'none'
|
|
798
|
+
},
|
|
799
|
+
'&:focus-visible': {
|
|
800
|
+
outline: 'none'
|
|
801
|
+
}
|
|
802
|
+
},
|
|
803
|
+
children: heading.title
|
|
646
804
|
}),
|
|
647
805
|
/*#__PURE__*/ _jsxs(Typography, {
|
|
648
806
|
variant: "body1",
|
|
@@ -652,18 +810,22 @@ export function AiSiteStartCard({ hostId, orgId, orgSlug, host, startBlank, leav
|
|
|
652
810
|
sx: {
|
|
653
811
|
float: 'right'
|
|
654
812
|
}
|
|
655
|
-
}, START_HELP.choose)) :
|
|
656
|
-
|
|
813
|
+
}, START_HELP.choose)) : /*#__PURE__*/ _jsx(StepHelp, {
|
|
814
|
+
step: step
|
|
815
|
+
}),
|
|
816
|
+
heading.lede
|
|
657
817
|
]
|
|
658
818
|
})
|
|
659
819
|
]
|
|
660
820
|
}),
|
|
661
821
|
notice && /*#__PURE__*/ _jsx(Alert, {
|
|
662
822
|
severity: "info",
|
|
823
|
+
"data-start-area": "notice",
|
|
663
824
|
children: notice
|
|
664
825
|
}),
|
|
665
|
-
|
|
826
|
+
asking && noneLeft && freeCredits && /*#__PURE__*/ _jsx(Alert, {
|
|
666
827
|
severity: "warning",
|
|
828
|
+
"data-start-area": "notice",
|
|
667
829
|
action: orgSlug ? /*#__PURE__*/ _jsx(Button, {
|
|
668
830
|
color: "inherit",
|
|
669
831
|
size: "small",
|
|
@@ -672,19 +834,6 @@ export function AiSiteStartCard({ hostId, orgId, orgSlug, host, startBlank, leav
|
|
|
672
834
|
}) : undefined,
|
|
673
835
|
children: aiFreeCreditsNoneLeftText(freeCredits.resetsOn)
|
|
674
836
|
}),
|
|
675
|
-
step === 'describe' && !started && !noneLeft && prompt && /*#__PURE__*/ _jsx(AiCreditsPromptNotice, {
|
|
676
|
-
prompt: prompt,
|
|
677
|
-
noun: "site",
|
|
678
|
-
orgSlug: orgSlug,
|
|
679
|
-
busy: busy,
|
|
680
|
-
onBuildWhatFits: ()=>void plan({
|
|
681
|
-
creditsConfirmed: true
|
|
682
|
-
}),
|
|
683
|
-
onSmaller: ()=>void plan({
|
|
684
|
-
creditsConfirmed: true,
|
|
685
|
-
pages: 1
|
|
686
|
-
})
|
|
687
|
-
}),
|
|
688
837
|
choosing && creating && pendingSite ? /*#__PURE__*/ _jsxs(Stack, {
|
|
689
838
|
spacing: 2,
|
|
690
839
|
component: "section",
|
|
@@ -697,6 +846,7 @@ export function AiSiteStartCard({ hostId, orgId, orgSlug, host, startBlank, leav
|
|
|
697
846
|
]
|
|
698
847
|
}) : null,
|
|
699
848
|
choosing ? /*#__PURE__*/ _jsxs(Box, {
|
|
849
|
+
"data-start-area": "choose-cards",
|
|
700
850
|
sx: {
|
|
701
851
|
display: 'grid',
|
|
702
852
|
gridTemplateColumns: {
|
|
@@ -754,153 +904,33 @@ export function AiSiteStartCard({ hostId, orgId, orgSlug, host, startBlank, leav
|
|
|
754
904
|
// Full screen: AI jobs opens in the panel this dialog covers.
|
|
755
905
|
onOpenJobs: exit
|
|
756
906
|
})
|
|
757
|
-
}) : /*#__PURE__*/ _jsxs(
|
|
907
|
+
}) : /*#__PURE__*/ _jsxs(Box, {
|
|
908
|
+
component: "section",
|
|
758
909
|
children: [
|
|
759
|
-
/*#__PURE__*/
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
gap: 1
|
|
784
|
-
},
|
|
785
|
-
children: AI_SITE_START_TYPES.map((type)=>/*#__PURE__*/ _jsx(Chip, {
|
|
786
|
-
label: type,
|
|
787
|
-
size: "small",
|
|
788
|
-
color: answers.siteType === type ? 'primary' : 'default',
|
|
789
|
-
variant: answers.siteType === type ? 'filled' : 'outlined',
|
|
790
|
-
onClick: ()=>answer({
|
|
791
|
-
siteType: type
|
|
792
|
-
})
|
|
793
|
-
}, type))
|
|
794
|
-
}),
|
|
795
|
-
/*#__PURE__*/ _jsx(TextField, {
|
|
796
|
-
fullWidth: true,
|
|
797
|
-
label: "Who is it for?",
|
|
798
|
-
placeholder: "local dog owners who want a regular groom booked online",
|
|
799
|
-
value: answers.audience,
|
|
800
|
-
onChange: (event)=>answer({
|
|
801
|
-
audience: event.target.value
|
|
802
|
-
}),
|
|
803
|
-
helperText: "Optional. It narrows who the pages are written for."
|
|
804
|
-
})
|
|
805
|
-
]
|
|
806
|
-
}),
|
|
807
|
-
/*#__PURE__*/ _jsxs(Stack, {
|
|
808
|
-
spacing: 2,
|
|
809
|
-
component: "section",
|
|
810
|
-
"aria-label": "Style",
|
|
811
|
-
children: [
|
|
812
|
-
/*#__PURE__*/ _jsx(SectionLabel, {
|
|
813
|
-
help: START_HELP.style,
|
|
814
|
-
children: 'Style'
|
|
815
|
-
}),
|
|
816
|
-
/*#__PURE__*/ _jsx(Typography, {
|
|
817
|
-
variant: "body2",
|
|
818
|
-
color: "text.secondary",
|
|
819
|
-
children: answers.kind ? 'This decides how your site looks and which pages it usually has.' : 'Picked from your answer above. Choose another to change how your site looks and which pages it usually has.'
|
|
820
|
-
}),
|
|
821
|
-
/*#__PURE__*/ _jsx(OptionCardGrid, {
|
|
822
|
-
label: "Style of site",
|
|
823
|
-
options: AI_SITE_KINDS.map((kind)=>({
|
|
824
|
-
id: kind.id,
|
|
825
|
-
title: kind.label,
|
|
826
|
-
description: kind.blurb,
|
|
827
|
-
icon: AI_SITE_KIND_ICONS[kind.id]
|
|
828
|
-
})),
|
|
829
|
-
value: aiSiteStartKind(answers).id,
|
|
830
|
-
onChange: (kind)=>answer({
|
|
831
|
-
kind
|
|
832
|
-
})
|
|
833
|
-
})
|
|
834
|
-
]
|
|
835
|
-
}),
|
|
836
|
-
/*#__PURE__*/ _jsxs(Stack, {
|
|
837
|
-
spacing: 2,
|
|
838
|
-
component: "section",
|
|
839
|
-
"aria-label": "Details",
|
|
840
|
-
children: [
|
|
841
|
-
/*#__PURE__*/ _jsx(SectionLabel, {
|
|
842
|
-
help: START_HELP.details,
|
|
843
|
-
children: 'Details'
|
|
844
|
-
}),
|
|
845
|
-
/*#__PURE__*/ _jsx(TextField, {
|
|
846
|
-
select: true,
|
|
847
|
-
fullWidth: true,
|
|
848
|
-
label: "Where do form submissions go?",
|
|
849
|
-
value: answers.submissions,
|
|
850
|
-
onChange: (event)=>answer({
|
|
851
|
-
submissions: event.target.value
|
|
852
|
-
}),
|
|
853
|
-
helperText: "You can change this on the form itself afterwards.",
|
|
854
|
-
children: AI_SITE_SUBMISSION_CHOICES.map((option)=>/*#__PURE__*/ _jsx(MenuItem, {
|
|
855
|
-
value: option.id,
|
|
856
|
-
children: `${option.label} — ${option.blurb}`
|
|
857
|
-
}, option.id))
|
|
858
|
-
}),
|
|
859
|
-
/*#__PURE__*/ _jsxs(Stack, {
|
|
860
|
-
direction: {
|
|
861
|
-
xs: 'column',
|
|
862
|
-
sm: 'row'
|
|
863
|
-
},
|
|
864
|
-
spacing: 2,
|
|
865
|
-
children: [
|
|
866
|
-
/*#__PURE__*/ _jsx(TextField, {
|
|
867
|
-
select: true,
|
|
868
|
-
fullWidth: true,
|
|
869
|
-
label: "Pages",
|
|
870
|
-
value: answers.pages,
|
|
871
|
-
onChange: (event)=>answer({
|
|
872
|
-
pages: Number(event.target.value)
|
|
873
|
-
}),
|
|
874
|
-
helperText: freeTaste ? AI_SITE_FREE_PAGES_NOTE : undefined,
|
|
875
|
-
children: Array.from({
|
|
876
|
-
length: band.max - band.min + 1
|
|
877
|
-
}, (_, index)=>band.min + index).map((count)=>/*#__PURE__*/ _jsx(MenuItem, {
|
|
878
|
-
value: count,
|
|
879
|
-
children: count
|
|
880
|
-
}, count))
|
|
881
|
-
}),
|
|
882
|
-
!freeTaste && /*#__PURE__*/ _jsxs(TextField, {
|
|
883
|
-
select: true,
|
|
884
|
-
fullWidth: true,
|
|
885
|
-
label: "Welcome email",
|
|
886
|
-
value: answers.welcomeEmail ? 'yes' : 'no',
|
|
887
|
-
onChange: (event)=>answer({
|
|
888
|
-
welcomeEmail: event.target.value === 'yes'
|
|
889
|
-
}),
|
|
890
|
-
children: [
|
|
891
|
-
/*#__PURE__*/ _jsx(MenuItem, {
|
|
892
|
-
value: "yes",
|
|
893
|
-
children: 'Draft one'
|
|
894
|
-
}),
|
|
895
|
-
/*#__PURE__*/ _jsx(MenuItem, {
|
|
896
|
-
value: "no",
|
|
897
|
-
children: 'No'
|
|
898
|
-
})
|
|
899
|
-
]
|
|
900
|
-
})
|
|
901
|
-
]
|
|
902
|
-
})
|
|
903
|
-
]
|
|
910
|
+
step === 'kind' && /*#__PURE__*/ _jsx(KindStep, _extends({}, stepProps)),
|
|
911
|
+
step === 'audience' && /*#__PURE__*/ _jsx(AudienceStep, _extends({}, stepProps)),
|
|
912
|
+
step === 'style' && /*#__PURE__*/ _jsx(StyleStep, _extends({}, stepProps)),
|
|
913
|
+
step === 'details' && /*#__PURE__*/ _jsx(DetailsStep, _extends({}, stepProps, {
|
|
914
|
+
freeTaste: freeTaste,
|
|
915
|
+
band: band
|
|
916
|
+
})),
|
|
917
|
+
step === 'review' && /*#__PURE__*/ _jsx(ReviewStep, {
|
|
918
|
+
answers: answers,
|
|
919
|
+
freeTaste: freeTaste,
|
|
920
|
+
onEdit: edit,
|
|
921
|
+
children: !noneLeft && prompt && /*#__PURE__*/ _jsx(AiCreditsPromptNotice, {
|
|
922
|
+
prompt: prompt,
|
|
923
|
+
noun: "site",
|
|
924
|
+
orgSlug: orgSlug,
|
|
925
|
+
busy: busy,
|
|
926
|
+
onBuildWhatFits: ()=>void plan({
|
|
927
|
+
creditsConfirmed: true
|
|
928
|
+
}),
|
|
929
|
+
onSmaller: ()=>void plan({
|
|
930
|
+
creditsConfirmed: true,
|
|
931
|
+
pages: 1
|
|
932
|
+
})
|
|
933
|
+
})
|
|
904
934
|
})
|
|
905
935
|
]
|
|
906
936
|
})
|
|
@@ -908,8 +938,9 @@ export function AiSiteStartCard({ hostId, orgId, orgSlug, host, startBlank, leav
|
|
|
908
938
|
})
|
|
909
939
|
})
|
|
910
940
|
}),
|
|
911
|
-
|
|
941
|
+
asking && /* The footer stays put while the questions scroll. It wraps, because
|
|
912
942
|
the estimate, the reason and the buttons are wider than a phone. */ /*#__PURE__*/ _jsxs(DialogActions, {
|
|
943
|
+
"data-start-area": "footer",
|
|
913
944
|
sx: _extends({
|
|
914
945
|
px: {
|
|
915
946
|
xs: 2,
|
|
@@ -923,7 +954,7 @@ export function AiSiteStartCard({ hostId, orgId, orgSlug, host, startBlank, leav
|
|
|
923
954
|
borderColor: 'divider'
|
|
924
955
|
}, AI_SITE_START_SURFACE_SX),
|
|
925
956
|
children: [
|
|
926
|
-
/*#__PURE__*/ _jsxs(Stack, {
|
|
957
|
+
reviewing && /*#__PURE__*/ _jsxs(Stack, {
|
|
927
958
|
direction: "row",
|
|
928
959
|
spacing: 0.5,
|
|
929
960
|
sx: {
|
|
@@ -942,20 +973,23 @@ export function AiSiteStartCard({ hostId, orgId, orgSlug, host, startBlank, leav
|
|
|
942
973
|
}))
|
|
943
974
|
]
|
|
944
975
|
}),
|
|
945
|
-
refusal && /*#__PURE__*/ _jsx(Typography, {
|
|
976
|
+
reviewing && refusal && /*#__PURE__*/ _jsx(Typography, {
|
|
946
977
|
variant: "body2",
|
|
947
978
|
color: "text.secondary",
|
|
948
979
|
children: refusal
|
|
949
980
|
}),
|
|
950
|
-
!freeTaste && /*#__PURE__*/ _jsx(AiModelSelector, {
|
|
981
|
+
reviewing && !freeTaste && /*#__PURE__*/ _jsx(AiModelSelector, {
|
|
951
982
|
choice: modelChoice,
|
|
952
983
|
disabled: busy
|
|
953
984
|
}),
|
|
954
985
|
/*#__PURE__*/ _jsx(Button, {
|
|
955
|
-
onClick:
|
|
986
|
+
onClick: back,
|
|
987
|
+
sx: reviewing ? undefined : {
|
|
988
|
+
mr: 'auto'
|
|
989
|
+
},
|
|
956
990
|
children: 'Back'
|
|
957
991
|
}),
|
|
958
|
-
/*#__PURE__*/ _jsx(Button, {
|
|
992
|
+
reviewing ? /*#__PURE__*/ _jsx(Button, {
|
|
959
993
|
variant: "contained",
|
|
960
994
|
size: "large",
|
|
961
995
|
disabled: busy || Boolean(refusal) || Boolean(prompt) || noneLeft,
|
|
@@ -964,6 +998,11 @@ export function AiSiteStartCard({ hostId, orgId, orgSlug, host, startBlank, leav
|
|
|
964
998
|
path: mdiCreation.path
|
|
965
999
|
}),
|
|
966
1000
|
children: busy ? 'Starting…' : 'Plan my site'
|
|
1001
|
+
}) : /*#__PURE__*/ _jsx(Button, {
|
|
1002
|
+
variant: "contained",
|
|
1003
|
+
size: "large",
|
|
1004
|
+
onClick: next,
|
|
1005
|
+
children: returnTo === 'review' ? 'Back to review' : 'Next'
|
|
967
1006
|
})
|
|
968
1007
|
]
|
|
969
1008
|
}),
|