diff --git a/apps/research/src/components/article/article-actions/EndedCall.tsx b/apps/research/src/components/article/article-actions/EndedCall.tsx index 0a0716ec..50058d2b 100644 --- a/apps/research/src/components/article/article-actions/EndedCall.tsx +++ b/apps/research/src/components/article/article-actions/EndedCall.tsx @@ -5,6 +5,7 @@ import { ProCheckoutCard } from '../article-payments'; interface EndedCallProps { checkout: () => void; + yearlyCheckout: () => void; isLoading?: boolean; isReport?: boolean; } @@ -14,6 +15,7 @@ const { useToken } = theme; const EndedCall: React.FC = ({ checkout, + yearlyCheckout, isLoading = false, isReport = false, }) => { @@ -29,15 +31,10 @@ const EndedCall: React.FC = ({ ? 'Renew your K33 Research Pro subscription to download the report' : 'Renew your K33 Research Pro subscription to keep reading the article'} - - Subscribe again and regain full access to all research. - void; + yearlyCheckout: () => void; isLoading?: boolean; isReport?: boolean; } @@ -14,6 +16,7 @@ const { useToken } = theme; const StartTrialCall: React.FC = ({ checkout, + yearlyCheckout, isLoading = false, isReport = false, }) => { @@ -22,23 +25,24 @@ const StartTrialCall: React.FC = ({ } = useToken(); return ( - +
{isReport ? 'Register to K33 Research Pro to download the report' : 'Register to K33 Research Pro to keep reading the article'} - Subscribe and get full access to all research. No credit card needed for free trial. - + */} = ({ No charge until the trial is complete. Cancel anytime. - +
); }; diff --git a/apps/research/src/components/article/article-actions/styles.module.scss b/apps/research/src/components/article/article-actions/styles.module.scss index 5d2d88df..bf9237ac 100644 --- a/apps/research/src/components/article/article-actions/styles.module.scss +++ b/apps/research/src/components/article/article-actions/styles.module.scss @@ -74,6 +74,13 @@ } } +.paymentCard { + width: 100% !important; + > div { + width: 100% !important; + } +} + .signupHeader { padding: 0px 8px; gap: 8px; diff --git a/apps/research/src/components/article/article-body/PrivateArticle.tsx b/apps/research/src/components/article/article-body/PrivateArticle.tsx index e74aaac6..060d71d0 100644 --- a/apps/research/src/components/article/article-body/PrivateArticle.tsx +++ b/apps/research/src/components/article/article-body/PrivateArticle.tsx @@ -40,6 +40,9 @@ const PrivateArticle: React.FC = ({ appStructure.payments.monthlyPriceId ); + const { doCheckOut: doYearlyCheckOut, isLoading: isYearlyLoading } = + useCustomerCheckout(appStructure.payments.annualPriceId); + const { productStatus, appState } = useProductInfo( appStructure.payments.productId ); @@ -77,6 +80,7 @@ const PrivateArticle: React.FC = ({ case 'ended': return ( = ({ default: return ( diff --git a/apps/research/src/components/article/article-payments/ProCheckoutCard.tsx b/apps/research/src/components/article/article-payments/ProCheckoutCard.tsx index f842a93c..32941a96 100644 --- a/apps/research/src/components/article/article-payments/ProCheckoutCard.tsx +++ b/apps/research/src/components/article/article-payments/ProCheckoutCard.tsx @@ -1,6 +1,16 @@ import * as React from 'react'; -import { Space, Divider, List, theme, Typography, Button } from 'antd'; +import { + Space, + Divider, + List, + theme, + Typography, + Button, + Switch, + Tag, +} from 'antd'; import { CheckCircleFilled } from '@ant-design/icons'; +import { usePlan } from '@/hooks'; const { Title, Text } = Typography; const { useToken } = theme; @@ -14,90 +24,195 @@ const features = [ interface ProCheckoutCardProps { handleCheckout: () => void; + handleYearlyCheckout: () => void; label: string; isFreeTrial?: boolean; isLoading?: boolean; + isEx?: boolean; } const ProCheckoutCard: React.FC = ({ handleCheckout, + handleYearlyCheckout, label, isFreeTrial = false, isLoading = false, + isEx = false, }) => { const { - token: { colorBgContainer, borderRadius, colorPrimary }, + token: { + colorBgContainer, + borderRadius, + colorPrimary, + colorTextQuaternary, + }, } = useToken(); + const { plan, setPlan } = usePlan(); return ( - - - - K33 Research Pro - - : null} + +
+ +
+ { + setPlan(isYear ? 'year' : 'monthly'); + }} + /> +
+
+ Save $100 + +
+
+
- - - $50 - - month - - {isFreeTrial && ( + : null} + > + + {plan === 'monthly' ? ( + <> + + $50 + + month + + ) : ( + <> + + $500 + + year + + )} + + {/* {isFreeTrial && ( After Free Trial - )} - + )} */} + + + K33 Research Pro + +
- - ( - + + - - ( + - {feat} - - - )} - /> - -
+ > + + + + {feat} + + + + )} + /> + + )} + + {plan === 'monthly' ? ( + + ) : ( + + )} + ); }; diff --git a/apps/research/src/components/platform/PricingTable.tsx b/apps/research/src/components/platform/PricingTable.tsx index ca35229b..d4a3e5b8 100644 --- a/apps/research/src/components/platform/PricingTable.tsx +++ b/apps/research/src/components/platform/PricingTable.tsx @@ -4,6 +4,7 @@ import { UserOutlined, UnlockTwoTone, EditOutlined } from '@ant-design/icons'; import { useCustomerCheckout, useCustomerDashboard, + usePlan, useProductInfo, } from '@/hooks'; import { appStructure } from '@/config'; @@ -16,8 +17,6 @@ setTwoToneColor('#777777'); const { useToken } = theme; const { Title, Text } = Typography; -type Plan = 'monthly' | 'year'; - const proPlanFeatures = [ 'The latest detailed insights into the markets', 'The most important weekly crypto news distilled and explained', @@ -28,8 +27,7 @@ const proPlanFeatures = [ ]; const PricingTable = () => { - const [plan, setPlan] = React.useState('monthly'); - + const { plan, setPlan } = usePlan(); const productId = appStructure.payments.productId; const monthlyPriceId = appStructure.payments.monthlyPriceId; const annualPriceId = appStructure.payments.annualPriceId; diff --git a/apps/research/src/hooks/index.ts b/apps/research/src/hooks/index.ts index 7563cfbb..4924dfc2 100644 --- a/apps/research/src/hooks/index.ts +++ b/apps/research/src/hooks/index.ts @@ -4,7 +4,7 @@ import { useCustomerMutation, useLazyGetProductInfoQuery, } from '@/services'; -import { ProductStatus } from '@/types'; +import { Plan, ProductStatus } from '@/types'; import { useAppState } from 'platform-js'; import * as React from 'react'; import { useHistoryTravel } from 'ahooks'; @@ -110,3 +110,8 @@ export const useBrowser = () => { return state; }; + +export const usePlan = (initialPlan: Plan = 'monthly') => { + const [plan, setPlan] = React.useState(initialPlan); + return { plan, setPlan }; +}; diff --git a/apps/research/src/types/ui.ts b/apps/research/src/types/ui.ts index 27b4186b..9502c469 100644 --- a/apps/research/src/types/ui.ts +++ b/apps/research/src/types/ui.ts @@ -26,3 +26,5 @@ export interface AppStructure { export type Navigations = Array; export type DividerConfig = boolean | { hideLast: boolean; hideFirst: boolean }; + +export type Plan = 'monthly' | 'year';