-
-
Notifications
You must be signed in to change notification settings - Fork 0
Promote dev to main (billing UI debt fix + upstream sync + reddit broker e2e spec) #62
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weβll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -264,7 +264,14 @@ export const MainBillingComponent: FC<{ | |||||
| setSubscription(sub); | ||||||
| }, [sub]); | ||||||
| const updatePayment = useCallback(async () => { | ||||||
| const { portal } = await (await fetch('/billing/portal')).json(); | ||||||
| // dos.me returns 409 no_stripe_subscription for accounts without a | ||||||
| // dos-managed plan - never navigate to an undefined portal. | ||||||
| const response = await fetch('/billing/portal'); | ||||||
| const { portal, message } = await response.json().catch(() => ({})); | ||||||
| if (!response.ok || !portal) { | ||||||
| toast.show(message || 'Payment portal is not available for this account'); | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The fallback error message is hardcoded. Please wrap it in the
Suggested change
|
||||||
| return; | ||||||
| } | ||||||
| window.location.href = portal; | ||||||
| }, []); | ||||||
| const currentPackage = useMemo(() => { | ||||||
|
|
@@ -281,22 +288,35 @@ export const MainBillingComponent: FC<{ | |||||
| } | ||||||
| return subscription?.subscriptionTier; | ||||||
| }, [subscription, initialChannels, monthlyOrYearly, period, sharedDosBilling]); | ||||||
| // dos.me owns checkout/portal/cancel: they only exist for a dos-managed | ||||||
| // paid plan, so hide both buttons for FREE and legacy tiers (e.g. | ||||||
| // comped ULTIMATE) where the calls can only answer 409. | ||||||
| const showPortalAndCancel = | ||||||
| !sharedDosBilling || | ||||||
| subscription?.subscriptionTier === 'STANDARD' || | ||||||
| subscription?.subscriptionTier === 'PRO'; | ||||||
| const moveToCheckout = useCallback( | ||||||
| (billing: 'STANDARD' | 'PRO' | 'FREE', reactivate = false) => | ||||||
| async () => { | ||||||
| if (reactivate) { | ||||||
| setLoading(true); | ||||||
| const { cancel_at } = await ( | ||||||
| await fetch('/billing/cancel', { | ||||||
| method: 'POST', | ||||||
| body: JSON.stringify({ | ||||||
| feedback: '', | ||||||
| }), | ||||||
| headers: { | ||||||
| 'Content-Type': 'application/json', | ||||||
| }, | ||||||
| }) | ||||||
| ).json(); | ||||||
| const response = await fetch('/billing/cancel', { | ||||||
| method: 'POST', | ||||||
| body: JSON.stringify({ | ||||||
| feedback: '', | ||||||
| }), | ||||||
| headers: { | ||||||
| 'Content-Type': 'application/json', | ||||||
| }, | ||||||
| }); | ||||||
| const { cancel_at, message } = await response | ||||||
| .json() | ||||||
| .catch(() => ({})); | ||||||
| if (!response.ok) { | ||||||
| setLoading(false); | ||||||
| toast.show(message || 'Could not reactivate the subscription'); | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The fallback error message is hardcoded. Please wrap it in the
Suggested change
|
||||||
| return; | ||||||
| } | ||||||
| setSubscription((subs) => ({ | ||||||
| ...subs!, | ||||||
| cancelAt: cancel_at, | ||||||
|
|
@@ -365,17 +385,23 @@ export const MainBillingComponent: FC<{ | |||||
| }); | ||||||
|
|
||||||
| setLoading(true); | ||||||
| const { cancel_at } = await ( | ||||||
| await fetch('/billing/cancel', { | ||||||
| method: 'POST', | ||||||
| body: JSON.stringify({ | ||||||
| feedback: info, | ||||||
| }), | ||||||
| headers: { | ||||||
| 'Content-Type': 'application/json', | ||||||
| }, | ||||||
| }) | ||||||
| ).json(); | ||||||
| const response = await fetch('/billing/cancel', { | ||||||
| method: 'POST', | ||||||
| body: JSON.stringify({ | ||||||
| feedback: info, | ||||||
| }), | ||||||
| headers: { | ||||||
| 'Content-Type': 'application/json', | ||||||
| }, | ||||||
| }); | ||||||
| const { cancel_at, message } = await response | ||||||
| .json() | ||||||
| .catch(() => ({})); | ||||||
| if (!response.ok) { | ||||||
| setLoading(false); | ||||||
| toast.show(message || 'Could not cancel the subscription'); | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||||||
| return; | ||||||
| } | ||||||
| setSubscription((subs) => ({ | ||||||
| ...subs!, | ||||||
| cancelAt: cancel_at, | ||||||
|
|
@@ -393,17 +419,26 @@ export const MainBillingComponent: FC<{ | |||||
| return; | ||||||
| } | ||||||
| setLoading(true); | ||||||
| const { url, portal, blocked } = await ( | ||||||
| await fetch('/billing/subscribe', { | ||||||
| method: 'POST', | ||||||
| body: JSON.stringify({ | ||||||
| period: monthlyOrYearly === 'on' ? 'YEARLY' : 'MONTHLY', | ||||||
| utm, | ||||||
| billing, | ||||||
| ...(dub ? { dub } : {}), | ||||||
| }), | ||||||
| }) | ||||||
| ).json(); | ||||||
| const response = await fetch('/billing/subscribe', { | ||||||
| method: 'POST', | ||||||
| body: JSON.stringify({ | ||||||
| period: monthlyOrYearly === 'on' ? 'YEARLY' : 'MONTHLY', | ||||||
| utm, | ||||||
| billing, | ||||||
| ...(dub ? { dub } : {}), | ||||||
| }), | ||||||
| }); | ||||||
| const { url, portal, blocked, message } = await response | ||||||
| .json() | ||||||
| .catch(() => ({})); | ||||||
| if (!response.ok) { | ||||||
| // A 4xx (no dos.me plan row, stripe error, ...) used to fall through | ||||||
| // to the success branch and toast "Subscription updated" + mutate | ||||||
| // the tier optimistically - surface the real failure instead. | ||||||
| setLoading(false); | ||||||
| toast.show(message || 'Subscription update failed, please try again later'); | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The fallback error message is hardcoded. Please wrap it in the
Suggested change
|
||||||
| return; | ||||||
| } | ||||||
| if (blocked) { | ||||||
| setLoading(false); | ||||||
| await deleteDialog( | ||||||
|
|
@@ -604,7 +639,7 @@ export const MainBillingComponent: FC<{ | |||||
| </div> | ||||||
| ))} | ||||||
| </div> | ||||||
| {!!subscription?.id && ( | ||||||
| {!!subscription?.id && showPortalAndCancel && ( | ||||||
| <div className="flex justify-center mt-[20px] gap-[10px]"> | ||||||
| <Button onClick={updatePayment}> | ||||||
| {t( | ||||||
|
|
||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The fallback error message is hardcoded. To support internationalization (i18n), please wrap the string in the
t()translation function.