PluginProbe
Extendify / 3.1.5
Extendify v3.1.5
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 0.7.0 All 126 releases
extendify / src / Launch / pages / PagesSelect.jsx

PagesSelect.jsx in Extendify 3.1.5, at src/Launch/pages/PagesSelect.jsx

218 lines 6.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 import { getPageTemplates } from '@launch/api/DataApi';
2 import { PagePreview } from '@launch/components/PagePreview';
3 import { PageSelectButton } from '@launch/components/PageSelectButton';
4 import { PageSelectButtonPlaceholder } from '@launch/components/PageSelectButtonPlaceholder';
5 import { ShoppingCart } from '@launch/components/QuestionIcon/Icons/shopping-cart';
6 import { Title } from '@launch/components/Title';
7 import { useFetch } from '@launch/hooks/useFetch';
8 import { PageLayout } from '@launch/layouts/PageLayout';
9 import { pageState } from '@launch/state/factory';
10 import { usePagesSelectionStore } from '@launch/state/pages-selections';
11 import { useUserSelectionStore } from '@launch/state/user-selections';
12 import { buildRecommendedPagesParams } from '@launch/utils/buildRecommendedPagesParams';
13 import { useEffect, useMemo, useRef, useState } from '@wordpress/element';
14 import { __ } from '@wordpress/i18n';
15
16 export const state = pageState('Pages', () => ({
17 ready: true,
18 canSkip: false,
19 useNav: true,
20 onRemove: () => {
21 // If the page is removed then clean up the selected pages
22 const { pages, remove } = usePagesSelectionStore.getState();
23 pages.forEach((page) => {
24 remove('pages', page);
25 });
26 },
27 }));
28
29 export const PagesSelect = () => {
30 const {
31 data: availablePages,
32 loading,
33 error,
34 } = useFetch(buildRecommendedPagesParams, getPageTemplates);
35 const [previewing, setPreviewing] = useState();
36 const [expandMore, setExpandMore] = useState();
37 const { siteInformation, siteObjective, siteQA } = useUserSelectionStore();
38 const { pages, remove, removeAll, add, has, style } =
39 usePagesSelectionStore();
40 const pagePreviewRef = useRef();
41
42 useEffect(() => {
43 state.setState({ ready: !loading && !error });
44 }, [loading, error]);
45
46 const homePage = useMemo(
47 () => ({
48 id: 'home-page',
49 slug: 'home-page',
50 name: __('Home page', 'extendify-local'),
51 patterns: style?.patterns
52 .flatMap(({ code }) => code)
53 .map((code, i) => ({
54 name: `pattern-${i}`,
55 code,
56 })),
57 }),
58 [style],
59 );
60 const styleMemo = useMemo(
61 () => ({ ...style, patterns: previewing?.patterns || [] }),
62 [style, previewing],
63 );
64
65 const handlePageToggle = (page) => {
66 if (has('pages', page)) {
67 remove('pages', page);
68 return;
69 }
70 add('pages', page);
71 return setPreviewing(page);
72 };
73
74 useEffect(() => {
75 // This needs two frames before the code is rendered
76 let raf2;
77 const id = requestAnimationFrame(() => {
78 raf2 = requestAnimationFrame(() => {
79 pagePreviewRef?.current?.scrollTo(0, 0);
80 });
81 });
82 return () => {
83 cancelAnimationFrame(id);
84 cancelAnimationFrame(raf2);
85 };
86 }, [previewing]);
87
88 useEffect(() => {
89 if (previewing) return;
90 setPreviewing(homePage);
91 }, [previewing, homePage]);
92
93 useEffect(() => {
94 if (!availablePages?.recommended) return;
95 // On re-load, remove any lingering pages and add the recommended ones
96 removeAll('pages');
97 availablePages.recommended.forEach((page) => {
98 add('pages', page);
99 });
100 }, [availablePages?.recommended, removeAll, add]);
101
102 const productsQuestion = siteQA?.questions?.find((q) => q.id === 'products');
103 const productsAnswer =
104 productsQuestion?.answerUser ?? productsQuestion?.answerAI;
105
106 return (
107 <PageLayout>
108 <div className="grow space-y-4 overflow-y-auto lg:flex lg:space-y-0">
109 <div className="lg:px-16 hidden h-full min-h-screen grow overflow-y-hidden bg-gray-100 px-4 pt-0 lg:block lg:min-h-0 lg:pb-0 xl:px-32">
110 <div className="flex h-full flex-col">
111 <h3 className="my-2 text-center text-base font-medium text-gray-700 lg:my-4 lg:text-lg">
112 {previewing?.name}
113 </h3>
114 <div
115 ref={pagePreviewRef}
116 className="relative h-full grow overflow-x-hidden rounded-t-lg lg:h-auto lg:overflow-y-auto"
117 >
118 {previewing && (
119 <PagePreview
120 ref={pagePreviewRef}
121 showNav={siteObjective !== 'landing-page'}
122 style={styleMemo}
123 siteTitle={siteInformation.title}
124 loading={loading}
125 />
126 )}
127 </div>
128 </div>
129 </div>
130 <div className="flex w-full flex-col items-center overflow-y-auto px-6 py-8 lg:max-w-lg lg:px-12">
131 <Title
132 title={__(
133 'Pick the pages to add to your website',
134 'extendify-local',
135 )}
136 description={__(
137 'We already selected the most common pages for your type of website.',
138 'extendify-local',
139 )}
140 />
141 <div
142 className="flex w-full flex-col gap-4 pb-4"
143 data-test="recommended-pages"
144 >
145 <PageSelectButton
146 page={homePage}
147 previewing={homePage.id === previewing?.id}
148 onPreview={() => setPreviewing(homePage)}
149 checked={true}
150 forceChecked={true}
151 onChange={() => undefined}
152 />
153 {!loading &&
154 !error &&
155 availablePages?.recommended?.map((page) => (
156 <PageSelectButton
157 key={page.id}
158 page={page}
159 previewing={page.id === previewing?.id}
160 onPreview={() => setPreviewing(page)}
161 checked={has('pages', page)}
162 onChange={() => handlePageToggle(page)}
163 />
164 ))}
165 {(loading || error) &&
166 Array.from({ length: 5 }, (_, index) => (
167 <PageSelectButtonPlaceholder key={index} />
168 ))}
169 </div>
170
171 {!loading && !expandMore && (
172 <div className="flex items-center justify-center">
173 <button
174 type="button"
175 data-test="expand-more"
176 onClick={setExpandMore}
177 className="button-focus my-4 bg-transparent text-center text-sm font-medium text-gray-900 hover:text-design-main"
178 >
179 {__('View more pages', 'extendify-local')}
180 </button>
181 </div>
182 )}
183
184 {expandMore && (
185 <div
186 className="flex w-full flex-col gap-4 pb-4"
187 data-test="optional-pages"
188 >
189 {availablePages?.optional?.map((page) => (
190 <PageSelectButton
191 key={page.id}
192 page={page}
193 previewing={page.id === previewing?.id}
194 onPreview={() => setPreviewing(page)}
195 checked={pages?.some((p) => p.id === page.id)}
196 onChange={() => handlePageToggle(page)}
197 />
198 ))}
199 </div>
200 )}
201
202 {!loading && productsAnswer === 'yes-shopping-cart' && (
203 <div className="flex gap-1.5 mt-7 mx-auto w-full rounded-sm inset-ring inset-ring-gray-900/8 bg-gray-900/2 px-3.5 py-3 text-sm">
204 <ShoppingCart />
205 <span>
206 {__(
207 'A "Shop" page will also be automatically created.',
208 'extendify-local',
209 )}
210 </span>
211 </div>
212 )}
213 </div>
214 </div>
215 </PageLayout>
216 );
217 };
218