PluginProbe
Extendify / 0.9.3
Extendify v0.9.3
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 / Onboarding / pages / SiteStyle.js

SiteStyle.js in Extendify 0.9.3, at src/Onboarding/pages/SiteStyle.js

149 lines 5.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 import {
2 useCallback,
3 useEffect,
4 useState,
5 useRef,
6 useMemo,
7 } from '@wordpress/element'
8 import { __, sprintf } from '@wordpress/i18n'
9 import { getStyles } from '@onboarding/api/DataApi'
10 import { StylePreview } from '@onboarding/components/StyledPreview'
11 import { useFetch } from '@onboarding/hooks/useFetch'
12 import { useIsMountedLayout } from '@onboarding/hooks/useIsMounted'
13 import { PageLayout } from '@onboarding/layouts/PageLayout'
14 import { useUserSelectionStore } from '@onboarding/state/UserSelections'
15 import { pageState } from '@onboarding/state/factory'
16 import { SpinnerIcon } from '@onboarding/svg'
17
18 export const fetcher = (params) => getStyles(params)
19 export const fetchData = (siteType) => {
20 siteType = siteType ?? useUserSelectionStore?.getState().siteType
21 return {
22 key: 'site-style',
23 siteType: siteType?.slug ?? 'default',
24 styles: siteType?.styles ?? [],
25 }
26 }
27 export const state = pageState('Design', (set, get) => ({
28 title: __('Design', 'extendify'),
29 default: undefined,
30 showInSidebar: true,
31 ready: false,
32 isDefault: () =>
33 useUserSelectionStore.getState().style?.slug === get().default?.slug,
34 }))
35 export const SiteStyle = () => {
36 const siteType = useUserSelectionStore((state) => state.siteType)
37 const { data: styleData, loading } = useFetch(fetchData, fetcher)
38 const once = useRef(false)
39 const stylesRef = useRef()
40 const isMounted = useIsMountedLayout()
41 const [styles, setStyles] = useState([])
42
43 useEffect(() => {
44 state.setState({ ready: !loading })
45 }, [loading])
46
47 useEffect(() => {
48 if (!styleData?.length) return
49 ;(async () => {
50 for (const style of styleData) {
51 if (!isMounted.current) return
52 setStyles((styles) => [...styles, style])
53 await new Promise((resolve) => setTimeout(resolve, 1000))
54 }
55 })()
56 }, [styleData, isMounted])
57
58 useEffect(() => {
59 if (styles?.length && !useUserSelectionStore.getState().style) {
60 useUserSelectionStore.getState().setStyle(styles[0])
61 state.setState({ default: styles[0] })
62 }
63 }, [styles])
64
65 useEffect(() => {
66 if (!styles?.length || once.current) return
67 once.current = true
68 // Focus the first style
69 stylesRef?.current?.querySelector('[role=button]')?.focus()
70 }, [styles])
71
72 return (
73 <PageLayout>
74 <div>
75 <h1 className="text-3xl text-partner-primary-text mb-4 mt-0">
76 {sprintf(
77 __(
78 'Now pick a design for your new %s site.',
79 'extendify',
80 ),
81 siteType?.label?.toLowerCase(),
82 )}
83 </h1>
84 <p className="text-base opacity-70 mb-0">
85 {__('You can personalize this later.', 'extendify')}
86 </p>
87 </div>
88 <div className="w-full">
89 <h2 className="text-lg m-0 mb-4 text-gray-900">
90 {loading
91 ? __(
92 'Please wait a moment while we generate style previews...',
93 'extendify',
94 )
95 : __('Pick your style', 'extendify')}
96 </h2>
97 <div
98 ref={stylesRef}
99 className="flex gap-6 flex-wrap justify-center">
100 {styles?.map((style) => (
101 <StylePreviewWrapper
102 key={style.recordId}
103 style={style}
104 />
105 ))}
106 {/* Budget skeleton loaders */}
107 {styleData?.slice(styles?.length).map((data) => (
108 <div
109 key={data.slug}
110 style={{ height: 497, width: 352 }}
111 className="relative">
112 <div className="bg-gray-50 h-full w-full flex items-center justify-center">
113 <SpinnerIcon className="spin w-8" />
114 </div>
115 </div>
116 ))}
117 </div>
118 </div>
119 </PageLayout>
120 )
121 }
122
123 const StylePreviewWrapper = ({ style }) => {
124 const onSelect = useCallback((style) => {
125 useUserSelectionStore.getState().setStyle(style)
126 }, [])
127 const context = useMemo(
128 () => ({
129 type: 'style',
130 detail: style.slug,
131 measure: true,
132 }),
133 [style],
134 )
135 return (
136 <div className="relative" style={{ height: 497, width: 352 }}>
137 <StylePreview
138 style={style}
139 context={context}
140 onSelect={onSelect}
141 active={
142 useUserSelectionStore.getState()?.style?.slug === style.slug
143 }
144 blockHeight={497}
145 />
146 </div>
147 )
148 }
149