Skip to content

Commit 746fbb5

Browse files
committed
dev!: refactor for best practices
1 parent d78484a commit 746fbb5

39 files changed

+2320
-1697
lines changed
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import { createRoot } from 'react-dom/client';
2+
import OnboardingScreen, { type SiteType } from './page';
3+
4+
interface OneDesignSettings {
5+
nonce: string;
6+
site_type: SiteType | '';
7+
setup_url: string;
8+
}
9+
10+
declare global {
11+
interface Window {
12+
OneDesignSettings: OneDesignSettings;
13+
}
14+
}
15+
16+
// Render to the target element.
17+
const target = document.getElementById( 'onedesign-site-selection-modal' );
18+
if ( target ) {
19+
const root = createRoot( target );
20+
root.render( <OnboardingScreen /> );
21+
}
Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
import { useState, useEffect } from 'react';
2+
import apiFetch from '@wordpress/api-fetch';
3+
import { __ } from '@wordpress/i18n';
4+
import {
5+
Card,
6+
CardHeader,
7+
CardBody,
8+
Notice,
9+
Button,
10+
SelectControl,
11+
} from '@wordpress/components';
12+
13+
const BRAND_SITE = 'brand-site';
14+
const GOVERNING_SITE = 'governing-site';
15+
16+
export type SiteType = typeof BRAND_SITE | typeof GOVERNING_SITE;
17+
18+
interface NoticeState {
19+
type: 'success' | 'error' | 'warning' | 'info';
20+
message: string;
21+
}
22+
23+
const SiteTypeSelector = ( { value, setSiteType }: {
24+
value: SiteType | '';
25+
setSiteType: ( v: SiteType | '' ) => void;
26+
} ) => (
27+
<SelectControl
28+
label={ __( 'Site Type', 'onedesign' ) }
29+
value={ value }
30+
help={ __(
31+
"Choose your site's primary purpose. This setting cannot be changed later and affects available features and configurations.",
32+
'onedesign',
33+
) }
34+
onChange={ ( v ) => {
35+
setSiteType( v );
36+
} }
37+
options={ [
38+
{ label: __( 'Select…', 'onedesign' ), value: '' },
39+
{ label: __( 'Brand Site', 'onedesign' ), value: BRAND_SITE },
40+
{ label: __( 'Governing site', 'onedesign' ), value: GOVERNING_SITE },
41+
] }
42+
/>
43+
);
44+
45+
const OnboardingScreen = () => {
46+
// WordPress provides snake_case keys here. Using them intentionally.
47+
// eslint-disable-next-line camelcase
48+
const { nonce, setup_url, site_type } = window.OneDesignSettings;
49+
50+
const [ siteType, setSiteType ] = useState<SiteType | ''>( site_type || '' );
51+
const [ notice, setNotice ] = useState<NoticeState | null>( null );
52+
const [ isSaving, setIsSaving ] = useState<boolean>( false );
53+
54+
useEffect( () => {
55+
apiFetch.use( apiFetch.createNonceMiddleware( nonce ) );
56+
apiFetch<{ onedesign_site_type?: SiteType }>( { path: '/wp/v2/settings' } )
57+
.then( ( settings ) => {
58+
if ( settings?.onedesign_site_type ) {
59+
setSiteType( settings.onedesign_site_type );
60+
}
61+
} )
62+
.catch( () => {
63+
setNotice( {
64+
type: 'error',
65+
message: __( 'Error fetching site type.', 'onedesign' ),
66+
} );
67+
} );
68+
}, [ nonce ] );
69+
70+
const handleSiteTypeChange = async ( value: SiteType | '' ) => {
71+
// Optimistically set site type.
72+
setSiteType( value );
73+
setIsSaving( true );
74+
75+
try {
76+
await apiFetch<{ onedesign_site_type?: SiteType }>( {
77+
path: '/wp/v2/settings',
78+
method: 'POST',
79+
data: { onedesign_site_type: value },
80+
} ).then( ( settings ) => {
81+
if ( ! settings?.onedesign_site_type ) {
82+
throw new Error( 'No site type in response' );
83+
}
84+
85+
setSiteType( settings.onedesign_site_type );
86+
87+
// Redirect user to setup page.
88+
if ( setup_url ) {
89+
window.location.href = setup_url;
90+
}
91+
} );
92+
} catch {
93+
setNotice( {
94+
type: 'error',
95+
message: __( 'Error setting site type.', 'onedesign' ),
96+
} );
97+
} finally {
98+
setIsSaving( false );
99+
}
100+
};
101+
102+
return (
103+
<Card>
104+
{ !! notice?.message && (
105+
<Notice
106+
status={ notice?.type ?? 'success' }
107+
isDismissible={ true }
108+
onRemove={ () => setNotice( null ) }
109+
>
110+
{ notice?.message }
111+
</Notice>
112+
) }
113+
114+
<CardHeader>
115+
<h2>{ __( 'OneDesign', 'onedesign' ) }</h2>
116+
</CardHeader>
117+
118+
<CardBody className="onedesign-onboarding-page">
119+
<SiteTypeSelector
120+
value={ siteType }
121+
setSiteType={ setSiteType }
122+
/>
123+
<Button
124+
variant="primary"
125+
onClick={ () => handleSiteTypeChange( siteType ) }
126+
disabled={ isSaving || ! siteType }
127+
style={ { marginTop: '1.5rem' } }
128+
className={ isSaving ? 'is-busy' : '' }
129+
>
130+
{ __( 'Select Current Site Type', 'onedesign' ) }
131+
</Button>
132+
</CardBody>
133+
</Card>
134+
);
135+
};
136+
137+
export default OnboardingScreen;

assets/src/css/onboarding.scss

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
// Styles specific to the plugin onboarding (Plugins page)
2+
3+
.onedesign-onboarding-page {
4+
5+
.components-card {
6+
margin-bottom: 20px;
7+
border: 1px solid #ddd;
8+
border-radius: 8px;
9+
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
10+
}
11+
12+
.components-select-control {
13+
max-width: 320px;
14+
}
15+
16+
.components-button.is-busy {
17+
cursor: not-allowed;
18+
opacity: 0.7;
19+
}
20+
}
21+
22+
// Onboarding modal container and backdrop
23+
[id="onedesign-site-selection-modal"] {
24+
position: fixed;
25+
top: 50%;
26+
left: 50%;
27+
transform: translate(-50%, -50%);
28+
z-index: 10000;
29+
min-width: 40vw;
30+
}
31+
32+
body.onedesign-site-selection-modal {
33+
34+
&::before {
35+
content: "";
36+
position: fixed;
37+
top: 0;
38+
left: 0;
39+
width: 100%;
40+
height: 100%;
41+
background-color: rgba(0, 0, 0, 0.5);
42+
z-index: 9999;
43+
}
44+
45+
.wp-list-table {
46+
47+
th,
48+
td {
49+
padding: 12px 8px;
50+
}
51+
52+
code {
53+
background-color: #f8f9fa;
54+
padding: 2px 6px;
55+
border-radius: 3px;
56+
font-size: 11px;
57+
color: #333;
58+
}
59+
}
60+
}

composer.json

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,10 +42,7 @@
4242
"autoload": {
4343
"psr-4": {
4444
"OneDesign\\": "inc/"
45-
},
46-
"files": [
47-
"custom-functions.php"
48-
]
45+
}
4946
},
5047
"require": {
5148
"php": "^8"

0 commit comments

Comments
 (0)