From b8ef1522f9d124fc3c5878bff7452f59ea169048 Mon Sep 17 00:00:00 2001 From: William Stein Date: Mon, 9 Dec 2024 05:54:57 +0000 Subject: [PATCH] purchase: make them linkable with popup modal --- src/packages/frontend/purchases/purchases.tsx | 189 +++++++++++++----- 1 file changed, 141 insertions(+), 48 deletions(-) diff --git a/src/packages/frontend/purchases/purchases.tsx b/src/packages/frontend/purchases/purchases.tsx index bb1ac09734..317438c65b 100644 --- a/src/packages/frontend/purchases/purchases.tsx +++ b/src/packages/frontend/purchases/purchases.tsx @@ -6,6 +6,7 @@ import { DatePicker, Flex, Input, + Modal, Popover, Space, Spin, @@ -78,6 +79,7 @@ import PurchasesPlot from "./purchases-plot"; import searchFilter from "@cocalc/frontend/search/filter"; import { debounce } from "lodash"; import dayjs from "dayjs"; +import Fragment from "@cocalc/frontend/misc/fragment-id"; const DEFAULT_LIMIT = 10; @@ -577,6 +579,24 @@ function DetailedPurchaseTable({ purchases: PurchaseItem[] | null; admin: boolean; }) { + const [current, setCurrent] = useState(undefined); + const fragment = useTypedRedux("account", "fragment"); + useEffect(() => { + if (purchases == null) { + return; + } + const id = parseInt(fragment?.get("id") ?? Fragment.get()?.id ?? "-1"); + if (id == -1) { + return; + } + for (const purchase of purchases) { + if (purchase.id == id) { + setCurrent(purchase); + return; + } + } + }, [fragment, purchases]); + if (purchases == null) { return ; } @@ -588,6 +608,15 @@ function DetailedPurchaseTable({ dataSource={purchases} rowKey="id" columns={[ + { + render: (_, purchase) => { + return ( + + ); + }, + }, { width: "100px", title: "Id", @@ -601,54 +630,8 @@ function DetailedPurchaseTable({ dataIndex: "description", key: "description", width: "35%", - render: ( - _, - { id, description, invoice_id, notes, period_end, service }, - ) => ( -
- - - {description?.["line_items"] != null && ( - - )} - {invoice_id && ( - - {admin && id != null && ( - - )} - {!admin && ( - - )} - - - )} - - {notes && ( - - )} -
+ render: (_, purchase) => ( + ), }, { @@ -722,10 +705,120 @@ function DetailedPurchaseTable({ ]} /> + {current != null && ( + { + setCurrent(undefined); + Fragment.clear(); + redux.getActions("account").setFragment(undefined); + }} + /> + )} + + ); +} + +function PurchaseDescription({ + id, + description, + invoice_id, + notes, + period_end, + service, + admin, +}) { + return ( +
+ + + {description?.["line_items"] != null && ( + + )} + {invoice_id && ( + + {admin && id != null && } + {!admin && ( + + )} + + + )} + + {notes && ( + + )}
); } +function PurchaseModal({ purchase, onClose, admin }) { + useEffect(() => { + Fragment.set({ id: purchase.id }); + }, [purchase.id]); + return ( + Purchase Id={purchase.id}} + > + + +
+ Time: +
+
+ + +
+
+ {purchase.project_id ? ( + <> + Project: + + ) : undefined} +
+
+ Service: +
+
+ Amount: +
+ {purchase.balance != null && ( +
+ Balance: +
+ )} +
+
+ ); +} + // "credit" | "openai-gpt-4" | "project-upgrade" | "license" | "edit-license", etc. function Description({ description, period_end, service }) {