Skip to content

Commit eeb887b

Browse files
committed
feat: improvements to upsell link positioning
1 parent 1b521a8 commit eeb887b

File tree

5 files changed

+110
-72
lines changed

5 files changed

+110
-72
lines changed

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/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: 24 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';
@@ -119,9 +123,14 @@ const Navigation = ({ setTab, currentTab }) => {
119123
'relative px-4 py-3 font-medium border-b-2',
120124
{
121125
'text-blue-600 border-blue-600':
122-
currentTab === slug,
126+
currentTab === slug &&
127+
slug !== 'get-neve-pro',
123128
'border-transparent text-gray-600 hover:text-gray-900 transition-colors duration-150':
124-
currentTab !== slug,
129+
currentTab !== slug &&
130+
slug !== 'get-neve-pro',
131+
'border-transparent text-blue-600 transition-colors duration-150':
132+
currentTab !== slug &&
133+
slug === 'get-neve-pro',
125134
},
126135
]);
127136

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

137146
if (!url) {
138147
linkProps.onClick = handleLinkClick;
148+
} else {
149+
linkProps.target = '_blank';
150+
linkProps.rel = 'noopener noreferrer';
139151
}
140152

141153
return (
@@ -144,7 +156,15 @@ const Navigation = ({ setTab, currentTab }) => {
144156
key={slug}
145157
className={itemClasses}
146158
>
147-
{label}
159+
<span className="flex items-center gap-1">
160+
{label}
161+
{url && (
162+
<LucideExternalLink
163+
size={14}
164+
className="opacity-60"
165+
/>
166+
)}
167+
</span>
148168
</a>
149169
);
150170
})}

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

Lines changed: 11 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;
@@ -52,6 +57,11 @@ if (neveDash.pro || neveDash.hasOldPro) {
5257
delete tabs['free-pro'];
5358
}
5459

60+
// Only show "Get Neve Pro" tab for users without valid licenses
61+
if (neveDash.pro && neveDash.license && 'valid' === neveDash.license.valid) {
62+
delete tabs['get-neve-pro'];
63+
}
64+
5565
if (neveDash.whiteLabel) {
5666
delete tabs.changelog;
5767
if (neveDash.whiteLabel.hideStarterSites) {
@@ -68,7 +78,7 @@ const getTabHash = () => {
6878

6979
hash = hash.substring(1);
7080

71-
if (!tabs[hash]?.render) {
81+
if (!tabs[hash]?.render && !tabs[hash]?.url) {
7282
return null;
7383
}
7484

0 commit comments

Comments
 (0)