Skip to content

Commit 47e7c84

Browse files
committed
feat: better biling
1 parent ba4ad5d commit 47e7c84

File tree

18 files changed

+518
-60
lines changed

18 files changed

+518
-60
lines changed

apps/frontend/src/components/billing/embedded.billing.tsx

Lines changed: 133 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -120,16 +120,20 @@ const FormWrapper: FC<{ showCoupon?: boolean; autoApplyCoupon?: string }> = ({
120120

121121
return (
122122
<form onSubmit={handleSubmit} className="flex flex-col flex-1">
123-
<StripeInputs showCoupon={showCoupon} autoApplyCoupon={autoApplyCoupon} />
124-
<SubmitBar loading={loading} />
123+
<StripeInputs
124+
showCoupon={showCoupon}
125+
autoApplyCoupon={autoApplyCoupon}
126+
loading={loading}
127+
/>
125128
</form>
126129
);
127130
};
128131

129-
const StripeInputs: FC<{ showCoupon: boolean; autoApplyCoupon?: string }> = ({
130-
showCoupon,
131-
autoApplyCoupon,
132-
}) => {
132+
const StripeInputs: FC<{
133+
showCoupon: boolean;
134+
autoApplyCoupon?: string;
135+
loading: boolean;
136+
}> = ({ showCoupon, autoApplyCoupon, loading }) => {
133137
const checkout = useCheckout();
134138
const t = useT();
135139
const [ready, setReady] = useState(false);
@@ -147,8 +151,16 @@ const StripeInputs: FC<{ showCoupon: boolean; autoApplyCoupon?: string }> = ({
147151
<h4 className="mt-[40px] mb-[32px] text-[24px] font-[700]">
148152
{checkout.type === 'loading' ? '' : t('billing_payment', 'Payment')}
149153
</h4>
150-
<PaymentElement id="payment-element" options={{ layout: 'tabs' }} onReady={() => setReady(true)} />
151-
{showCoupon && ready && <CouponInput autoApplyCoupon={autoApplyCoupon} />}
154+
<PaymentElement
155+
id="payment-element"
156+
options={{ layout: 'tabs' }}
157+
onReady={() => setReady(true)}
158+
/>
159+
{ready && <PriceBreakdown />}
160+
{showCoupon && ready && (
161+
<CouponInput autoApplyCoupon={autoApplyCoupon} />
162+
)}
163+
{ready && <SubmitBar loading={loading} />}
152164
{checkout.type === 'loading' ? null : (
153165
<div className="mt-[24px] text-[16px] font-[600] flex gap-[4px] items-center">
154166
<div>
@@ -176,6 +188,119 @@ const StripeInputs: FC<{ showCoupon: boolean; autoApplyCoupon?: string }> = ({
176188
);
177189
};
178190

191+
const PriceBreakdown: FC = () => {
192+
const checkoutState = useCheckout();
193+
const t = useT();
194+
195+
if (checkoutState.type !== 'success') {
196+
return null;
197+
}
198+
199+
const { checkout } = checkoutState;
200+
const lineItem = checkout?.lineItems?.[0];
201+
const recurring = checkout?.recurring;
202+
const discountAmounts = checkout?.discountAmounts;
203+
const hasDiscount = discountAmounts && discountAmounts.length > 0;
204+
205+
// Get values
206+
const planName = lineItem?.name || t('billing_subscription', 'Subscription');
207+
const unitAmount = lineItem?.unitAmount?.amount || '$0.00';
208+
const discountDisplay = hasDiscount ? discountAmounts[0] : null;
209+
const dueToday = checkout?.total?.total?.amount || '$0.00';
210+
const nextBillingTotal = recurring?.dueNext?.total?.amount;
211+
const nextBillingDate = recurring?.trial?.trialEnd
212+
? dayjs(recurring.trial.trialEnd * 1000).format('MMMM D, YYYY')
213+
: null;
214+
const billingInterval =
215+
recurring?.interval === 'month'
216+
? t('billing_monthly', 'Monthly')
217+
: t('billing_yearly', 'Yearly');
218+
219+
return (
220+
<div className="mt-[40px]">
221+
<h4 className="mb-[16px] text-[24px] font-[700]">
222+
{t('billing_order_summary', 'Order Summary')}
223+
</h4>
224+
<div className="rounded-[12px] border border-newColColor p-[20px] flex flex-col gap-[12px]">
225+
{/* Plan */}
226+
<div className="flex justify-between items-center">
227+
<div className="flex flex-col">
228+
<span className="font-[600] text-textColor">{planName}</span>
229+
<span className="text-[13px] text-textColor/60">
230+
{billingInterval}
231+
</span>
232+
</div>
233+
<span className="font-[500] text-textColor">{unitAmount}</span>
234+
</div>
235+
236+
{/* Discount */}
237+
{discountDisplay && (
238+
<div className="flex justify-between items-center font-[600]">
239+
<div className="flex items-center gap-[6px]">
240+
<svg
241+
xmlns="http://www.w3.org/2000/svg"
242+
width="16"
243+
height="16"
244+
viewBox="0 0 24 24"
245+
fill="none"
246+
stroke="currentColor"
247+
strokeWidth="2"
248+
strokeLinecap="round"
249+
strokeLinejoin="round"
250+
>
251+
<path d="M20.59 13.41l-7.17 7.17a2 2 0 0 1-2.83 0L2 12V2h10l8.59 8.59a2 2 0 0 1 0 2.82z" />
252+
<line x1="7" y1="7" x2="7.01" y2="7" />
253+
</svg>
254+
<span className="font-[500]">
255+
{discountDisplay.displayName || discountDisplay.promotionCode}
256+
{discountDisplay.percentOff &&
257+
` (${discountDisplay.percentOff}% off)`}
258+
</span>
259+
</div>
260+
<span className="font-[500]">
261+
{discountDisplay.amount !== '$0.00'
262+
? `-${discountDisplay.amount}`
263+
: t('billing_applied', 'Applied')}
264+
</span>
265+
</div>
266+
)}
267+
268+
{/* Divider */}
269+
<div className="border-t border-newColColor my-[4px]" />
270+
271+
{/* Due today */}
272+
<div className="flex justify-between items-center">
273+
<span className="font-[600] text-textColor">
274+
{t('billing_due_today', 'Due today')}
275+
</span>
276+
<span className="font-[700] text-[18px] text-textColor">
277+
{dueToday}
278+
</span>
279+
</div>
280+
281+
{/* Next billing info */}
282+
{nextBillingTotal && nextBillingDate && (
283+
<div className="flex justify-between items-center text-[13px] text-textColor/60">
284+
<span>
285+
{t('billing_then', 'Then')} {nextBillingTotal}{' '}
286+
{t('billing_on', 'on')} {nextBillingDate}
287+
</span>
288+
</div>
289+
)}
290+
291+
<div className="text-[12px]">
292+
<strong>
293+
{t(
294+
'billing_cancel_notice',
295+
'Cancel anytime from settings without talking to a person and never be charged.'
296+
)}
297+
</strong>
298+
</div>
299+
</div>
300+
</div>
301+
);
302+
};
303+
179304
const AppliedCouponDisplay: FC<{
180305
appliedCode: string;
181306
checkout: any;

apps/frontend/src/components/billing/faq.component.tsx

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ const useFaqList = () => {
1919
),
2020
description: t(
2121
'faq_to_confirm_credit_card_information_postiz_will_hold',
22-
'To confirm credit card information Postiz will hold $2 and release it immediately'
22+
'To confirm credit card information Postiz will hold $2 and release it immediately, you can cancel your subscription anytime from settings without talking to a person'
2323
),
2424
},
2525
]
@@ -72,9 +72,7 @@ export const FAQSection: FC<{
7272
className="bg-sixth p-[24px] border border-tableBorder rounded-[8px] flex flex-col"
7373
onClick={changeShow}
7474
>
75-
<div
76-
className={`text-[20px] cursor-pointer flex justify-center`}
77-
>
75+
<div className={`text-[20px] cursor-pointer flex justify-center`}>
7876
<div className="flex-1">{title}</div>
7977
<div className="flex items-center justify-center w-[32px]">
8078
{!show ? (

i18n.lock

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -458,7 +458,7 @@ checksums:
458458
upload_content_to_tiktok_without_posting: 6c3943e4d796b720933b90d250bd611c
459459
choose_upload_without_posting_description: 223c59be260eeaafe420791b76e2523c
460460
faq_am_i_going_to_be_charged_by_postiz: f4aad17d35bcaf45427216a432f23af3
461-
faq_to_confirm_credit_card_information_postiz_will_hold: 5087b85985bbb6f46ea869d4796fb891
461+
faq_to_confirm_credit_card_information_postiz_will_hold: ec475e644e3b5db2550c5bc06320b1cd
462462
faq_can_i_trust_postiz_gitroom: 9ee3c694bc392c339333047484d36003
463463
faq_postiz_gitroom_is_proudly_open_source: 17658906aec47f1557f84c71efadee03
464464
faq_what_are_channels: 22bc7aebd017e487d9a5ac8946a2a08d
@@ -469,7 +469,6 @@ checksums:
469469
faq_we_automate_chatgpt_to_help_you_write: e19d331417449c114f03b2b6ad862f93
470470
enter_email: 57d0675d7ff70e463dd0389652f35b20
471471
are_you_sure: 6d5cd13628a7887711fd0c29f1123652
472-
yes_delete_it: e028575f88f6dc8e25f7a02fde480df9
473472
no_cancel: 9ebf9f7c2d2591e603861ef4c0c7c559
474473
are_you_sure_you_want_to_delete: f41210d5066ca7ae76a171fbe4b085a3
475474
are_you_sure_you_want_to_delete_the_image: 5fc0522337ba24f14a15d5f35b19e1d3
@@ -509,7 +508,7 @@ checksums:
509508
delete_integration: ccc879ccfcf7f85bcfe09f2bc3fa0dd3
510509
start_writing_your_post: 471efc4f2a7e2cf02a065a2de34e7213
511510
billing_join_over: 6e1c237241ba00ddbb07fd603344c5c3
512-
billing_entrepreneurs_count: 05164f2ca2e8e20de3f63977c07d39fe
511+
billing_entrepreneurs_count: 1e90206cb8ea01d0a1084d3af1a4cbed
513512
billing_who_use: 63bdc59ef443e193eca87889e83ea07a
514513
billing_postiz_grow_social: 3cf5ab166df9cb65e17b9a039ccbbbad
515514
billing_no_risk_trial: 6e5c60d9ddf3affa8ba8870272f9f9ab
@@ -541,6 +540,27 @@ checksums:
541540
billing_pay_0_start_trial: 28e72154e6cce7541e707b35f3a67309
542541
billing_pay_now: 50cb14454e1b2df4a2f83bf1ac799819
543542
billing_per_month: 6293d01c3d13f6938d47285122bd1a48
543+
billing_per_year: 7d37200832af52329220e7431cf1a0e2
544+
billing_order_summary: 77352aa7eeded06ca26b3fe72e4bcfda
545+
billing_applied: a79bcd1e53b38db7b03b506ff2e05904
546+
billing_due_today: a14cb9dd0003485894d328bb803c80e5
547+
billing_then: 5e941fb7dd51a18651fcfb865edd5ba6
548+
billing_on: 221bc27170a3baba6741482c0b28baa1
549+
billing_discount_applied: 66ca13dec03ff95bf7461fb5e9e3a3c5
550+
billing_remove: dba2fe5fe9f83f8078c687f28cba4b52
551+
billing_coupon_expires: 91d8dcbb9a0ec894dd769f99528f0768
552+
billing_invalid_coupon: 07fdf7218d84836632d60d2819089587
553+
billing_coupon_applied: 53d5f95a8b47b6771ac06fb48578367a
554+
billing_coupon_removed: ebef384172a4632e325ddfa5de48d370
555+
billing_error_removing_coupon: aedc7fb1697d846a707828e02059cd61
556+
billing_have_discount_coupon: 7f3e2b5a65a2901492ea3d185003dc80
557+
billing_discount_coupon: 417a5576094621af534c5b3ba1898f1b
558+
billing_cancel: 2e2a849c2223911717de8caa2c71bade
559+
billing_enter_coupon_code: 4abd909f35156b0964bd5993f14d7b78
560+
billing_applying: 0a321e775629314323ab227340e1a919
561+
billing_apply: 0f03e8e3752eb120bf8ea0b8f8f5d244
562+
billing_subscription: ba9f3675e18987d067d48533c8897343
563+
billing_cancel_notice: bc2edd49b3c0a51f8e11bb93f56c5571
544564
select_channels: 3aab82dc90ccafe55059c32c5a33c222
545565
start_a_new_chat: 65b9067206fa4e4929d48ce242d879a6
546566
your_assistant: bd6422d1c2a2ba461e1da169b082bf7b
@@ -656,6 +676,7 @@ checksums:
656676
are_you_sure_go_back_to_global_mode: e7e0913ac6a8bdecd5a9349ad84d2f3c
657677
yes_go_back_to_global_mode: 50484cd2f72d76bd6a02d5ac956ba466
658678
are_you_sure_delete_this_post: 25e67cb71ee64bf67af09ee20257655f
679+
yes_delete_it: e028575f88f6dc8e25f7a02fde480df9
659680
cant_edit_networks_when_creating_set: 10c389a15c85e82b69f3202bcd8fc527
660681
click_to_exit_global_editing: fec20b458bec4dcabf3efe65d1e5777b
661682
edit_content: 13b729cc6459ecdc3ea84d476c6dcddd

libraries/react-shared-libraries/src/translation/locales/ar/translation.json

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -454,7 +454,7 @@
454454
"upload_content_to_tiktok_without_posting": "ارفع المحتوى إلى تيك توك دون نشره",
455455
"choose_upload_without_posting_description": "اختر الرفع دون النشر إذا كنت ترغب في مراجعة وتحرير المحتوى الخاص بك داخل تطبيق تيك توك قبل النشر. هذا يمنحك إمكانية الوصول إلى أدوات التحرير المدمجة في تيك توك ويسمح لك بإجراء التعديلات النهائية قبل النشر.",
456456
"faq_am_i_going_to_be_charged_by_postiz": "هل سيتم تحميلي رسوم من قبل Postiz؟",
457-
"faq_to_confirm_credit_card_information_postiz_will_hold": "لتأكيد معلومات بطاقة الائتمان، سيقوم Postiz بحجز مبلغ 2 دولار وإطلاقه فوراً",
457+
"faq_to_confirm_credit_card_information_postiz_will_hold": "لتأكيد معلومات بطاقة الائتمان، سيحتجز Postiz مبلغ 2 دولار ويعيده فوراً، يمكنك إلغاء اشتراكك في أي وقت من الإعدادات دون الحاجة للتحدث مع أي شخص.",
458458
"faq_can_i_trust_postiz_gitroom": "هل يمكنني الوثوق بـ Postiz؟",
459459
"faq_postiz_gitroom_is_proudly_open_source": "Postiz مفتوح المصدر بكل فخر! نحن نؤمن بثقافة أخلاقية وشفافة، مما يعني أن Postiz سيبقى للأبد. يمكنك الاطلاع على الكود بالكامل أو استخدامه في مشاريعك الشخصية. لعرض مستودع المصدر المفتوح، <a href=\"https://github.com/gitroomhq/postiz-app\" target=\"_blank\" style=\"text-decoration: underline;\">اضغط هنا</a>.",
460460
"faq_what_are_channels": "ما هي القنوات؟",
@@ -465,7 +465,6 @@
465465
"faq_we_automate_chatgpt_to_help_you_write": "نحن نستخدم ChatGPT لمساعدتك في كتابة المنشورات والمقالات الاجتماعية.",
466466
"enter_email": "أدخل البريد الإلكتروني",
467467
"are_you_sure": "هل أنت متأكد؟",
468-
"yes_delete_it": "نعم، احذفه!",
469468
"no_cancel": "لا، إلغاء!",
470469
"are_you_sure_you_want_to_delete": "هل أنت متأكد أنك تريد حذف {{name}}؟",
471470
"are_you_sure_you_want_to_delete_the_image": "هل أنت متأكد أنك تريد حذف الصورة؟",
@@ -505,7 +504,7 @@
505504
"delete_integration": "حذف التكامل",
506505
"start_writing_your_post": "ابدأ بكتابة منشورك لمعاينة",
507506
"billing_join_over": "انضم إلى أكثر من",
508-
"billing_entrepreneurs_count": "18,000+ رائد أعمال",
507+
"billing_entrepreneurs_count": "أكثر من 20,000 رائد أعمال",
509508
"billing_who_use": "الذين يستخدمون",
510509
"billing_postiz_grow_social": "Postiz لتنمية حضورهم على وسائل التواصل الاجتماعي",
511510
"billing_no_risk_trial": "تجربة مجانية بدون أي مخاطرة 100%",
@@ -537,6 +536,27 @@
537536
"billing_pay_0_start_trial": "ادفع 0 دولار اليوم - ابدأ تجربتك المجانية!",
538537
"billing_pay_now": "ادفع الآن",
539538
"billing_per_month": "/ شهريًا",
539+
"billing_per_year": "/ سنوياً",
540+
"billing_order_summary": "ملخص الطلب",
541+
"billing_applied": "تم التطبيق",
542+
"billing_due_today": "المستحق اليوم",
543+
"billing_then": "ثم",
544+
"billing_on": "في",
545+
"billing_discount_applied": "تم تطبيق الخصم",
546+
"billing_remove": "إزالة",
547+
"billing_coupon_expires": "تنتهي صلاحية القسيمة في",
548+
"billing_invalid_coupon": "رمز القسيمة غير صالح",
549+
"billing_coupon_applied": "تم تطبيق القسيمة بنجاح!",
550+
"billing_coupon_removed": "تمت إزالة القسيمة",
551+
"billing_error_removing_coupon": "حدث خطأ أثناء إزالة القسيمة",
552+
"billing_have_discount_coupon": "هل لديك قسيمة خصم؟",
553+
"billing_discount_coupon": "قسيمة خصم",
554+
"billing_cancel": "إلغاء",
555+
"billing_enter_coupon_code": "أدخل رمز القسيمة",
556+
"billing_applying": "جارٍ التطبيق...",
557+
"billing_apply": "تطبيق",
558+
"billing_subscription": "الاشتراك",
559+
"billing_cancel_notice": "يمكنك الإلغاء في أي وقت من الإعدادات دون الحاجة للتحدث مع أي شخص ولن يتم خصم أي مبلغ منك.",
540560
"select_channels": "اختر القنوات",
541561
"start_a_new_chat": "ابدأ محادثة جديدة",
542562
"your_assistant": "مساعدك",
@@ -652,6 +672,7 @@
652672
"are_you_sure_go_back_to_global_mode": "هذا الإجراء لا يمكن التراجع عنه. هل أنت متأكد أنك تريد العودة إلى الوضع العام؟",
653673
"yes_go_back_to_global_mode": "نعم، العودة إلى الوضع العام",
654674
"are_you_sure_delete_this_post": "هل أنت متأكد أنك تريد حذف هذا المنشور؟",
675+
"yes_delete_it": "نعم، احذفه!",
655676
"cant_edit_networks_when_creating_set": "لا يمكنك تعديل الشبكات أثناء إنشاء مجموعة",
656677
"click_to_exit_global_editing": "انقر على هذا الزر للخروج من التحرير العام وتخصيص المنشور لهذه القناة",
657678
"edit_content": "تعديل المحتوى",

0 commit comments

Comments
 (0)