PluginProbe
Extendify / 3.0.4
Extendify v3.0.4
3.2.1 3.2.0 3.1.6 3.1.5 3.1.4 3.1.3 3.1.2 3.1.1 3.1.0 3.0.6 3.0.5 3.0.4 trunk 0.1.0 0.10.0 0.10.1 0.10.2 0.11.0 0.11.1 0.2.0 0.3.0 0.3.1 0.4.0 0.5.0 0.6.0 All 127 releases
extendify / src / Launch / pages / SiteQuestions.jsx

SiteQuestions.jsx in Extendify 3.0.4, at src/Launch/pages/SiteQuestions.jsx

221 lines 6.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 import { Questionnaire } from '@launch/components/Questionnaire';
2 import { Title } from '@launch/components/Title';
3 import { PageLayout } from '@launch/layouts/PageLayout';
4 import { pageState } from '@launch/state/factory';
5 import { useUserSelectionStore } from '@launch/state/user-selections';
6 import { useCallback, useEffect, useMemo, useRef } from '@wordpress/element';
7 import { __ } from '@wordpress/i18n';
8
9 export const state = pageState('Site Questions', () => ({
10 ready: false,
11 canSkip: false,
12 useNav: true,
13 onRemove: () => {},
14 }));
15
16 export const SiteQuestions = () => {
17 const {
18 siteQA,
19 setSiteQuestionAnswer,
20 setShowHiddenQuestions,
21 setSiteStructure,
22 setSiteObjective,
23 setCTALink,
24 siteObjective,
25 siteStructure,
26 urlParameters,
27 } = useUserSelectionStore();
28
29 const pageTitle = __(
30 "Let's review your AI-powered recommendations",
31 'extendify-local',
32 );
33
34 const pageDescription = __(
35 'Using the details you provided, our AI suggested the best settings for your site. Take a quick look and confirm everything looks right before moving on.',
36 'extendify-local',
37 );
38
39 const showHiddenQuestions = siteQA?.showHidden;
40 const hasHiddenQuestions =
41 Array.isArray(siteQA?.questions) &&
42 siteQA.questions.some((q) => q.group === 'hidden');
43
44 let questionsToRender = showHiddenQuestions
45 ? siteQA?.questions
46 : siteQA?.questions?.filter((q) => q.group === 'visible');
47
48 const hasQuestions =
49 Array.isArray(questionsToRender) && questionsToRender.length > 0;
50
51 const allAnswered =
52 hasQuestions &&
53 questionsToRender.every(
54 (question) => question?.answerUser || question?.answerAI,
55 );
56
57 const componentMounted = useRef(false);
58
59 useEffect(() => {
60 state.setState({ ready: allAnswered });
61 }, [allAnswered]);
62
63 const applyAnswerEffects = useCallback(
64 (questionId, answerId, options = {}) => {
65 if (questionId === 'pages') {
66 if (answerId === 'multiple-pages') setSiteStructure('multi-page');
67 if (answerId === 'one-page') setSiteStructure('single-page');
68 }
69
70 if (questionId === 'external-cta' && options?.isExtraField) {
71 setCTALink(answerId);
72 }
73 },
74 [setSiteStructure, setCTALink],
75 );
76
77 const handleChanges = (questionId, answerId, options = {}) => {
78 setSiteQuestionAnswer(questionId, answerId, options);
79 applyAnswerEffects(questionId, answerId, options);
80 };
81
82 const pagesAnswer = useMemo(() => {
83 return (
84 questionsToRender?.find((q) => q.id === 'pages')?.answerUser ||
85 questionsToRender?.find((q) => q.id === 'pages')?.answerAI
86 );
87 }, [questionsToRender]);
88
89 /**
90 * Temporary logic to force siteObjective to 'landing-page' and trigger
91 * the current LP flow. This will be replaced and removed in v2 of Landing Page flow.
92 */
93 const checkAndSetLP = useCallback(() => {
94 if (!questionsToRender || !questionsToRender.length) return;
95
96 const ctaAnswer =
97 questionsToRender.find((q) => q.id === 'external-cta')?.answerUser ||
98 questionsToRender.find((q) => q.id === 'external-cta')?.answerAI;
99
100 const otherQuestions = questionsToRender.filter(
101 (q) => !['pages', 'external-cta'].includes(q.id),
102 );
103 const allOthersNo = otherQuestions.every((q) => {
104 const ans = q?.answerUser || q?.answerAI;
105 return ans === 'no';
106 });
107
108 let newSiteObjective;
109 if (pagesAnswer === 'one-page' && ctaAnswer === 'yes' && allOthersNo) {
110 newSiteObjective = 'landing-page';
111 }
112
113 setSiteObjective(newSiteObjective);
114 }, [pagesAnswer, questionsToRender, setSiteObjective]);
115
116 useEffect(() => {
117 if (!hasQuestions) return;
118
119 checkAndSetLP();
120 }, [checkAndSetLP, hasQuestions]);
121
122 useEffect(() => {
123 if (!hasQuestions || componentMounted.current) return;
124
125 questionsToRender.forEach((question) => {
126 const answer = question?.answerUser || question?.answerAI;
127 if (!answer) return;
128
129 if (question.id === 'products' && siteObjective === 'ecommerce') {
130 setSiteQuestionAnswer(question.id, 'yes-shopping-cart');
131 }
132
133 if (question.id === 'pages') {
134 const mappedAnswer = {
135 'single-page': 'one-page',
136 'multi-page': 'multiple-pages',
137 };
138
139 if (mappedAnswer?.[siteStructure]) {
140 setSiteQuestionAnswer(question.id, mappedAnswer[siteStructure]);
141 return;
142 }
143 }
144
145 applyAnswerEffects(question.id, answer);
146 });
147
148 componentMounted.current = true;
149 }, [
150 applyAnswerEffects,
151 hasQuestions,
152 questionsToRender,
153 siteObjective,
154 setSiteQuestionAnswer,
155 siteStructure,
156 ]);
157
158 /**
159 * Check if the URL parameters contain a valid structure.
160 * If a valid structure is found, filter out the 'pages' question.
161 */
162 const hasValidStructureUrlParameter =
163 urlParameters?.structure === 'multi-page' ||
164 urlParameters?.structure === 'single-page';
165 if (hasValidStructureUrlParameter) {
166 questionsToRender = questionsToRender.filter(
167 (question) => question.id !== 'pages',
168 );
169 }
170
171 if (hasQuestions && pagesAnswer === 'multiple-pages') {
172 questionsToRender = questionsToRender.filter(
173 (question) => question.id !== 'external-cta',
174 );
175 }
176
177 return (
178 <PageLayout>
179 <div className="grow overflow-y-auto px-6 py-8 md:p-12 3xl:p-16">
180 <Title title={pageTitle} description={pageDescription} />
181 {!hasQuestions && (
182 <div className="text-center text-gray-500">
183 {__('Loading...', 'extendify-local')}
184 </div>
185 )}
186 {hasQuestions && (
187 <>
188 <Questionnaire
189 questions={questionsToRender}
190 onAnswerChange={handleChanges}
191 />
192
193 {hasHiddenQuestions && !showHiddenQuestions && (
194 <div className="flex justify-center">
195 <button
196 type="button"
197 className="mt-12 flex flex-col items-center bg-transparent text-base font-medium text-design-main"
198 onClick={() => setShowHiddenQuestions(true)}
199 >
200 {__('Show more questions', 'extendify-local')}
201 <svg
202 className="fill-current"
203 width="32"
204 height="32"
205 viewBox="0 0 32 32"
206 fill="none"
207 xmlns="http://www.w3.org/2000/svg"
208 >
209 <title>{__('Down Arrow Icon', 'extendify-local')}</title>
210 <path d="M23.3327 15.4672L15.9993 21.3339L8.66602 15.4672L9.86602 13.8672L15.9993 18.6672L21.9993 13.8672L23.3327 15.4672Z" />
211 </svg>
212 </button>
213 </div>
214 )}
215 </>
216 )}
217 </div>
218 </PageLayout>
219 );
220 };
221