diff options
| author | Frank <[email protected]> | 2025-09-25 17:47:50 -0400 |
|---|---|---|
| committer | Frank <[email protected]> | 2025-09-25 17:47:50 -0400 |
| commit | f9117bcc7f03a45458e20b6488881cf3ac0f877e (patch) | |
| tree | f1ee97105c2b12aa9ab208d2ef62004afef80b79 | |
| parent | 6e712f9faf4e83c3e063ab2d2daeb7fd38194ca8 (diff) | |
| download | opencode-f9117bcc7f03a45458e20b6488881cf3ac0f877e.tar.gz opencode-f9117bcc7f03a45458e20b6488881cf3ac0f877e.zip | |
zen: check balance on enable billing
| -rw-r--r-- | packages/console/app/src/component/workspace/billing-section.tsx | 71 |
1 files changed, 51 insertions, 20 deletions
diff --git a/packages/console/app/src/component/workspace/billing-section.tsx b/packages/console/app/src/component/workspace/billing-section.tsx index 7d297ed33..02cf8433e 100644 --- a/packages/console/app/src/component/workspace/billing-section.tsx +++ b/packages/console/app/src/component/workspace/billing-section.tsx @@ -4,6 +4,8 @@ import { Billing } from "@opencode/console-core/billing.js" import { withActor } from "~/context/auth.withActor" import { IconCreditCard } from "~/component/icon" import styles from "./billing-section.module.css" +import { Database, eq } from "@opencode/console-core/drizzle/index.js" +import { BillingTable } from "@opencode/console-core/schema/billing.sql.js" const createCheckoutUrl = action(async (workspaceID: string, successUrl: string, cancelUrl: string) => { "use server" @@ -17,12 +19,23 @@ const reload = action(async (form: FormData) => { return json(await withActor(() => Billing.reload(), workspaceID), { revalidate: getBillingInfo.key }) }, "billing.reload") -const disableReload = action(async (form: FormData) => { +const setReload = action(async (form: FormData) => { "use server" const workspaceID = form.get("workspaceID")?.toString() if (!workspaceID) return { error: "Workspace ID is required" } - return json(await withActor(() => Billing.disableReload(), workspaceID), { revalidate: getBillingInfo.key }) -}, "billing.disableReload") + const reload = form.get("reload")?.toString() === "true" + return json( + await Database.use((tx) => + tx + .update(BillingTable) + .set({ + reload, + }) + .where(eq(BillingTable.workspaceID, workspaceID)), + ), + { revalidate: getBillingInfo.key }, + ) +}, "billing.setReload") const createSessionUrl = action(async (workspaceID: string, returnUrl: string) => { "use server" @@ -44,7 +57,7 @@ export function BillingSection() { const createCheckoutUrlSubmission = useSubmission(createCheckoutUrl) const createSessionUrlAction = useAction(createSessionUrl) const createSessionUrlSubmission = useSubmission(createSessionUrl) - const disableReloadSubmission = useSubmission(disableReload) + const setReloadSubmission = useSubmission(setReload) const reloadSubmission = useSubmission(reload) // DUMMY DATA FOR TESTING - UNCOMMENT ONE OF THE SCENARIOS BELOW @@ -89,6 +102,10 @@ export function BillingSection() { return ((balanceInfo()?.balance ?? 0) / 100000000).toFixed(2) }) + const hasBalance = createMemo(() => { + return (balanceInfo()?.balance ?? 0) > 0 && balanceAmount() !== "0.00" + }) + return ( <section class={styles.root}> <div data-slot="section-title"> @@ -136,19 +153,32 @@ export function BillingSection() { <Show when={balanceInfo()?.reload} fallback={ - <button - data-color="primary" - disabled={createCheckoutUrlSubmission.pending} - onClick={async () => { - const baseUrl = window.location.href - const checkoutUrl = await createCheckoutUrlAction(params.id, baseUrl, baseUrl) - if (checkoutUrl) { - window.location.href = checkoutUrl - } - }} + <Show + when={hasBalance()} + fallback={ + <button + data-color="primary" + disabled={createCheckoutUrlSubmission.pending} + onClick={async () => { + const baseUrl = window.location.href + const checkoutUrl = await createCheckoutUrlAction(params.id, baseUrl, baseUrl) + if (checkoutUrl) { + window.location.href = checkoutUrl + } + }} + > + {createCheckoutUrlSubmission.pending ? "Loading..." : "Enable Billing"} + </button> + } > - {createCheckoutUrlSubmission.pending ? "Loading..." : "Enable Billing"} - </button> + <form action={setReload} method="post" data-slot="create-form"> + <input type="hidden" name="workspaceID" value={params.id} /> + <input type="hidden" name="reload" value="true" /> + <button data-color="primary" type="submit" disabled={setReloadSubmission.pending}> + {setReloadSubmission.pending ? "Enabling..." : "Enable Billing"} + </button> + </form> + </Show> } > <button @@ -164,10 +194,11 @@ export function BillingSection() { > {createSessionUrlSubmission.pending ? "Loading..." : "Manage Payment Methods"} </button> - <form action={disableReload} method="post" data-slot="create-form"> + <form action={setReload} method="post" data-slot="create-form"> <input type="hidden" name="workspaceID" value={params.id} /> - <button data-color="ghost" type="submit" disabled={disableReloadSubmission.pending}> - {disableReloadSubmission.pending ? "Disabling..." : "Disable"} + <input type="hidden" name="reload" value="false" /> + <button data-color="ghost" type="submit" disabled={setReloadSubmission.pending}> + {setReloadSubmission.pending ? "Disabling..." : "Disable"} </button> </form> </Show> @@ -176,7 +207,7 @@ export function BillingSection() { <div data-slot="usage"> <Show when={!balanceInfo()?.reload}> <Show - when={!(balanceAmount() === "0.00" || balanceAmount() === "-0.00")} + when={hasBalance()} fallback={ <p> We'll load <b>$20</b> (+$1.23 processing fee) and reload it when it reaches <b>$5</b>. |
