feat: billing change
This commit is contained in:
parent
991d354c34
commit
0fe10976b0
|
|
@ -15,6 +15,7 @@ import { Button } from '@gitroom/react/form/button';
|
|||
import dayjs from 'dayjs';
|
||||
import Image from 'next/image';
|
||||
import { useToaster } from '@gitroom/react/toaster/toaster';
|
||||
import { useT } from '@gitroom/react/translation/get.transation.service.client';
|
||||
|
||||
export const EmbeddedBilling: FC<{
|
||||
stripe: Promise<Stripe>;
|
||||
|
|
@ -119,22 +120,23 @@ const FormWrapper = () => {
|
|||
|
||||
const StripeInputs = () => {
|
||||
const checkout = useCheckout();
|
||||
const t = useT();
|
||||
return (
|
||||
<>
|
||||
<div>
|
||||
<h4 className="mb-[8px] text-[24px]">
|
||||
{checkout.type === 'loading' ? '' : 'Billing Address'}
|
||||
{checkout.type === 'loading' ? '' : t('billing_billing_address', 'Billing Address')}
|
||||
</h4>
|
||||
<BillingAddressElement />
|
||||
</div>
|
||||
<div>
|
||||
<h4 className="mt-[20px] mb-[8px] text-[24px]">
|
||||
{checkout.type === 'loading' ? '' : 'Payment'}
|
||||
{checkout.type === 'loading' ? '' : t('billing_payment', 'Payment')}
|
||||
</h4>
|
||||
<PaymentElement id="payment-element" options={{ layout: 'tabs' }} />
|
||||
{checkout.type === 'loading' ? null : (
|
||||
<div className="mt-[24px] flex gap-[10px]">
|
||||
<div>Powered by Stripe</div>
|
||||
<div>{t('billing_powered_by_stripe', 'Powered by Stripe')}</div>
|
||||
<Image src="/stripe.svg" alt="Stripe" width={20} height={20} />
|
||||
</div>
|
||||
)}
|
||||
|
|
@ -145,6 +147,7 @@ const StripeInputs = () => {
|
|||
|
||||
const SubmitBar: FC<{ loading: boolean }> = ({ loading }) => {
|
||||
const checkout = useCheckout();
|
||||
const t = useT();
|
||||
if (checkout.type === 'loading' || checkout.type === 'error') {
|
||||
return null;
|
||||
}
|
||||
|
|
@ -154,15 +157,15 @@ const SubmitBar: FC<{ loading: boolean }> = ({ loading }) => {
|
|||
<div className="w-full h-full border-t border-newColColor bg-newBgColorInner px-[80px] flex gap-[32px] justify-end items-center font-[400] text-[14px] text-[#A3A3A3]">
|
||||
{checkout.checkout.recurring?.trial?.trialEnd ? (
|
||||
<div>
|
||||
Your 7-day trial is{' '}
|
||||
<span className="text-textColor font-[600]">100% free</span> ending{' '}
|
||||
{t('billing_your_7_day_trial_is', 'Your 7-day trial is')}{' '}
|
||||
<span className="text-textColor font-[600]">{t('billing_100_percent_free', '100% free')}</span> {t('billing_ending', 'ending')}{' '}
|
||||
<span className="text-textColor font-[600]">
|
||||
{dayjs(
|
||||
checkout.checkout.recurring?.trial?.trialEnd * 1000
|
||||
).format('MMMM D, YYYY')}{' '}
|
||||
—{' '}
|
||||
</span>
|
||||
<span className="text-textColor font-[600]">Cancel anytime.</span>
|
||||
<span className="text-textColor font-[600]">{t('billing_cancel_anytime_short', 'Cancel anytime.')}</span>
|
||||
</div>
|
||||
) : null}
|
||||
<div>
|
||||
|
|
@ -172,8 +175,8 @@ const SubmitBar: FC<{ loading: boolean }> = ({ loading }) => {
|
|||
loading={loading}
|
||||
>
|
||||
{checkout.checkout.recurring?.trial?.trialEnd
|
||||
? 'Pay $0 Today - Start your free trial!'
|
||||
: 'Pay Now'}
|
||||
? t('billing_pay_0_start_trial', 'Pay $0 Today - Start your free trial!')
|
||||
: t('billing_pay_now', 'Pay Now')}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ import {
|
|||
FAQComponent,
|
||||
FAQSection,
|
||||
} from '@gitroom/frontend/components/billing/faq.component';
|
||||
import { useT } from '@gitroom/react/translation/get.transation.service.client';
|
||||
|
||||
const ModeComponent = dynamic(
|
||||
() => import('@gitroom/frontend/components/layout/mode.component'),
|
||||
|
|
@ -45,6 +46,7 @@ export const FirstBillingComponent = () => {
|
|||
const [tier, setTier] = useState('STANDARD');
|
||||
const [period, setPeriod] = useState('MONTHLY');
|
||||
const fetch = useFetch();
|
||||
const t = useT();
|
||||
|
||||
useEffect(() => {
|
||||
setStripe(loadStripe(stripeClient));
|
||||
|
|
@ -102,9 +104,8 @@ export const FirstBillingComponent = () => {
|
|||
<div className="flex px-[80px] flex-1">
|
||||
<div className="flex-1 py-[40px] flex flex-col pe-[40px]">
|
||||
<div className="text-[36px] font-[600] leading-[110%] whitespace-pre-line">
|
||||
Join Over{' '}
|
||||
<span className="text-[#FC69FF]">18,000+ Entrepreneurs</span> who
|
||||
use{'\n'}Postiz To Grow Their Social Presence
|
||||
{t('billing_join_over', 'Join Over')}{' '}
|
||||
<span className="text-[#FC69FF]">{t('billing_entrepreneurs_count', '18,000+ Entrepreneurs')}</span> {t('billing_who_use', 'who use')}{'\n'}{t('billing_postiz_grow_social', 'Postiz To Grow Their Social Presence')}
|
||||
</div>
|
||||
|
||||
<div className="flex mt-[34px] mb-[10px]">
|
||||
|
|
@ -112,19 +113,19 @@ export const FirstBillingComponent = () => {
|
|||
<div>
|
||||
<CheckIconComponent />
|
||||
</div>
|
||||
<div>100% No-Risk Free Trial</div>
|
||||
<div>{t('billing_no_risk_trial', '100% No-Risk Free Trial')}</div>
|
||||
</div>
|
||||
<div className="flex-1 flex gap-[8px] justify-center">
|
||||
<div>
|
||||
<CheckIconComponent />
|
||||
</div>
|
||||
<div>Pay NOTHING for the first 7-days</div>
|
||||
<div>{t('billing_pay_nothing_7_days', 'Pay NOTHING for the first 7-days')}</div>
|
||||
</div>
|
||||
<div className="flex gap-[8px]">
|
||||
<div>
|
||||
<CheckIconComponent />
|
||||
</div>
|
||||
<div>Cancel anytime, hassle-free</div>
|
||||
<div>{t('billing_cancel_anytime', 'Cancel anytime, hassle-free')}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
@ -140,7 +141,7 @@ export const FirstBillingComponent = () => {
|
|||
<div className="flex flex-col ps-[40px] border-l border-newColColor py-[40px]">
|
||||
<div className="top-[20px] sticky">
|
||||
<div className="flex mb-[24px]">
|
||||
<div className="flex-1 text-[24px] font-[700]">Choose a Plan</div>
|
||||
<div className="flex-1 text-[24px] font-[700]">{t('billing_choose_plan', 'Choose a Plan')}</div>
|
||||
<div className="h-[44px] px-[6px] flex items-center justify-center gap-[12px] border border-newColColor rounded-[12px] select-none">
|
||||
<div
|
||||
className={clsx(
|
||||
|
|
@ -151,7 +152,7 @@ export const FirstBillingComponent = () => {
|
|||
)}
|
||||
onClick={() => setPeriod('MONTHLY')}
|
||||
>
|
||||
Monthly
|
||||
{t('billing_monthly', 'Monthly')}
|
||||
</div>
|
||||
<div
|
||||
className={clsx(
|
||||
|
|
@ -162,9 +163,9 @@ export const FirstBillingComponent = () => {
|
|||
)}
|
||||
onClick={() => setPeriod('YEARLY')}
|
||||
>
|
||||
<div>Yearly</div>
|
||||
<div>{t('billing_yearly', 'Yearly')}</div>
|
||||
<div className="bg-[#AA0FA4] text-[white] px-[8px] rounded-[4px]">
|
||||
20% Off
|
||||
{t('billing_20_percent_off', '20% Off')}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -194,7 +195,7 @@ export const FirstBillingComponent = () => {
|
|||
]
|
||||
}
|
||||
</span>{' '}
|
||||
/ month
|
||||
{t('billing_per_month', '/ month')}
|
||||
</div>
|
||||
</div>
|
||||
),
|
||||
|
|
@ -202,7 +203,7 @@ export const FirstBillingComponent = () => {
|
|||
)}
|
||||
</div>
|
||||
<div className="flex flex-col mt-[54px] gap-[24px]">
|
||||
<div className="text-[24px] font-[700]">Features</div>
|
||||
<div className="text-[24px] font-[700]">{t('billing_features', 'Features')}</div>
|
||||
<BillingFeatures tier={tier} />
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -212,43 +213,72 @@ export const FirstBillingComponent = () => {
|
|||
);
|
||||
};
|
||||
|
||||
type FeatureItem = {
|
||||
key: string;
|
||||
defaultValue: string;
|
||||
prefix?: string | number;
|
||||
};
|
||||
|
||||
export const BillingFeatures: FC<{ tier: string }> = ({ tier }) => {
|
||||
const render = useMemo(() => {
|
||||
const t = useT();
|
||||
const features = useMemo(() => {
|
||||
const currentPricing = pricing[tier];
|
||||
const channelsOr = currentPricing.channel;
|
||||
const list = [];
|
||||
list.push(`${channelsOr} ${channelsOr === 1 ? 'channel' : 'channels'}`);
|
||||
list.push(
|
||||
`${
|
||||
currentPricing.posts_per_month > 10000
|
||||
? 'Unlimited'
|
||||
: currentPricing.posts_per_month
|
||||
} posts per month`
|
||||
);
|
||||
const list: FeatureItem[] = [];
|
||||
|
||||
list.push({
|
||||
key: channelsOr === 1 ? 'billing_channel' : 'billing_channels',
|
||||
defaultValue: channelsOr === 1 ? 'channel' : 'channels',
|
||||
prefix: channelsOr,
|
||||
});
|
||||
|
||||
list.push({
|
||||
key: 'billing_posts_per_month',
|
||||
defaultValue: 'posts per month',
|
||||
prefix: currentPricing.posts_per_month > 10000 ? 'unlimited' : currentPricing.posts_per_month,
|
||||
});
|
||||
|
||||
if (currentPricing.team_members) {
|
||||
list.push(`Unlimited team members`);
|
||||
list.push({ key: 'billing_unlimited_team_members', defaultValue: 'Unlimited team members' });
|
||||
}
|
||||
if (currentPricing?.ai) {
|
||||
list.push(`AI auto-complete`);
|
||||
list.push(`AI copilots`);
|
||||
list.push(`AI Autocomplete`);
|
||||
list.push({ key: 'billing_ai_auto_complete', defaultValue: 'AI auto-complete' });
|
||||
list.push({ key: 'billing_ai_copilots', defaultValue: 'AI copilots' });
|
||||
list.push({ key: 'billing_ai_autocomplete', defaultValue: 'AI Autocomplete' });
|
||||
}
|
||||
list.push(`Advanced Picture Editor`);
|
||||
list.push({ key: 'billing_advanced_picture_editor', defaultValue: 'Advanced Picture Editor' });
|
||||
if (currentPricing?.image_generator) {
|
||||
list.push(
|
||||
`${currentPricing?.image_generation_count} AI Images per month`
|
||||
);
|
||||
list.push({
|
||||
key: 'billing_ai_images_per_month',
|
||||
defaultValue: 'AI Images per month',
|
||||
prefix: currentPricing?.image_generation_count,
|
||||
});
|
||||
}
|
||||
if (currentPricing?.generate_videos) {
|
||||
list.push(`${currentPricing?.generate_videos} AI Videos per month`);
|
||||
list.push({
|
||||
key: 'billing_ai_videos_per_month',
|
||||
defaultValue: 'AI Videos per month',
|
||||
prefix: currentPricing?.generate_videos,
|
||||
});
|
||||
}
|
||||
return list;
|
||||
}, [tier]);
|
||||
|
||||
const renderFeature = (feature: FeatureItem) => {
|
||||
const translatedText = t(feature.key, feature.defaultValue);
|
||||
if (feature.prefix === 'unlimited') {
|
||||
return `${t('billing_unlimited', 'Unlimited')} ${translatedText}`;
|
||||
}
|
||||
if (feature.prefix !== undefined) {
|
||||
return `${feature.prefix} ${translatedText}`;
|
||||
}
|
||||
return translatedText;
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="grid grid-cols-2 gap-y-[8px] gap-x-[32px]">
|
||||
{render.map((p) => (
|
||||
<div key={p} className="flex items-center gap-[8px]">
|
||||
{features.map((feature) => (
|
||||
<div key={feature.key} className="flex items-center gap-[8px]">
|
||||
<div>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
|
|
@ -263,7 +293,7 @@ export const BillingFeatures: FC<{ tier: string }> = ({ tier }) => {
|
|||
/>
|
||||
</svg>
|
||||
</div>
|
||||
<div>{p}</div>
|
||||
<div>{renderFeature(feature)}</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
|
|
|||
36
i18n.lock
36
i18n.lock
|
|
@ -15,7 +15,7 @@ checksums:
|
|||
send_test: 6252eb4669859b7f7db4cdbc227580e1
|
||||
select_role: 406451b1c9a26f1484164b8b71c1bd7e
|
||||
video_made_with_ai: c37747aaf8107d339d6238a0463f7096
|
||||
please_add_at_least: 90d3c0237b56e57c7a58d5decf6e9d3c
|
||||
please_add_at_least: 776aa47593c7961b69172b49f49dc304
|
||||
send_invitation_via_email: 9275e0b85147a931421b3bf6c3083cb4
|
||||
global_settings: ba55734261d6bc26e792fda32de3e7ec
|
||||
copy_id: 831147124db35832872f8470c577e440
|
||||
|
|
@ -94,6 +94,7 @@ checksums:
|
|||
you_can_also_drag_drop_pictures: 40cc62ceac0cde30c1218c48796eb202
|
||||
you_don_t_have_any_assets_yet: ec8d0dc0a7ebf4c2437afb95f0e4cdb5
|
||||
click_the_button_below_to_upload_one: e2fb4d45f48de2277a0d71b9dd2c08ee
|
||||
click_the_button_below_to_upload_other: 8999406064d8cb19c648097db01f1b1a
|
||||
add_selected_media: 0f1bf2187f3df8d3b90df1895c6e530b
|
||||
insert_media: 15267304e6c6b2c19fc7d1941b2a6a11
|
||||
design_media: fee3bbf1846d9e5f4a1af783b9e3fc90
|
||||
|
|
@ -506,3 +507,36 @@ checksums:
|
|||
label_who_can_reply_to_this_post: 4d8913296a1fc3f197cb0aead34af73d
|
||||
delete_integration: ccc879ccfcf7f85bcfe09f2bc3fa0dd3
|
||||
start_writing_your_post: 471efc4f2a7e2cf02a065a2de34e7213
|
||||
billing_join_over: 6e1c237241ba00ddbb07fd603344c5c3
|
||||
billing_entrepreneurs_count: 05164f2ca2e8e20de3f63977c07d39fe
|
||||
billing_who_use: 63bdc59ef443e193eca87889e83ea07a
|
||||
billing_postiz_grow_social: 3cf5ab166df9cb65e17b9a039ccbbbad
|
||||
billing_no_risk_trial: 6e5c60d9ddf3affa8ba8870272f9f9ab
|
||||
billing_pay_nothing_7_days: 2db15615cad39981069b65e6a0852b18
|
||||
billing_cancel_anytime: f69ae39eec3fb9eb6114481d67c8481e
|
||||
billing_choose_plan: 6eacca8177c43945435ac9c97a1e9734
|
||||
billing_monthly: 818f1192e32bb855597f930d3e78806e
|
||||
billing_yearly: 87f43e016c19cb25860f456549a2f431
|
||||
billing_20_percent_off: 2d643feeaf30cafb2dd864b90f5c014b
|
||||
billing_features: 341ff316a339b106a178f0b8d362951b
|
||||
billing_channel: 7f661d461a99f05a2d57195fc3d262c3
|
||||
billing_channels: f6cd2d03caa496e649e95df2d6610879
|
||||
billing_unlimited: e1a92523172cd1bdde5550689840e42d
|
||||
billing_posts_per_month: ca72453dbacbffceddb12b41e3d1f559
|
||||
billing_unlimited_team_members: 254b7e4f144033e09d0127f50cd0422e
|
||||
billing_ai_auto_complete: 91eab83ad474698d10e25fbde8b8ffce
|
||||
billing_ai_copilots: 00054c5d5fe79ed4bb7e6decaa9f6608
|
||||
billing_ai_autocomplete: 25c332479a2cfa33c6f8a1548b58199f
|
||||
billing_advanced_picture_editor: 329a6c2e8b2685f81609859a4de07b0f
|
||||
billing_ai_images_per_month: 5073aa90b32654abe6200d426a97f03e
|
||||
billing_ai_videos_per_month: c786199d8dc9bded54fab8f92c350b19
|
||||
billing_billing_address: 48980a775bfc7292b0c4f9b74b4d352e
|
||||
billing_payment: 95142d3fd8b6a6f551aba771842e9c11
|
||||
billing_powered_by_stripe: 4b1f500613fe28f3cc17cb003ed0caf6
|
||||
billing_your_7_day_trial_is: 4b59fb559f5fd520668974e909e3479c
|
||||
billing_100_percent_free: 6616fd6ee152264c06dd2537f6347e66
|
||||
billing_ending: f66133a14aa7d86ea2453df97de12cd5
|
||||
billing_cancel_anytime_short: 5b1b4a998fd56b18e4153dd83c84022c
|
||||
billing_pay_0_start_trial: 28e72154e6cce7541e707b35f3a67309
|
||||
billing_pay_now: 50cb14454e1b2df4a2f83bf1ac799819
|
||||
billing_per_month: 6293d01c3d13f6938d47285122bd1a48
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
|
@ -502,5 +502,38 @@
|
|||
"separate_post": "Separate post to multiple posts",
|
||||
"label_who_can_reply_to_this_post": "Who can reply to this post?",
|
||||
"delete_integration": "Delete Integration",
|
||||
"start_writing_your_post": "Start writing your post for a preview"
|
||||
"start_writing_your_post": "Start writing your post for a preview",
|
||||
"billing_join_over": "Join Over",
|
||||
"billing_entrepreneurs_count": "18,000+ Entrepreneurs",
|
||||
"billing_who_use": "who use",
|
||||
"billing_postiz_grow_social": "Postiz To Grow Their Social Presence",
|
||||
"billing_no_risk_trial": "100% No-Risk Free Trial",
|
||||
"billing_pay_nothing_7_days": "Pay NOTHING for the first 7-days",
|
||||
"billing_cancel_anytime": "Cancel anytime, hassle-free",
|
||||
"billing_choose_plan": "Choose a Plan",
|
||||
"billing_monthly": "Monthly",
|
||||
"billing_yearly": "Yearly",
|
||||
"billing_20_percent_off": "20% Off",
|
||||
"billing_features": "Features",
|
||||
"billing_channel": "channel",
|
||||
"billing_channels": "channels",
|
||||
"billing_unlimited": "Unlimited",
|
||||
"billing_posts_per_month": "posts per month",
|
||||
"billing_unlimited_team_members": "Unlimited team members",
|
||||
"billing_ai_auto_complete": "AI auto-complete",
|
||||
"billing_ai_copilots": "AI copilots",
|
||||
"billing_ai_autocomplete": "AI Autocomplete",
|
||||
"billing_advanced_picture_editor": "Advanced Picture Editor",
|
||||
"billing_ai_images_per_month": "AI Images per month",
|
||||
"billing_ai_videos_per_month": "AI Videos per month",
|
||||
"billing_billing_address": "Billing Address",
|
||||
"billing_payment": "Payment",
|
||||
"billing_powered_by_stripe": "Powered by Stripe",
|
||||
"billing_your_7_day_trial_is": "Your 7-day trial is",
|
||||
"billing_100_percent_free": "100% free",
|
||||
"billing_ending": "ending",
|
||||
"billing_cancel_anytime_short": "Cancel anytime.",
|
||||
"billing_pay_0_start_trial": "Pay $0 Today - Start your free trial!",
|
||||
"billing_pay_now": "Pay Now",
|
||||
"billing_per_month": "/ month"
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue