Skip to content

Commit c1050ee

Browse files
authored
Merge pull request #853 from Codeinwp/bf-24
Dashboard layout improvements & bf banner
2 parents b20eb1a + 43b63e9 commit c1050ee

File tree

10 files changed

+272
-32
lines changed

10 files changed

+272
-32
lines changed

assets/img/bf-bg.jpg

12.8 KB
Loading
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
import { Button } from '@wordpress/components';
2+
import { close } from '@wordpress/icons';
3+
import { useEffect, useState } from '@wordpress/element';
4+
import classNames from 'classnames';
5+
import { dismissNotice } from '../../utils/api';
6+
7+
export default () => {
8+
const { urgency, title, subtitle, cta_link, cta_text, dismiss_key } = optimoleDashboardApp.bf_notices.banner;
9+
const [ isVisible, setIsVisible ] = useState( true );
10+
const [ shouldRender, setShouldRender ] = useState( true );
11+
12+
const onClose = () => {
13+
dismissNotice( dismiss_key, () => {
14+
setIsVisible( false );
15+
});
16+
};
17+
18+
useEffect( () => {
19+
if ( ! isVisible ) {
20+
const timer = setTimeout( () => {
21+
setShouldRender( false );
22+
}, 300 );
23+
return () => clearTimeout( timer );
24+
}
25+
}, [ isVisible ]);
26+
27+
const wrapClasses = classNames(
28+
'relative flex flex-col items-center text-center xl:flex-row gap-5 justify-between xl:items-center bg-black text-white p-5 py-4 pr-7 box-border rounded-lg mt-5 bg-no-repeat transition-all duration-300',
29+
{
30+
'opacity-0': ! isVisible,
31+
'opacity-100': isVisible
32+
}
33+
);
34+
35+
if ( ! shouldRender ) {
36+
return null;
37+
}
38+
39+
return (
40+
<div className={wrapClasses}
41+
style={{
42+
backgroundImage: `url(${optimoleDashboardApp.assets_url}/img/bf-bg.jpg)`,
43+
backgroundPosition: 'right 0',
44+
backgroundSize: 'auto 100%'
45+
}}
46+
>
47+
<Button
48+
icon={close}
49+
onClick={onClose}
50+
label={optimoleDashboardApp.strings.csat.close}
51+
className="absolute right-1 top-1 cursor-pointer text-white hover:text-promo-orange"
52+
/>
53+
<div className="flex flex-col gap-3 xl:items-start items-center">
54+
<div className="text-sm lg:text-base border-b border-0 border-dashed uppercase pb-1 font-semibold">{urgency}</div>
55+
<div className="text-4xl lg:text-5xl italic uppercase font-extrabold" dangerouslySetInnerHTML={{ __html: title }}/>
56+
<div className="text-sm lg:text-base font-extrabold" dangerouslySetInnerHTML={{ __html: subtitle }}/>
57+
</div>
58+
59+
<a href={cta_link} target="_blank" className="bg-promo-orange text-white px-7 py-3 uppercase text-base font-bold grow flex justify-center max-w-[150px] text-center cursor-pointer hover:bg-white hover:text-orange-400 transition-colors">{cta_text}</a>
60+
</div>
61+
);
62+
};

assets/src/dashboard/parts/connected/Sidebar.js

Lines changed: 32 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,7 @@ const Sidebar = () => {
4141
});
4242

