Skip to content

Commit

Permalink
Merge pull request #853 from Codeinwp/bf-24
Browse files Browse the repository at this point in the history
Dashboard layout improvements & bf banner
  • Loading branch information
selul authored Nov 8, 2024
2 parents b20eb1a + 43b63e9 commit c1050ee
Show file tree
Hide file tree
Showing 10 changed files with 272 additions and 32 deletions.
Binary file added assets/img/bf-bg.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
62 changes: 62 additions & 0 deletions assets/src/dashboard/parts/components/BlackFridayBanner.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import { Button } from '@wordpress/components';
import { close } from '@wordpress/icons';
import { useEffect, useState } from '@wordpress/element';
import classNames from 'classnames';
import { dismissNotice } from '../../utils/api';

export default () => {
const { urgency, title, subtitle, cta_link, cta_text, dismiss_key } = optimoleDashboardApp.bf_notices.banner;
const [ isVisible, setIsVisible ] = useState( true );
const [ shouldRender, setShouldRender ] = useState( true );

const onClose = () => {
dismissNotice( dismiss_key, () => {
setIsVisible( false );
});
};

useEffect( () => {
if ( ! isVisible ) {
const timer = setTimeout( () => {
setShouldRender( false );
}, 300 );
return () => clearTimeout( timer );
}
}, [ isVisible ]);

const wrapClasses = classNames(
'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',
{
'opacity-0': ! isVisible,
'opacity-100': isVisible
}
);

if ( ! shouldRender ) {
return null;
}

return (
<div className={wrapClasses}
style={{
backgroundImage: `url(${optimoleDashboardApp.assets_url}/img/bf-bg.jpg)`,
backgroundPosition: 'right 0',
backgroundSize: 'auto 100%'
}}
>
<Button
icon={close}
onClick={onClose}
label={optimoleDashboardApp.strings.csat.close}
className="absolute right-1 top-1 cursor-pointer text-white hover:text-promo-orange"
/>
<div className="flex flex-col gap-3 xl:items-start items-center">
<div className="text-sm lg:text-base border-b border-0 border-dashed uppercase pb-1 font-semibold">{urgency}</div>
<div className="text-4xl lg:text-5xl italic uppercase font-extrabold" dangerouslySetInnerHTML={{ __html: title }}/>
<div className="text-sm lg:text-base font-extrabold" dangerouslySetInnerHTML={{ __html: subtitle }}/>
</div>

<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>
</div>
);
};
58 changes: 32 additions & 26 deletions assets/src/dashboard/parts/connected/Sidebar.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,7 @@ const Sidebar = () => {
});

