mirror of
https://github.com/aljazceru/opencode.git
synced 2025-12-21 09:44:21 +01:00
wip: zen
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
import { Billing } from "@opencode/cloud-core/billing.js"
|
import { Billing } from "@opencode/cloud-core/billing.js"
|
||||||
import { query, useParams, createAsync } from "@solidjs/router"
|
import { query, action, useParams, createAsync, useAction } from "@solidjs/router"
|
||||||
import { For } from "solid-js"
|
import { For } from "solid-js"
|
||||||
import { withActor } from "~/context/auth.withActor"
|
import { withActor } from "~/context/auth.withActor"
|
||||||
import { formatDateUTC, formatDateForTable } from "./common"
|
import { formatDateUTC, formatDateForTable } from "./common"
|
||||||
@@ -12,9 +12,15 @@ const getPaymentsInfo = query(async (workspaceID: string) => {
|
|||||||
}, workspaceID)
|
}, workspaceID)
|
||||||
}, "payment.list")
|
}, "payment.list")
|
||||||
|
|
||||||
|
const downloadReceipt = action(async (workspaceID: string, paymentID: string) => {
|
||||||
|
"use server"
|
||||||
|
return withActor(() => Billing.generateReceiptUrl({ paymentID }), workspaceID)
|
||||||
|
}, "receipt.download")
|
||||||
|
|
||||||
export function PaymentSection() {
|
export function PaymentSection() {
|
||||||
const params = useParams()
|
const params = useParams()
|
||||||
const payments = createAsync(() => getPaymentsInfo(params.id))
|
const payments = createAsync(() => getPaymentsInfo(params.id))
|
||||||
|
const downloadReceiptAction = useAction(downloadReceipt)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
payments() &&
|
payments() &&
|
||||||
@@ -31,6 +37,7 @@ export function PaymentSection() {
|
|||||||
<th>Date</th>
|
<th>Date</th>
|
||||||
<th>Payment ID</th>
|
<th>Payment ID</th>
|
||||||
<th>Amount</th>
|
<th>Amount</th>
|
||||||
|
<th>Receipt</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
@@ -44,6 +51,20 @@ export function PaymentSection() {
|
|||||||
</td>
|
</td>
|
||||||
<td data-slot="payment-id">{payment.id}</td>
|
<td data-slot="payment-id">{payment.id}</td>
|
||||||
<td data-slot="payment-amount">${((payment.amount ?? 0) / 100000000).toFixed(2)}</td>
|
<td data-slot="payment-amount">${((payment.amount ?? 0) / 100000000).toFixed(2)}</td>
|
||||||
|
<td data-slot="payment-receipt">
|
||||||
|
<button
|
||||||
|
onClick={async () => {
|
||||||
|
const receiptUrl = await downloadReceiptAction(params.id, payment.paymentID!)
|
||||||
|
if (receiptUrl) {
|
||||||
|
window.open(receiptUrl, "_blank")
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
data-slot="receipt-button"
|
||||||
|
style="cursor: pointer;"
|
||||||
|
>
|
||||||
|
download
|
||||||
|
</button>
|
||||||
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
)
|
)
|
||||||
}}
|
}}
|
||||||
|
|||||||
@@ -538,7 +538,6 @@ export async function handler(
|
|||||||
async function reload() {
|
async function reload() {
|
||||||
if (!apiKey) return
|
if (!apiKey) return
|
||||||
|
|
||||||
// acquire reload lock
|
|
||||||
const lock = await Database.use((tx) =>
|
const lock = await Database.use((tx) =>
|
||||||
tx
|
tx
|
||||||
.update(BillingTable)
|
.update(BillingTable)
|
||||||
|
|||||||
@@ -224,4 +224,21 @@ export namespace Billing {
|
|||||||
return session.url
|
return session.url
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
export const generateReceiptUrl = fn(
|
||||||
|
z.object({
|
||||||
|
paymentID: z.string(),
|
||||||
|
}),
|
||||||
|
async (input) => {
|
||||||
|
const { paymentID } = input
|
||||||
|
|
||||||
|
const intent = await Billing.stripe().paymentIntents.retrieve(paymentID)
|
||||||
|
if (!intent.latest_charge) throw new Error("No charge found")
|
||||||
|
|
||||||
|
const charge = await Billing.stripe().charges.retrieve(intent.latest_charge as string)
|
||||||
|
if (!charge.receipt_url) throw new Error("No receipt URL found")
|
||||||
|
|
||||||
|
return charge.receipt_url
|
||||||
|
},
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user