4343
return (
44-
<div
45-
className="flex flex-col mt-8 mb-5 p-0 transition-all ease-in-out duration-700 gap-5 basis-3/12"
46-
>
44+
<div className="grid md:grid-cols-2 xl:flex xl:flex-col xl:mt-8 xl:mb-5 p-0 transition-all ease-in-out duration-700 gap-5 basis-4/12 2xl:basis-3/12">
4745
<div className="bg-white gap-5 flex flex-col text-gray-700 border-0 rounded-lg shadow-md p-8">
4846
<TextControl
4947
label={ optimoleDashboardApp.strings.logged_in_as }
@@ -73,33 +71,41 @@ const Sidebar = () => {
7371

7472
{ 'free' === plan ? (
7573
<div
76-
className="bg-info flex flex-col text-white border-0 rounded-lg shadow-md p-8 bg-promo bg-no-repeat"
74+
className="bg-info flex flex-col text-white border-0 rounded-lg overflow-hidden shadow-md bg-promo bg-no-repeat"
7775
style={ {
7876
backgroundImage: `url( ${ optimoleDashboardApp.assets_url }/img/logo2.png )`
7977
} }
8078
>
81-
<h3 className="mt-0 text-white text-lg">{ optimoleDashboardApp.strings.upgrade.title_long }</h3>
82-
83-
<ul>
84-
{ reasons.map( ( reason, index ) => (
85-
<li
86-
key={ index }
87-
className="flex items-center gap-2"
88-
>
89-
<Icon icon="yes-alt" className="text-white" />
90-
<span className="text-white font-normal text-base">{ reason }</span>
91-
</li>
92-
) ) }
93-
</ul>
94-
95-
<Button
96-
variant="link"
97-
className="optml__button flex w-full justify-center font-bold min-h-40 !no-underline !text-white !bg-opaque-black !rounded"
98-
href={ optimoleDashboardApp.optimoleHome + 'pricing' }
99-
target="_blank"
100-
>
101-
{ optimoleDashboardApp.strings.upgrade.cta }
102-
</Button>
79+
{optimoleDashboardApp?.bf_notices?.sidebar && (
80+
<a href={optimoleDashboardApp.bf_notices.sidebar.cta_link} className="flex flex-col gap-3 p-3 bg-black !no-underline text-center cursor-pointer hover:opacity-90 transition-opacity" target="_blank">
81+
<span className="font-extrabold text-[17px] uppercase italic" dangerouslySetInnerHTML={{ __html: optimoleDashboardApp.bf_notices.sidebar.title }}/>
82+
<span className="text-[11px] font-bold" dangerouslySetInnerHTML={{ __html: optimoleDashboardApp.bf_notices.sidebar.subtitle }}/>
83+
</a>
84+
)}
85+
86+
<div className="p-8 flex flex-col">
87+
<h3 className="mt-0 text-white text-lg">{ optimoleDashboardApp.strings.upgrade.title_long }</h3>
88+
<ul>
89+
{ reasons.map( ( reason, index ) => (
90+
<li
91+
key={ index }
92+
className="flex items-center gap-2"
93+
>
94+
<Icon icon="yes-alt" className="text-white" />
95+
<span className="text-white font-normal text-base">{ reason }</span>
96+
</li>
97+
) ) }
98+
</ul>
99+
100+
<Button
101+
variant="link"
102+
className="optml__button flex w-full justify-center font-bold min-h-40 !no-underline !text-white !bg-opaque-black !rounded"
103+
href={ optimoleDashboardApp.optimoleHome + 'pricing' }
104+
target="_blank"
105+
>
106+
{ optimoleDashboardApp.strings.upgrade.cta }
107+
</Button>
108+
</div>
103109
</div>
104110
) : (
105111
<Button

assets/src/dashboard/parts/connected/index.js

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import Sidebar from './Sidebar';
2222
import CSAT from './CSAT';
2323
import { retrieveConflicts } from '../../utils/api';
2424
import formbricks from '@formbricks/js/app';
25+
import BlackFridayBanner from '../components/BlackFridayBanner';
2526
if ( 'undefined' !== typeof window && optimoleDashboardApp.user_data.plan ) {
2627
formbricks.init({
2728
environmentId: 'clo8wxwzj44orpm0gjchurujm',
@@ -144,10 +145,12 @@ const ConnectedLayout = ({
144145
}, [ canSave ]);
145146

146147
return (
147-
<>
148-
<div className="optml-connected max-w-screen-xl flex flex-col lg:flex-row mx-auto gap-5">
148+
<div className="optml-connected 2xl:max-w-screen-xl max-w-screen px-4 mx-auto">
149+
{optimoleDashboardApp?.bf_notices?.banner && <BlackFridayBanner/>}
150+
151+
<div className="flex flex-col xl:flex-row mx-auto gap-5">
149152
<div
150-
className="flex flex-col justify-between mt-8 mb-5 p-0 transition-all ease-in-out duration-700 relative text-gray-700 basis-9/12"
153+
className="flex flex-col justify-between mt-8 xl:mb-5 p-0 transition-all ease-in-out duration-700 relative text-gray-700 basis-8/12 2xl:basis-9/12"
151154
>
152155
{ 'dashboard' === tab && <Dashboard /> }
153156

@@ -171,7 +174,7 @@ const ConnectedLayout = ({
171174
</div>
172175

173176
<CSAT />
174-
</>
177+
</div>
175178
);
176179
};
177180

assets/src/dashboard/utils/api.js

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -603,4 +603,26 @@ export const addNotice = ( text ) => {
603603
);
604604
};
605605

606+
export const dismissNotice = ( key, callback = () => {}) => {
607+
apiFetch({
608+
path: optimoleDashboardApp.routes[ 'dismiss_notice' ],
609+
method: 'POST',
610+
data: {
611+
key
612+
}
613+
}).then( response => {
614+
if ( 'success' !== response.code ) {
615+
addNotice( response?.data?.error || optimoleDashboardApp.strings.options_strings.settings_saved_error );
616+
617+
return;
618+
}
619+
620+
if ( callback ) {
621+
callback( response );
622+
}
623+
}).catch( err => {
624+
addNotice( optimoleDashboardApp.strings.options_strings.settings_saved_error );
625+
});
626+
};
627+
606628

inc/admin.php

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ class Optml_Admin {
2020
const IMAGE_DATA_COLLECTED = 'optml_image_data_collected';
2121

2222
const IMAGE_DATA_COLLECTED_BATCH = 100;
23+
24+
const BF_PROMO_DISMISS_KEY = 'optml_bf24_notice_dismiss';
2325
/**
2426
* Hold the settings object.
2527
*
@@ -1333,9 +1335,66 @@ private function localize_dashboard_app() {
13331335
'hash' => '#settings',
13341336
],
13351337
],
1338+
'bf_notices' => $this->get_bf_notices(),
13361339
];
13371340
}
13381341

1342+
/**
1343+
* Get the black friday notices.
1344+
*
1345+
* @return array
1346+
*/
1347+
public function get_bf_notices() {
1348+
$date = new DateTime();
1349+
1350+
$now = time();
1351+
$start = strtotime( '2024-11-25 00:00:00' );
1352+
$end = strtotime( '2024-12-03 23:59:59' );
1353+
1354+
if ( $now < $start || $now > $end ) {
1355+
return [];
1356+
}
1357+
1358+
$notices = [
1359+
'sidebar' => [
1360+
'title' => sprintf(
1361+
'<span class="text-promo-orange">%1$s:</span> %2$s',
1362+
__( 'Private Sale', 'optimole-wp' ),
1363+
__( '25 Nov - 03 Dec', 'optimole-wp' )
1364+
),
1365+
'subtitle' => sprintf(
1366+
/* translators: 1 is the promo code, 2 is the discount amount ('25 off') */
1367+
__( 'Use code %1$s for %2$s on yearly plans.', 'optimole-wp' ),
1368+
'<span class="border-b border-0 border-white border-dashed text-promo-orange">BFCM2425</span>',
1369+
'<span class="text-promo-orange uppercase">' . __( '25% off', 'optimole-wp' ) . '</span>'
1370+
),
1371+
'cta_link' => esc_url_raw( tsdk_utmify( tsdk_translate_link( 'https://optimole.com/pricing' ), 'bfcm24', 'sidebarnotice' ) ),
1372+
],
1373+
];
1374+
1375+
if ( get_option( self::BF_PROMO_DISMISS_KEY ) === 'yes' ) {
1376+
return $notices;
1377+
}
1378+
1379+
$notices['banner'] = [
1380+
/* translators: number of days left */
1381+
'urgency' => sprintf( __( 'Hurry up! only %s left', 'optimole-wp' ), human_time_diff( $end, $now ) ),
1382+
/* translators: private sale */
1383+
'title' => sprintf( __( 'Black Friday %s', 'optimole-wp' ), '<span class="text-promo-orange">' . __( 'private sale' ) . '</span>' ),
1384+
'subtitle' => sprintf(
1385+
/* translators: 1 is the promo code, 2 is the discount amount ('25 off') */
1386+
__( 'Use coupon code %1$s for an instant %2$s on Optimole yearly plans', 'optimole-wp' ),
1387+
'<span class="border-b border-0 border-white border-dashed text-promo-orange">BFCM2425</span>',
1388+
'<span class="text-promo-orange">' . __( '25% discount', 'optimole-wp' ) . '</span>'
1389+
),
1390+
'cta_text' => __( 'Claim now', 'optimole-wp' ),
1391+
'cta_link' => esc_url_raw( tsdk_utmify( tsdk_translate_link( 'https://optimole.com/pricing' ), 'bfcm24', 'dismissiblenotice' ) ),
1392+
'dismiss_key' => self::BF_PROMO_DISMISS_KEY,
1393+
];
1394+
1395+
return $notices;
1396+
}
1397+
13391398
/**
13401399
* Get all dashboard strings.
13411400
*

inc/rest.php

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,17 @@ class Optml_Rest {
104104
'permission_callback' => 'upload_files',
105105
],
106106
],
107+
'notification_dismiss_routes' => [
108+
'dismiss_notice' => [
109+
'POST',
110+
'args' => [
111+
'key' => [
112+
'type' => 'string',
113+
'required' => true,
114+
],
115+
],
116+
],
117+
],
107118
];
108119

109120
/**
@@ -168,6 +179,7 @@ public function register() {
168179
$this->register_cache_routes();
169180
$this->register_media_offload_routes();
170181
$this->register_dam_routes();
182+
$this->register_notification_routes();
171183
}
172184

173185
/**
@@ -244,6 +256,17 @@ public function register_dam_routes() {
244256
}
245257
}
246258

259+
/**
260+
* Register notification dismiss routes.
261+
*
262+
* @return void
263+
*/
264+
public function register_notification_routes() {
265+
foreach ( self::$rest_routes['notification_dismiss_routes'] as $route => $details ) {
266+
$this->reqister_route( $route, $details[0], isset( $details['args'] ) ? $details['args'] : [] );
267+
}
268+
}
269+
247270
/**
248271
* Clear Cache request.
249272
*
@@ -887,4 +910,27 @@ public function insert_images( WP_REST_Request $request ) {
887910

888911
return $this->response( $insert );
889912
}
913+
914+
/**
915+
* Dismiss a notification (set the notification key to 'yes').
916+
*
917+
* @param WP_REST_Request $request the incoming request.
918+
*
919+
* @return WP_REST_Response
920+
*/
921+
public function dismiss_notice( WP_REST_Request $request ) {
922+
$key = $request->get_param( 'key' );
923+
924+
if ( empty( $key ) ) {
925+
return $this->response( [ 'error' => 'Invalid key' ], 'error' );
926+
}
927+
928+
$result = update_option( $key, 'yes' );
929+
930+
if ( ! $result ) {
931+
return $this->response( [ 'error' => 'Could not dismiss notice' ], 'error' );
932+
}
933+
934+
return $this->response( [ 'success' => 'Notice dismissed' ] );
935+
}
890936
}

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
},
1919
"scripts": {
2020
"build:dashboard": "wp-scripts build assets/src/dashboard/index.js --output-path=assets/build/dashboard",
21-
"dev:dashboard": "wp-scripts start assets/src/dashboard/index.js --output-path=assets/build/dashboard",
21+
"dev:dashboard": "wp-scripts start assets/src/dashboard/index.js --output-path=assets/build/dashboard --hot --allowed-hosts all",
2222
"build-dev:dashboard": "NODE_ENV=development wp-scripts build assets/src/dashboard/index.js --output-path=assets/build/dashboard",
2323
"build:media": "wp-scripts build assets/src/media/*.js --output-path=assets/build/media",
2424
"dev:media": "wp-scripts start assets/src/media/*.js --output-path=assets/build/media",

tailwind.config.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
11
/** @type {import('tailwindcss').Config} */
22
module.exports = {
33
content: [
4-
'./assets/src/**/*.js'
4+
'./assets/src/**/*.js',
5+
'./inc/admin.php'
56
],
67
theme: {
78
extend: {
89
backgroundPosition: {
910
'promo': '90% 70%'
1011
},
1112
colors: {
13+
'promo-orange': '#FF8811',
1214
'primary': '#EF686B',
1315
'success': '#5F9D61',
1416
'danger': '#E77777',

0 commit comments

Comments
 (0)