return (
<div
className="flex flex-col mt-8 mb-5 p-0 transition-all ease-in-out duration-700 gap-5 basis-3/12"
>
<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">
<div className="bg-white gap-5 flex flex-col text-gray-700 border-0 rounded-lg shadow-md p-8">
<TextControl
label={ optimoleDashboardApp.strings.logged_in_as }
Expand Down Expand Up @@ -73,33 +71,41 @@ const Sidebar = () => {

{ 'free' === plan ? (
<div
className="bg-info flex flex-col text-white border-0 rounded-lg shadow-md p-8 bg-promo bg-no-repeat"
className="bg-info flex flex-col text-white border-0 rounded-lg overflow-hidden shadow-md bg-promo bg-no-repeat"
style={ {
backgroundImage: `url( ${ optimoleDashboardApp.assets_url }/img/logo2.png )`
} }
>
<h3 className="mt-0 text-white text-lg">{ optimoleDashboardApp.strings.upgrade.title_long }</h3>

<ul>
{ reasons.map( ( reason, index ) => (
<li
key={ index }
className="flex items-center gap-2"
>
<Icon icon="yes-alt" className="text-white" />
<span className="text-white font-normal text-base">{ reason }</span>
</li>
) ) }
</ul>

<Button
variant="link"
className="optml__button flex w-full justify-center font-bold min-h-40 !no-underline !text-white !bg-opaque-black !rounded"
href={ optimoleDashboardApp.optimoleHome + 'pricing' }
target="_blank"
>
{ optimoleDashboardApp.strings.upgrade.cta }
</Button>
{optimoleDashboardApp?.bf_notices?.sidebar && (
<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">
<span className="font-extrabold text-[17px] uppercase italic" dangerouslySetInnerHTML={{ __html: optimoleDashboardApp.bf_notices.sidebar.title }}/>
<span className="text-[11px] font-bold" dangerouslySetInnerHTML={{ __html: optimoleDashboardApp.bf_notices.sidebar.subtitle }}/>
</a>
)}

<div className="p-8 flex flex-col">
<h3 className="mt-0 text-white text-lg">{ optimoleDashboardApp.strings.upgrade.title_long }</h3>
<ul>
{ reasons.map( ( reason, index ) => (
<li
key={ index }
className="flex items-center gap-2"
>
<Icon icon="yes-alt" className="text-white" />
<span className="text-white font-normal text-base">{ reason }</span>
</li>
) ) }
</ul>

<Button
variant="link"
className="optml__button flex w-full justify-center font-bold min-h-40 !no-underline !text-white !bg-opaque-black !rounded"
href={ optimoleDashboardApp.optimoleHome + 'pricing' }
target="_blank"
>
{ optimoleDashboardApp.strings.upgrade.cta }
</Button>
</div>
</div>
) : (
<Button
Expand Down
11 changes: 7 additions & 4 deletions assets/src/dashboard/parts/connected/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import Sidebar from './Sidebar';
import CSAT from './CSAT';
import { retrieveConflicts } from '../../utils/api';
import formbricks from '@formbricks/js/app';
import BlackFridayBanner from '../components/BlackFridayBanner';
if ( 'undefined' !== typeof window && optimoleDashboardApp.user_data.plan ) {
formbricks.init({
environmentId: 'clo8wxwzj44orpm0gjchurujm',
Expand Down Expand Up @@ -144,10 +145,12 @@ const ConnectedLayout = ({
}, [ canSave ]);

return (
<>
<div className="optml-connected max-w-screen-xl flex flex-col lg:flex-row mx-auto gap-5">
<div className="optml-connected 2xl:max-w-screen-xl max-w-screen px-4 mx-auto">
{optimoleDashboardApp?.bf_notices?.banner && <BlackFridayBanner/>}

<div className="flex flex-col xl:flex-row mx-auto gap-5">
<div
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"
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"
>
{ 'dashboard' === tab && <Dashboard /> }

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

<CSAT />
</>
</div>
);
};

Expand Down
22 changes: 22 additions & 0 deletions assets/src/dashboard/utils/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -603,4 +603,26 @@ export const addNotice = ( text ) => {
);
};

export const dismissNotice = ( key, callback = () => {}) => {
apiFetch({
path: optimoleDashboardApp.routes[ 'dismiss_notice' ],
method: 'POST',
data: {
key
}
}).then( response => {
if ( 'success' !== response.code ) {
addNotice( response?.data?.error || optimoleDashboardApp.strings.options_strings.settings_saved_error );

return;
}

if ( callback ) {
callback( response );
}
}).catch( err => {
addNotice( optimoleDashboardApp.strings.options_strings.settings_saved_error );
});
};


59 changes: 59 additions & 0 deletions inc/admin.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ class Optml_Admin {
const IMAGE_DATA_COLLECTED = 'optml_image_data_collected';

const IMAGE_DATA_COLLECTED_BATCH = 100;

const BF_PROMO_DISMISS_KEY = 'optml_bf24_notice_dismiss';
/**
* Hold the settings object.
*
Expand Down Expand Up @@ -1333,9 +1335,66 @@ private function localize_dashboard_app() {
'hash' => '#settings',
],
],
'bf_notices' => $this->get_bf_notices(),
];
}

/**
* Get the black friday notices.
*
* @return array
*/
public function get_bf_notices() {
$date = new DateTime();

$now = time();
$start = strtotime( '2024-11-25 00:00:00' );
$end = strtotime( '2024-12-03 23:59:59' );

if ( $now < $start || $now > $end ) {
return [];
}

$notices = [
'sidebar' => [
'title' => sprintf(
'<span class="text-promo-orange">%1$s:</span> %2$s',
__( 'Private Sale', 'optimole-wp' ),
__( '25 Nov - 03 Dec', 'optimole-wp' )
),
'subtitle' => sprintf(
/* translators: 1 is the promo code, 2 is the discount amount ('25 off') */
__( 'Use code %1$s for %2$s on yearly plans.', 'optimole-wp' ),
'<span class="border-b border-0 border-white border-dashed text-promo-orange">BFCM2425</span>',
'<span class="text-promo-orange uppercase">' . __( '25% off', 'optimole-wp' ) . '</span>'
),
'cta_link' => esc_url_raw( tsdk_utmify( tsdk_translate_link( 'https://optimole.com/pricing' ), 'bfcm24', 'sidebarnotice' ) ),
],
];

if ( get_option( self::BF_PROMO_DISMISS_KEY ) === 'yes' ) {
return $notices;
}

$notices['banner'] = [
/* translators: number of days left */
'urgency' => sprintf( __( 'Hurry up! only %s left', 'optimole-wp' ), human_time_diff( $end, $now ) ),
/* translators: private sale */
'title' => sprintf( __( 'Black Friday %s', 'optimole-wp' ), '<span class="text-promo-orange">' . __( 'private sale' ) . '</span>' ),
'subtitle' => sprintf(
/* translators: 1 is the promo code, 2 is the discount amount ('25 off') */
__( 'Use coupon code %1$s for an instant %2$s on Optimole yearly plans', 'optimole-wp' ),
'<span class="border-b border-0 border-white border-dashed text-promo-orange">BFCM2425</span>',
'<span class="text-promo-orange">' . __( '25% discount', 'optimole-wp' ) . '</span>'
),
'cta_text' => __( 'Claim now', 'optimole-wp' ),
'cta_link' => esc_url_raw( tsdk_utmify( tsdk_translate_link( 'https://optimole.com/pricing' ), 'bfcm24', 'dismissiblenotice' ) ),
'dismiss_key' => self::BF_PROMO_DISMISS_KEY,
];

return $notices;
}

/**
* Get all dashboard strings.
*
Expand Down
46 changes: 46 additions & 0 deletions inc/rest.php
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,17 @@ class Optml_Rest {
'permission_callback' => 'upload_files',
],
],
'notification_dismiss_routes' => [
'dismiss_notice' => [
'POST',
'args' => [
'key' => [
'type' => 'string',
'required' => true,
],
],
],
],
];

/**
Expand Down Expand Up @@ -168,6 +179,7 @@ public function register() {
$this->register_cache_routes();
$this->register_media_offload_routes();
$this->register_dam_routes();
$this->register_notification_routes();
}

/**
Expand Down Expand Up @@ -244,6 +256,17 @@ public function register_dam_routes() {
}
}

/**
* Register notification dismiss routes.
*
* @return void
*/
public function register_notification_routes() {
foreach ( self::$rest_routes['notification_dismiss_routes'] as $route => $details ) {
$this->reqister_route( $route, $details[0], isset( $details['args'] ) ? $details['args'] : [] );
}
}

/**
* Clear Cache request.
*
Expand Down Expand Up @@ -887,4 +910,27 @@ public function insert_images( WP_REST_Request $request ) {

return $this->response( $insert );
}

/**
* Dismiss a notification (set the notification key to 'yes').
*
* @param WP_REST_Request $request the incoming request.
*
* @return WP_REST_Response
*/
public function dismiss_notice( WP_REST_Request $request ) {
$key = $request->get_param( 'key' );

if ( empty( $key ) ) {
return $this->response( [ 'error' => 'Invalid key' ], 'error' );
}

$result = update_option( $key, 'yes' );

if ( ! $result ) {
return $this->response( [ 'error' => 'Could not dismiss notice' ], 'error' );
}

return $this->response( [ 'success' => 'Notice dismissed' ] );
}
}
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
},
"scripts": {
"build:dashboard": "wp-scripts build assets/src/dashboard/index.js --output-path=assets/build/dashboard",
"dev:dashboard": "wp-scripts start assets/src/dashboard/index.js --output-path=assets/build/dashboard",
"dev:dashboard": "wp-scripts start assets/src/dashboard/index.js --output-path=assets/build/dashboard --hot --allowed-hosts all",
"build-dev:dashboard": "NODE_ENV=development wp-scripts build assets/src/dashboard/index.js --output-path=assets/build/dashboard",
"build:media": "wp-scripts build assets/src/media/*.js --output-path=assets/build/media",
"dev:media": "wp-scripts start assets/src/media/*.js --output-path=assets/build/media",
Expand Down
4 changes: 3 additions & 1 deletion tailwind.config.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
/** @type {import('tailwindcss').Config} */
module.exports = {
content: [
'./assets/src/**/*.js'
'./assets/src/**/*.js',
'./inc/admin.php'
],
theme: {
extend: {
backgroundPosition: {
'promo': '90% 70%'
},
colors: {
'promo-orange': '#FF8811',
'primary': '#EF686B',
'success': '#5F9D61',
'danger': '#E77777',
Expand Down
Loading

0 comments on commit c1050ee

Please sign in to comment.