mirror of
https://github.com/dnote/dnote
synced 2026-03-16 15:35:52 +01:00
Update plan details
This commit is contained in:
parent
6dad47ffb1
commit
ac8ffdfa70
8 changed files with 81 additions and 89 deletions
|
|
@ -25,5 +25,4 @@
|
|||
list-style: none;
|
||||
margin-bottom: 0;
|
||||
padding-left: 0;
|
||||
padding-top: rem(12px);
|
||||
}
|
||||
|
|
@ -17,19 +17,28 @@
|
|||
*/
|
||||
|
||||
import React from 'react';
|
||||
import classnames from 'classnames';
|
||||
|
||||
import FeatureItem from './FeatureItem';
|
||||
|
||||
import styles from './FeatureList.module.scss';
|
||||
import styles from './FeatureList.scss';
|
||||
|
||||
function FeatureList({ features }) {
|
||||
interface Props {
|
||||
features: any;
|
||||
wrapperClassName?: string;
|
||||
}
|
||||
|
||||
const FeatureList: React.FunctionComponent<Props> = ({
|
||||
features,
|
||||
wrapperClassName
|
||||
}) => {
|
||||
return (
|
||||
<ul className={styles['feature-list']}>
|
||||
<ul className={classnames(styles['feature-list'], wrapperClassName)}>
|
||||
{features.map(feature => {
|
||||
return <FeatureItem key={feature.id} label={feature.label} />;
|
||||
})}
|
||||
</ul>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export default FeatureList;
|
||||
|
|
@ -18,23 +18,17 @@
|
|||
|
||||
import React from 'react';
|
||||
|
||||
import BookIcon from '../../Icons/Book';
|
||||
import Plan from './internal';
|
||||
|
||||
const selfHostedPerks = [
|
||||
{
|
||||
id: 'own-machine',
|
||||
icon: <BookIcon width={16} height={16} fill="#6e6e6e" className="" />,
|
||||
value: 'Ideal for occasional note taking'
|
||||
}
|
||||
];
|
||||
const desc =
|
||||
'Streamline your learnings into a personal knowledge base. You can access any item at any time.';
|
||||
|
||||
function Core({ wrapperClassName, ctaContent, bottomContent }) {
|
||||
return (
|
||||
<Plan
|
||||
name="Core"
|
||||
desc={desc}
|
||||
price="Free"
|
||||
perks={selfHostedPerks}
|
||||
wrapperClassName={wrapperClassName}
|
||||
ctaContent={ctaContent}
|
||||
bottomContent={bottomContent}
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@
|
|||
}
|
||||
}
|
||||
.header-body {
|
||||
margin-top: rem(20px);
|
||||
margin-top: rem(32px);
|
||||
}
|
||||
|
||||
.name {
|
||||
|
|
@ -65,20 +65,23 @@
|
|||
}
|
||||
|
||||
.price-wrapper {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
@include font-size('large');
|
||||
font-weight: 600;
|
||||
margin-top: rem(12px);
|
||||
}
|
||||
|
||||
.price {
|
||||
@include font-size('3x-large');
|
||||
display: inline-block;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.interval {
|
||||
@include font-size('large');
|
||||
text-transform: uppercase;
|
||||
font-weight: 600;
|
||||
margin-left: rem(4px);
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.desc {
|
||||
margin-top: rem(20px);
|
||||
@include font-size('regular');
|
||||
}
|
||||
|
||||
.cta-wrapper {
|
||||
|
|
@ -92,30 +95,6 @@
|
|||
padding-top: rem(12px);
|
||||
}
|
||||
|
||||
.perks {
|
||||
margin-top: rem(12px);
|
||||
}
|
||||
.perk-value {
|
||||
@include font-size('regular');
|
||||
margin-left: rem(8px);
|
||||
}
|
||||
.perk-item {
|
||||
display: flex;
|
||||
flex-shrink: 1;
|
||||
|
||||
&:not(:first-child) {
|
||||
margin-top: rem(4px);
|
||||
}
|
||||
}
|
||||
|
||||
.perk-icon {
|
||||
flex-shrink: 0;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: flex-start;
|
||||
margin-top: rem(4px);
|
||||
}
|
||||
|
||||
.feature-bold {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,29 +19,17 @@
|
|||
import React from 'react';
|
||||
|
||||
import Plan from './internal';
|
||||
import ServerIcon from '../../Icons/Server';
|
||||
import GlobeIcon from '../../Icons/Globe';
|
||||
|
||||
const proPerks = [
|
||||
{
|
||||
id: 'hosted',
|
||||
icon: <ServerIcon width={16} height={16} fill="#4d4d8b" />,
|
||||
value: 'Ideal for maximizing memory retention'
|
||||
},
|
||||
{
|
||||
id: 'support',
|
||||
icon: <GlobeIcon width={16} height={16} fill="#4d4d8b" />,
|
||||
value: 'Support the Dnote community and development'
|
||||
}
|
||||
];
|
||||
const desc =
|
||||
'Powerful features to maximize your memory retention and become the best learner you can be.';
|
||||
|
||||
function ProPlan({ wrapperClassName, ctaContent, bottomContent }) {
|
||||
return (
|
||||
<Plan
|
||||
name="Pro"
|
||||
price="$3"
|
||||
desc={desc}
|
||||
interval="month"
|
||||
perks={proPerks}
|
||||
wrapperClassName={wrapperClassName}
|
||||
ctaContent={ctaContent}
|
||||
bottomContent={bottomContent}
|
||||
|
|
|
|||
|
|
@ -29,21 +29,21 @@ interface Perk {
|
|||
|
||||
interface Props {
|
||||
name: string;
|
||||
desc: string;
|
||||
price: string;
|
||||
bottomContent: string;
|
||||
ctaContent: React.ReactElement;
|
||||
interval?: string;
|
||||
perks: Perk[];
|
||||
wrapperClassName: string;
|
||||
}
|
||||
|
||||
const Plan: React.FunctionComponent<Props> = ({
|
||||
name,
|
||||
desc,
|
||||
price,
|
||||
bottomContent,
|
||||
ctaContent,
|
||||
interval,
|
||||
perks,
|
||||
wrapperClassName
|
||||
}) => {
|
||||
return (
|
||||
|
|
@ -55,23 +55,14 @@ const Plan: React.FunctionComponent<Props> = ({
|
|||
>
|
||||
<h2 className={styles.name}>{name}</h2>
|
||||
|
||||
<ul className={classnames('list-unstyled', styles.perks)}>
|
||||
{perks.map(perk => {
|
||||
return (
|
||||
<li key={perk.id} className={styles['perk-item']}>
|
||||
<div className={styles['perk-icon']}>{perk.icon}</div>
|
||||
<div className={styles['perk-value']}>{perk.value}</div>
|
||||
</li>
|
||||
);
|
||||
})}
|
||||
</ul>
|
||||
<div className={styles['price-wrapper']}>
|
||||
<strong className={styles.price}>{price}</strong>{' '}
|
||||
{interval && <div className={styles.interval}> / {interval}</div>}
|
||||
</div>
|
||||
|
||||
<p className={styles.desc}>{desc}</p>
|
||||
|
||||
<div className={styles['header-body']}>
|
||||
<div className={styles['price-wrapper']}>
|
||||
<strong className={styles.price}>{price}</strong>
|
||||
{interval && <div className={styles.interval}>/ {interval}</div>}
|
||||
</div>
|
||||
|
||||
<div className={styles['cta-wrapper']}>{ctaContent}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -94,3 +94,15 @@
|
|||
.feature-bold {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.bottom {
|
||||
padding-top: rem(20px);
|
||||
}
|
||||
|
||||
.pro-prelude {
|
||||
padding: 0 rem(8px);
|
||||
}
|
||||
|
||||
.pro-feature-list {
|
||||
margin-top: rem(12px);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@
|
|||
* along with Dnote. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import React, { Fragment } from 'react';
|
||||
import Helmet from 'react-helmet';
|
||||
import { Link } from 'react-router-dom';
|
||||
import classnames from 'classnames';
|
||||
|
|
@ -31,11 +31,11 @@ import styles from './Subscription.scss';
|
|||
|
||||
const proFeatures = [
|
||||
{
|
||||
id: 'core',
|
||||
label: <div className={styles['feature-bold']}>Everything in core</div>
|
||||
id: 'num-books',
|
||||
label: <div>Unlimited books</div>
|
||||
},
|
||||
{
|
||||
id: 'host',
|
||||
id: 'spaced-rep',
|
||||
label: <div>Automated Spaced Repetition</div>
|
||||
},
|
||||
{
|
||||
|
|
@ -44,11 +44,19 @@ const proFeatures = [
|
|||
}
|
||||
];
|
||||
|
||||
const baseFeatures = [
|
||||
const coreFeatures = [
|
||||
{
|
||||
id: 'oss',
|
||||
label: <div>Open source</div>
|
||||
},
|
||||
{
|
||||
id: 'num-notes',
|
||||
label: <div>Unlimited notes</div>
|
||||
},
|
||||
{
|
||||
id: 'num-books',
|
||||
label: <div>5 total books</div>
|
||||
},
|
||||
{
|
||||
id: 'sync',
|
||||
label: <div>Multi-device sync</div>
|
||||
|
|
@ -100,7 +108,7 @@ const Subscription: React.FunctionComponent<Props> = () => {
|
|||
)}
|
||||
to={getSubscriptionCheckoutPath()}
|
||||
>
|
||||
Unlock
|
||||
Upgrade
|
||||
</Link>
|
||||
);
|
||||
}
|
||||
|
|
@ -117,9 +125,7 @@ const Subscription: React.FunctionComponent<Props> = () => {
|
|||
|
||||
<div className={styles.hero}>
|
||||
<div className="container">
|
||||
<h1 className={styles.heading}>
|
||||
Dnote has simple plans for everyone.
|
||||
</h1>
|
||||
<h1 className={styles.heading}>Choose your Dnote plan.</h1>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
@ -137,13 +143,27 @@ const Subscription: React.FunctionComponent<Props> = () => {
|
|||
See source code
|
||||
</a>
|
||||
}
|
||||
bottomContent={<FeatureList features={baseFeatures} />}
|
||||
bottomContent={
|
||||
<div className={styles.bottom}>
|
||||
<FeatureList features={coreFeatures} />
|
||||
</div>
|
||||
}
|
||||
/>
|
||||
|
||||
<ProPlan
|
||||
wrapperClassName={styles['pro-plan']}
|
||||
ctaContent={renderPlanCta()}
|
||||
bottomContent={<FeatureList features={proFeatures} />}
|
||||
bottomContent={
|
||||
<div className={styles.bottom}>
|
||||
<div className={styles['pro-prelude']}>
|
||||
Everything from the core plan, plus:
|
||||
</div>
|
||||
<FeatureList
|
||||
features={proFeatures}
|
||||
wrapperClassName={styles['pro-feature-list']}
|
||||
/>
|
||||
</div>
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue