Skip to content

Commit 415b3d9

Browse files
HardeepAsraniselul
andauthored
feat: improvements to upsell link positioning (#4450)
* feat: improvements to upsell link positioning * feat: add buttons to all pages * fix: make nav tab reactive --------- Co-authored-by: Marius Cristea <marius.cristea@vertistudio.com>
1 parent 2308e32 commit 415b3d9

7 files changed

Lines changed: 153 additions & 79 deletions

File tree

assets/apps/dashboard/src/Components/Content/FreePro.js

Lines changed: 1 addition & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,10 @@
22

33
import { __ } from '@wordpress/i18n';
44

5-
import {
6-
CheckCircle2,
7-
XCircle,
8-
HelpCircle,
9-
ArrowRight,
10-
BookOpen,
11-
} from 'lucide-react';
5+
import { CheckCircle2, XCircle, HelpCircle } from 'lucide-react';
126

137
import Card from '../../Layout/Card';
148
import Tooltip from '../Common/Tooltip';
15-
import Button from '../Common/Button';
169
import TransitionWrapper from '../Common/TransitionWrapper';
1710

1811
const FreeProCard = () => (
@@ -80,63 +73,12 @@ const FreeProCard = () => (
8073
</Card>
8174
);
8275

83-
const UpsellCard = () => {
84-
return (
85-
<Card>
86-
<div className="max-w-2xl mx-auto">
87-
<h3 className="text-lg font-semibold mb-4">
88-
{__('Need help deciding?', 'neve')}
89-
</h3>
90-
<div className="space-y-4 mb-6 text-gray-600">
91-
<p>
92-
{__(
93-
'Our support team is happy to answer your questions about specific Pro features and help you determine if they match your needs.',
94-
'neve'
95-
)}
96-
</p>
97-
<div className="flex items-start space-x-2">
98-
<div className="bg-gray-100 px-3 py-1.5 rounded">
99-
{__(
100-
'Average response time: ~8 hours during business days',
101-
'neve'
102-
)}
103-
</div>
104-
</div>
105-
</div>
106-
<div className="flex gap-4">
107-
<Button
108-
isPrimary
109-
href={neveDash.upgradeURL}
110-
target="_blank"
111-
className="gap-"
112-
>
113-
{__('View Pro Plans', 'neve')}
114-
<ArrowRight className="ml-2" size={16} />
115-
</Button>
116-
<Button
117-
isLink
118-
href="https://themeisle.com/contact"
119-
target="_blank"
120-
className="!border-gray-300"
121-
>
122-
{__('Contact Support', 'neve')}
123-
<BookOpen className="ml-2" size={16} />
124-
</Button>
125-
</div>
126-
</div>
127-
</Card>
128-
);
129-
};
130-
13176
export default () => {
13277
return (
13378
<div className="grid gap-6">
13479
<TransitionWrapper from="top">
13580
<FreeProCard />
13681
</TransitionWrapper>
137-
<TransitionWrapper className="delay-150">
138-
<UpsellCard />
139-
</TransitionWrapper>
14082
</div>
14183
);
14284
};

assets/apps/dashboard/src/Components/Content/ModuleGrid.js

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,12 @@
22
import { useDispatch, useSelect } from '@wordpress/data';
33
import { useState } from '@wordpress/element';
44
import { __ } from '@wordpress/i18n';
5-
import { LoaderCircle, LucideCheck, LucideSettings } from 'lucide-react';
5+
import {
6+
LoaderCircle,
7+
LucideCheck,
8+
LucideSettings,
9+
LucideExternalLink,
10+
} from 'lucide-react';
611

712
import useLicenseData from '../../Hooks/useLicenseData';
813
import Card from '../../Layout/Card';
@@ -137,12 +142,14 @@ const ModulesHeader = () => {
137142
: __('Neve Pro Modules', 'neve')}
138143
</h2>
139144
{!isLicenseValid && (
140-
<Link
141-
className="text-sm font-medium"
142-
text={__('Get Neve Pro', 'neve')}
143-
url={neveDash.upgradeURLModules}
144-
isExternal
145-
/>
145+
<Button
146+
isPrimary
147+
href={neveDash.upgradeURLModules}
148+
target="_blank"
149+
>
150+
{__('Get Neve Pro', 'neve')}
151+
<LucideExternalLink size={16} className="shrink-0" />
152+
</Button>
146153
)}
147154
</div>
148155
);

assets/apps/dashboard/src/Components/Content/Settings/GeneralTabContent.js

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {
77
LucideMonitorDown,
88
LucideTags,
99
LucideType,
10+
LucideExternalLink,
1011
} from 'lucide-react';
1112
import useLicenseData from '../../../Hooks/useLicenseData';
1213
import { NEVE_HAS_VALID_PRO } from '../../../utils/constants';
@@ -16,6 +17,7 @@ import OptionGroup from './OptionGroup';
1617
import ControlWrap from '../../Controls/ControlWrap';
1718
import Toggle from '../../Common/Toggle';
1819
import Select from '../../Common/Select';
20+
import Button from '../../Common/Button';
1921

2022
const DUMMY_SETTINGS_ARGS = {
2123
enable_featured_image_taxonomy: {
@@ -185,9 +187,22 @@ export default () => {
185187

186188
return (
187189
<>
188-
<h1 className="text-lg font-semibold mb-6">
189-
{__('General Settings', 'neve')}
190-
</h1>
190+
<div className="flex items-center justify-between mb-6">
191+
<h1 className="text-lg font-semibold">
192+
{__('General Settings', 'neve')}
193+
</h1>
194+
195+
{!isLicenseValid && (
196+
<Button
197+
isPrimary
198+
href={neveDash.upgradeURLModules}
199+
target="_blank"
200+
>
201+
{__('Get Neve Pro', 'neve')}
202+
<LucideExternalLink size={16} className="shrink-0" />
203+
</Button>
204+
)}
205+
</div>
191206

192207
<div>
193208
{(isLicenseValid && <ProModuleSettings />) || <DummySettings />}

assets/apps/dashboard/src/Components/Content/Settings/PerformanceTabContent.js

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,14 @@
11
/* global neveDash */
22
import { __ } from '@wordpress/i18n';
3-
import { LucideCode, LucideSmile, LucideText, LucideZap } from 'lucide-react';
3+
import {
4+
LucideCode,
5+
LucideSmile,
6+
LucideText,
7+
LucideZap,
8+
LucideExternalLink,
9+
} from 'lucide-react';
410
import ToggleControl from '../../Controls/ToggleControl';
11+
import Button from '../../Common/Button';
512
import useLicenseData from '../../../Hooks/useLicenseData';
613
import OptionGroup from './OptionGroup';
714

@@ -78,9 +85,22 @@ export default () => {
7885

7986
return (
8087
<>
81-
<h1 className="text-lg font-semibold mb-6">
82-
{__('Performance Settings', 'neve')}
83-
</h1>
88+
<div className="flex items-center justify-between mb-6">
89+
<h1 className="text-lg font-semibold">
90+
{__('Performance Settings', 'neve')}
91+
</h1>
92+
93+
{!isLicenseValid && (
94+
<Button
95+
isPrimary
96+
href={neveDash.upgradeURLModules}
97+
target="_blank"
98+
>
99+
{__('Get Neve Pro', 'neve')}
100+
<LucideExternalLink size={16} className="shrink-0" />
101+
</Button>
102+
)}
103+
</div>
84104

85105
<div>
86106
<ToggleControl

assets/apps/dashboard/src/Components/Content/Sidebar/Sidebar.js

Lines changed: 60 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
/* global neveDash */
12
import { changeOption } from '../../../utils/rest';
23
import SupportCard from './SupportCard';
34
import LicenseCard from './LicenseCard';
@@ -12,8 +13,9 @@ import {
1213
import Card from '../../../Layout/Card';
1314
import Link from '../../Common/Link';
1415
import Toggle from '../../Common/Toggle';
16+
import Button from '../../Common/Button';
1517
import PluginsCard from './PluginsCard';
16-
import { LucideLoaderCircle } from 'lucide-react';
18+
import { LucideLoaderCircle, ArrowRight, BookOpen } from 'lucide-react';
1719

1820
const ReviewCard = () => (
1921
<Card title={__('Leave us a review', 'neve')}>
@@ -107,6 +109,54 @@ const ContributingCard = () => {
107109
);
108110
};
109111

112+
const UpsellCard = () => {
113+
return (
114+
<Card>
115+
<div className="max-w-2xl mx-auto">
116+
<h3 className="text-lg font-semibold mb-4">
117+
{__('Need help deciding?', 'neve')}
118+
</h3>
119+
<div className="space-y-4 mb-6 text-gray-600">
120+
<p>
121+
{__(
122+
'Our support team is happy to answer your questions about specific Pro features and help you determine if they match your needs.',
123+
'neve'
124+
)}
125+
</p>
126+
<div className="flex items-start space-x-2">
127+
<div className="bg-gray-100 px-3 py-1.5 rounded">
128+
{__(
129+
'Average response time: ~8 hours during business days',
130+
'neve'
131+
)}
132+
</div>
133+
</div>
134+
</div>
135+
<div className="flex gap-4">
136+
<Button
137+
isPrimary
138+
href={neveDash.upgradeURL}
139+
target="_blank"
140+
className="gap-"
141+
>
142+
{__('View Pro Plans', 'neve')}
143+
<ArrowRight className="ml-2" size={16} />
144+
</Button>
145+
<Button
146+
isLink
147+
href="https://themeisle.com/contact"
148+
target="_blank"
149+
className="!border-gray-300"
150+
>
151+
{__('Contact Support', 'neve')}
152+
<BookOpen className="ml-2" size={16} />
153+
</Button>
154+
</div>
155+
</div>
156+
</Card>
157+
);
158+
};
159+
110160
const CommunityCard = () => {
111161
return (
112162
<Card title={__('Join the Community', 'neve')}>
@@ -127,12 +177,21 @@ const CommunityCard = () => {
127177
};
128178

129179
const Sidebar = () => {
180+
const { currentTab } = useSelect((select) => {
181+
const { getTab } = select(NEVE_STORE);
182+
return {
183+
currentTab: getTab(),
184+
};
185+
});
186+
130187
return (
131188
<div className="grid gap-6">
132189
{NEVE_HAS_PRO && <LicenseCard />}
133190

134191
{NEVE_HAS_PRO && <SupportCard />}
135192

193+
{currentTab === 'free-pro' && <UpsellCard />}
194+
136195
{!NEVE_IS_WHITELABEL && <ReviewCard />}
137196

138197
{!NEVE_HAS_PRO && <PluginsCard />}

assets/apps/dashboard/src/Components/Header.js

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,11 @@ import { Fragment, useEffect } from '@wordpress/element';
66
import { __ } from '@wordpress/i18n';
77

88
import { useDispatch, useSelect } from '@wordpress/data';
9-
import { LucideBookOpen, LucideFileText } from 'lucide-react';
9+
import {
10+
LucideBookOpen,
11+
LucideFileText,
12+
LucideExternalLink,
13+
} from 'lucide-react';
1014
import useLicenseData from '../Hooks/useLicenseData';
1115
import Container from '../Layout/Container';
1216
import { NEVE_IS_WHITELABEL, NEVE_STORE } from '../utils/constants';
@@ -107,6 +111,8 @@ const HeaderTopBar = ({ currentTab, setTab }) => {
107111
};
108112

109113
const Navigation = ({ setTab, currentTab }) => {
114+
const { isLicenseValid } = useLicenseData();
115+
110116
return (
111117
<div className="border-b border-gray-200">
112118
<Container>
@@ -115,13 +121,22 @@ const Navigation = ({ setTab, currentTab }) => {
115121
if (!label) {
116122
return null;
117123
}
124+
// Hide "Get Neve Pro" tab for users with valid licenses
125+
if (slug === 'get-neve-pro' && isLicenseValid) {
126+
return null;
127+
}
118128
const itemClasses = cn([
119129
'relative px-4 py-3 font-medium border-b-2',
120130
{
121131
'text-blue-600 border-blue-600':
122-
currentTab === slug,
132+
currentTab === slug &&
133+
slug !== 'get-neve-pro',
123134
'border-transparent text-gray-600 hover:text-gray-900 transition-colors duration-150':
124-
currentTab !== slug,
135+
currentTab !== slug &&
136+
slug !== 'get-neve-pro',
137+
'border-transparent text-blue-600 transition-colors duration-150':
138+
currentTab !== slug &&
139+
slug === 'get-neve-pro',
125140
},
126141
]);
127142

@@ -136,6 +151,9 @@ const Navigation = ({ setTab, currentTab }) => {
136151

137152
if (!url) {
138153
linkProps.onClick = handleLinkClick;
154+
} else {
155+
linkProps.target = '_blank';
156+
linkProps.rel = 'noopener noreferrer';
139157
}
140158

141159
return (
@@ -144,7 +162,15 @@ const Navigation = ({ setTab, currentTab }) => {
144162
key={slug}
145163
className={itemClasses}
146164
>
147-
{label}
165+
<span className="flex items-center gap-1">
166+
{label}
167+
{url && (
168+
<LucideExternalLink
169+
size={14}
170+
className="opacity-60"
171+
/>
172+
)}
173+
</span>
148174
</a>
149175
);
150176
})}

assets/apps/dashboard/src/utils/common.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,11 @@ const tabs = {
2929
changelog: {
3030
render: () => <Changelog />,
3131
},
32+
'get-neve-pro': {
33+
label: __('Get Neve Pro', 'neve'),
34+
url: neveDash.upgradeURLModules,
35+
external: true,
36+
},
3237
};
3338

3439
const { plugins } = neveDash;
@@ -68,7 +73,7 @@ const getTabHash = () => {
6873

6974
hash = hash.substring(1);
7075

71-
if (!tabs[hash]?.render) {
76+
if (!tabs[hash]?.render && !tabs[hash]?.url) {
7277
return null;
7378
}
7479

0 commit comments

Comments
 (0)