diff --git a/apps/web/src/assets/plans-footer.svg b/apps/web/src/assets/plans-footer.svg new file mode 100644 index 000000000..6c71ab718 --- /dev/null +++ b/apps/web/src/assets/plans-footer.svg @@ -0,0 +1,128 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/web/src/common/theme.ts b/apps/web/src/common/theme.ts index 786d5eb03..d1f41abba 100644 --- a/apps/web/src/common/theme.ts +++ b/apps/web/src/common/theme.ts @@ -60,7 +60,7 @@ export const THEME_LIGHT: any = { paragraph: "#858585", background: "#F7F7F7", border: "#EFEFEF", - heading: "#4B4B4B", + heading: "#6F6F6F", icon: "#666666", separator: "#E8E8E8", placeholder: "#999999", diff --git a/apps/web/src/components/icons/index.tsx b/apps/web/src/components/icons/index.tsx index 4762430bc..efb8eca87 100644 --- a/apps/web/src/components/icons/index.tsx +++ b/apps/web/src/components/icons/index.tsx @@ -226,7 +226,6 @@ import { mdiHistory, mdiArrowCollapseRight, mdiNoteEditOutline, - mdiArrowUp, mdiInbox, mdiConsoleLine, mdiSpellcheck, @@ -260,6 +259,12 @@ import BoxArrowDownIcon from "@notesnook/icons/box-arrow-down.svg?react"; import DownloadIcon from "@notesnook/icons/download-simple.svg?react"; import FloppyDiskIcon from "@notesnook/icons/floppy-disk.svg?react"; import CheckSvg from "@notesnook/icons/check.svg?react"; +import ShieldCheckSvg from "@notesnook/icons/shield-check.svg?react"; +import CalendarBlankSvg from "@notesnook/icons/calendar-blank.svg?react"; +import ProhibitSvg from "@notesnook/icons/prohibit.svg?react"; +import HandCoinsSvg from "@notesnook/icons/hand-coins.svg?react"; +import ArrowUpSvg from "@notesnook/icons/arrow-up.svg?react"; +import LightningSvg from "@notesnook/icons/lightning.svg?react"; type MDIIconWrapperProps = { title?: string; @@ -625,7 +630,6 @@ export const SessionHistory = createIcon(mdiHistory); export const ColorRemove = createIcon(mdiCloseCircleOutline); export const ExpandSidebar = createIcon(mdiArrowCollapseRight); export const HamburgerMenu = createIcon(mdiMenu); -export const ArrowUp = createIcon(mdiArrowUp); export const Inbox = createIcon(mdiInbox); export const SpellCheck = createIcon(mdiSpellcheck); export const ClearTrash = createIcon(mdiDeleteSweepOutline); @@ -654,3 +658,9 @@ export const Copy = createSvgIcon(CopyIcon); export const BoxArrowDown = createSvgIcon(BoxArrowDownIcon); export const Download = createSvgIcon(DownloadIcon); export const FloppyDisk = createSvgIcon(FloppyDiskIcon); +export const ShieldCheck = createSvgIcon(ShieldCheckSvg); +export const CalendarBlank = createSvgIcon(CalendarBlankSvg); +export const Prohibit = createSvgIcon(ProhibitSvg); +export const HandCoins = createSvgIcon(HandCoinsSvg); +export const ArrowUp = createSvgIcon(ArrowUpSvg); +export const Lightning = createSvgIcon(LightningSvg); diff --git a/apps/web/src/dialogs/buy-dialog/plan-list.tsx b/apps/web/src/dialogs/buy-dialog/plan-list.tsx index 08dd968d7..b249fa003 100644 --- a/apps/web/src/dialogs/buy-dialog/plan-list.tsx +++ b/apps/web/src/dialogs/buy-dialog/plan-list.tsx @@ -25,7 +25,12 @@ import { FileDoc, Picture, CheckSvgIcon, - ArrowRightSvgIcon + ArrowRightSvgIcon, + ShieldCheck, + CaretDown, + CalendarBlank, + Prohibit, + HandCoins } from "../../components/icons"; import { Plan } from "./types"; import { PERIOD_METADATA, PLAN_METADATA, usePlans } from "./plans"; @@ -52,6 +57,8 @@ import Accordion from "../../components/accordion"; import { useStore as useUserStore } from "../../stores/user-store"; import { getCurrencySymbol } from "../../common/currencies"; import Star from "../../assets/star.svg"; +import { DialogManager } from "../../common/dialog-manager"; +import Dialog from "../../components/dialog"; const PLAN_CARD_FEATURES = [ getFeature("storage"), @@ -200,208 +207,274 @@ export function PlansList(props: PlansListProps) { ))} - - {isLoading ? ( - - ) : ( - plans - .filter( - (p) => - p.plan !== SubscriptionPlan.EDUCATION && - p.period === selectedPeriod - ) - .map((plan) => { - const metadata = PLAN_METADATA[plan.plan]; - const isRecommended = recommendedPlan === plan.plan; - return ( - + + + {isLoading ? ( + + ) : ( + plans + .filter( + (p) => + p.plan !== SubscriptionPlan.EDUCATION && + p.period === selectedPeriod + ) + .map((plan) => { + const metadata = PLAN_METADATA[plan.plan]; + const isRecommended = recommendedPlan === plan.plan; + return ( - - {metadata.title} - - {isRecommended && ( - - - Recommended - - - )} - - - {metadata.subtitle} - - - - {plan.recurring ? ( - - ) : ( - - )} - - - {PLAN_CARD_FEATURES.map((feature, index) => { - const caption = - feature.availability[planToAvailability(plan.plan)] - .caption; - return ( - + {metadata.title} + + {isRecommended && ( - - - - {feature.title} - - - + Recommended - {index < PLAN_CARD_FEATURES.length - 1 && ( - + + {metadata.subtitle} + + + + {plan.recurring ? ( + + ) : ( + + )} + + + {PLAN_CARD_FEATURES.map((feature, index) => { + const caption = + feature.availability[planToAvailability(plan.plan)] + .caption; + return ( + + - )} - - ); - })} + > + + + + {feature.title} + + + + + + + {index < PLAN_CARD_FEATURES.length - 1 && ( + + )} + + ); + })} + + {selectedPlan === plan.id ? ( + + + You are on this plan. + + ) : ( + + )} - {selectedPlan === plan.id ? ( - - - You are on this plan. - - ) : ( - - )} - - ); - }) - )} - - - {/* */} - {/* Cancel anytime. {PERIOD_METADATA[selectedPeriod].refundDays}-day */} - {/* money-back guarantee. */} - {/* */} - {/* */} + ); + }) + )} + + + + + + + + + Cancel anytime + + + 14-day money back guarantee + + + + + + ); } @@ -621,7 +694,7 @@ function RecurringPricing(props: PricingProps) { }} > {" "} - /Month + / Month )} @@ -1216,3 +1289,122 @@ function toMonthlyPrice(price: number, period: Period) { ? (price / (12 * 5)).toFixed(2) : (price / 12).toFixed(2); } + +const CancelInfoDialog = DialogManager.register(function CancelInfoDialog( + props +) { + return ( + props.onClose(false)} + width={550} + > + + + + + + + ); +}); + +type CancelInfoCardProps = { + icon: React.ComponentType<{ size: number; color?: string }>; + title: string; + description: string; +}; + +function CancelInfoCard(props: CancelInfoCardProps) { + const Icon = props.icon; + + return ( + + + + + + + + {props.title} + + + {props.description} + + + + + ); +} diff --git a/apps/web/src/views/plans.tsx b/apps/web/src/views/plans.tsx index fd017b6b7..063d59648 100644 --- a/apps/web/src/views/plans.tsx +++ b/apps/web/src/views/plans.tsx @@ -28,11 +28,13 @@ import { import { FlexScrollContainer } from "../components/scroll-container"; import { Flex, Text, Button, Image, Box } from "@notesnook/ui"; import { useStore as useUserStore } from "../stores/user-store"; +import { useStore as useThemeStore } from "../stores/theme-store"; import { useEffect } from "react"; import { getQueryParams, hardNavigate } from "../navigation"; import { isUserSubscribed } from "../hooks/use-is-user-premium"; -import { ChevronLeft } from "../components/icons"; +import { ArrowUp, ChevronLeft, Lightning } from "../components/icons"; import Star from "../assets/star.svg"; +import PlansFooter from "../assets/plans-footer.svg"; function Plans() { const user = useUserStore((store) => store.user); @@ -173,12 +175,236 @@ function Plans() {