PluginProbe
Extendify / 3.2.1
Extendify v3.2.1
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 / SiteInformation.jsx

SiteInformation.jsx in Extendify 3.2.1, at src/Launch/pages/SiteInformation.jsx

286 lines 9.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 import { getOption, updateOption } from '@launch/api/WPApi';
2 import { AcceptTerms } from '@launch/components/BusinessInformation/AcceptTerms';
3 import { SiteTones } from '@launch/components/BusinessInformation/Tones';
4 import { LoadingIndicator } from '@launch/components/LoadingIndicator';
5 import { Title } from '@launch/components/Title';
6 import { useFetch } from '@launch/hooks/useFetch';
7 import { PageLayout } from '@launch/layouts/PageLayout';
8 import { pageState } from '@launch/state/factory';
9 import { usePagesStore } from '@launch/state/Pages';
10 import { useUserSelectionStore } from '@launch/state/user-selections';
11 import { getUrlParameter } from '@shared/utils/get-url-parameter';
12 import { Tooltip } from '@wordpress/components';
13 import { useEffect, useLayoutEffect, useState } from '@wordpress/element';
14 import { decodeEntities } from '@wordpress/html-entities';
15 import { __ } from '@wordpress/i18n';
16 import { Icon, info } from '@wordpress/icons';
17
18 const fetcher = async () => ({ title: await getOption('blogname') });
19 const fetchData = () => ({ key: 'site-info' });
20 export const state = pageState('Site Information', () => ({
21 ready: false,
22 canSkip: false,
23 useNav: true,
24 onRemove: () => {},
25 }));
26 const descriptionUrlParameter = getUrlParameter('description', false);
27 const titleUrlParameter = getUrlParameter('title', false);
28
29 export const SiteInformation = () => {
30 const { loading } = useFetch(fetchData, fetcher);
31 const nextPage = usePagesStore((state) => state.nextPage);
32 const {
33 businessInformation,
34 setBusinessInformation,
35 siteInformation,
36 setSiteInformation,
37 setSiteProfile,
38 siteObjective,
39 setCTALink,
40 CTALink,
41 setUrlParameters,
42 setSiteQuestions,
43 siteQA,
44 setSiteStructure,
45 } = useUserSelectionStore();
46 const isLandingPage = siteObjective === 'landing-page';
47
48 let resolvedTitle = siteInformation.title;
49 const isTitleEmpty = !resolvedTitle;
50 const isTitleDefault = resolvedTitle === window.extSharedData.siteTitle;
51 if ((isTitleEmpty || isTitleDefault) && titleUrlParameter) {
52 resolvedTitle = titleUrlParameter;
53 }
54 const [title, setTitle] = useState(decodeEntities(resolvedTitle || ''));
55 const [description, setDescription] = useState(
56 businessInformation.description || descriptionUrlParameter || '',
57 );
58 const [callToActionLink, setCallToActionLink] = useState(CTALink || '');
59
60 useEffect(() => {
61 state.setState({ ready: false });
62 const timer = setTimeout(() => {
63 setSiteInformation('title', title);
64 setBusinessInformation('description', description);
65 if (isLandingPage && callToActionLink) {
66 setCTALink(callToActionLink);
67 }
68 state.setState({ ready: !!title.length });
69 setSiteProfile(undefined); // this also resets SOME state
70 updateOption('extendify_site_profile', null);
71 if (siteQA?.questions.length !== 0) {
72 setSiteQuestions({
73 showHidden: false,
74 questions: [],
75 });
76 setSiteStructure(undefined);
77 }
78 }, 1000);
79 return () => clearTimeout(timer);
80 }, [
81 title,
82 description,
83 setSiteInformation,
84 setBusinessInformation,
85 isLandingPage,
86 setCTALink,
87 callToActionLink,
88 setSiteProfile,
89 siteQA,
90 setSiteQuestions,
91 setSiteStructure,
92 ]);
93
94 useLayoutEffect(() => {
95 if (!titleUrlParameter && !descriptionUrlParameter) return;
96
97 setUrlParameters({
98 title: titleUrlParameter,
99 description: descriptionUrlParameter,
100 });
101 }, [setUrlParameters]);
102
103 const pageTitle = isLandingPage
104 ? __('Tell Us About Your Landing Page', 'extendify-local')
105 : __('Tell Us About Your Website', 'extendify-local');
106
107 const pageTitleDescription = isLandingPage
108 ? __(
109 "Share your vision, and we'll craft a landing page that's perfectly tailored to your needs, ready to launch in no time. Let's begin by learning more about what you're building.",
110 'extendify-local',
111 )
112 : __(
113 "Share your vision, and we'll craft a website that's perfectly tailored to your needs, ready to launch in no time. Let's begin by learning more about what you're building.",
114 'extendify-local',
115 );
116
117 return (
118 <PageLayout>
119 <div className="grow overflow-y-auto px-6 py-8 md:p-12 3xl:p-16">
120 <Title title={pageTitle} description={pageTitleDescription} />
121 <div className="relative mx-auto w-full max-w-xl">
122 {loading ? (
123 <LoadingIndicator />
124 ) : (
125 <form
126 className="flex w-full flex-col gap-4"
127 onSubmit={(e) => {
128 e.preventDefault();
129 if (!state.getState().ready) return;
130 nextPage();
131 }}
132 >
133 <SiteTitle
134 title={title}
135 setTitle={setTitle}
136 isLandingPage={isLandingPage}
137 />
138 <BusinessInfo
139 description={description}
140 setDescription={setDescription}
141 siteObjective={siteObjective}
142 />
143 {isLandingPage && !showSiteQuestions && (
144 <SiteCTA
145 title={callToActionLink}
146 setCTA={setCallToActionLink}
147 />
148 )}
149 <SiteTones />
150 <AcceptTerms />
151 </form>
152 )}
153 </div>
154 </div>
155 </PageLayout>
156 );
157 };
158
159 const SiteTitle = ({ title, setTitle, isLandingPage }) => {
160 return (
161 <div>
162 <label
163 htmlFor="extendify-site-title-input"
164 className="m-0 text-lg font-medium leading-8 text-gray-900 md:text-base md:leading-10"
165 >
166 {isLandingPage
167 ? __('Landing Page title (required)', 'extendify-local')
168 : __('Website title (required)', 'extendify-local')}
169 </label>
170 <input
171 data-test="site-title-input"
172 autoComplete="off"
173 // biome-ignore lint: allow autofocus here
174 autoFocus
175 type="text"
176 name="site-title-input"
177 id="extendify-site-title-input"
178 className="input-focus h-12 w-full rounded-sm border border-gray-200 px-4 py-6 ring-offset-0"
179 value={title}
180 onChange={(e) => setTitle(e.target.value)}
181 placeholder={__('Enter your website name', 'extendify-local')}
182 />
183 </div>
184 );
185 };
186
187 const objectivePlaceholders = {
188 business: __(
189 'E.g., We are a yoga studio in London with professionally trained instructors with focus on hot yoga for therapeutic purposes.',
190 'extendify-local',
191 ),
192 ecommerce: __(
193 'E.g., We are an online store specializing in eco-friendly home goods, offering sustainably sourced products to help you live a greener lifestyle.',
194 'extendify-local',
195 ),
196 blog: __(
197 'E.g., A personal finance blog sharing expert tips on budgeting, investing, and achieving financial freedom for young professionals.',
198 'extendify-local',
199 ),
200 'landing-page': __(
201 'E.g., A free ebook packed with actionable productivity tips and strategies to help you stay focused, manage your time effectively, and achieve your goals.',
202 'extendify-local',
203 ),
204 other: __(
205 'E.g., A personal photography portfolio featuring a collection of landscape, portrait, and street photography, capturing moments from around the world.',
206 'extendify-local',
207 ),
208 };
209 const objectiveLabels = {
210 business: __('Describe your business', 'extendify-local'),
211 ecommerce: __('Describe your eCommerce website', 'extendify-local'),
212 blog: __('Describe your blog', 'extendify-local'),
213 'landing-page': __('Describe your Landing Page', 'extendify-local'),
214 other: __('Describe your website', 'extendify-local'),
215 };
216
217 const showSiteQuestions = window.extSharedData?.showSiteQuestions ?? false;
218
219 const BusinessInfo = ({ description, setDescription, siteObjective }) => {
220 return (
221 <div>
222 <label
223 htmlFor="extendify-site-info-input"
224 className="m-0 text-lg font-medium leading-8 text-gray-900 md:text-base md:leading-10"
225 >
226 {showSiteQuestions
227 ? objectiveLabels.other
228 : (objectiveLabels[siteObjective] ?? objectiveLabels.business)}
229 </label>
230 <textarea
231 data-test="site-info-input"
232 autoComplete="off"
233 rows="4"
234 name="site-info-input"
235 id="extendify-site-info-input"
236 className={
237 'input-focus placeholder:text-base h-40 w-full rounded-lg border border-gray-300 p-2 ring-offset-0 placeholder:italic placeholder:opacity-50'
238 }
239 value={description}
240 onChange={(e) => setDescription(e.target.value)}
241 placeholder={
242 showSiteQuestions
243 ? objectivePlaceholders.other
244 : (objectivePlaceholders[siteObjective] ??
245 objectivePlaceholders.business)
246 }
247 />
248 </div>
249 );
250 };
251
252 const SiteCTA = ({ title, setCTA }) => {
253 return (
254 <div>
255 <div className="flex items-center space-x-1">
256 <label
257 htmlFor="extendify-site-cta-input"
258 className="m-0 text-lg font-medium leading-8 text-gray-900 md:text-base md:leading-10"
259 >
260 {__('Call-To-Action Link', 'extendify-local')}
261 </label>
262 <Tooltip
263 delay={100}
264 text={__(
265 'This link will be used in all Call-to-Action buttons, directing visitors to your chosen destination.',
266 'extendify-local',
267 )}
268 >
269 <Icon icon={info} size="16" className="fill-current text-gray-600" />
270 </Tooltip>
271 </div>
272 <input
273 data-test="site-cta-input"
274 autoComplete="off"
275 type="text"
276 name="site-cta-input"
277 id="extendify-site-cta-input"
278 className="input-focus h-12 w-full rounded-sm border border-gray-200 px-4 py-6 ring-offset-0 placeholder:italic placeholder:opacity-50"
279 value={title}
280 onChange={(e) => setCTA(e.target.value)}
281 placeholder=""
282 />
283 </div>
284 );
285 };
286