diff --git a/src/components/AppSidebar.tsx b/src/components/AppSidebar.tsx index c141a88..0f3183e 100644 --- a/src/components/AppSidebar.tsx +++ b/src/components/AppSidebar.tsx @@ -29,6 +29,10 @@ const data = { title: "Offered", url: "/quotes/offered", }, + { + title: "Offer Expired", + url: "/quotes/offerexpired", + }, { title: "Accepted", url: "/quotes/accepted", @@ -41,6 +45,10 @@ const data = { title: "Rejected", url: "/quotes/rejected", }, + { + title: "Canceled", + url: "/quotes/canceled", + }, ], }, ], diff --git a/src/generated/client/sdk.gen.ts b/src/generated/client/sdk.gen.ts index e4d1df7..2b547a4 100644 --- a/src/generated/client/sdk.gen.ts +++ b/src/generated/client/sdk.gen.ts @@ -1,7 +1,7 @@ // This file is auto-generated by @hey-api/openapi-ts import type { Options as ClientOptions, TDataShape, Client } from '@hey-api/client-fetch'; -import type { ListQuotesData, ListQuotesResponse, ListPendingQuotesData, ListPendingQuotesResponse, AdminLookupQuoteData, AdminLookupQuoteResponse, AdminUpdateQuoteData, AdminUpdateQuoteResponse, ResolveOfferData, EnquireQuoteData, EnquireQuoteResponse, LookupQuoteData, LookupQuoteResponse, ActivateKeysetData, ActivateKeysetResponse, DebitData, CreditData, ECashBalance, OnChainBalanceData, OnChainData} from './types.gen'; +import type { ListQuotesData, ListQuotesResponse, ListPendingQuotesData, ListPendingQuotesResponse, AdminLookupQuoteData, AdminLookupQuoteResponse, AdminUpdateQuoteData, AdminUpdateQuoteResponse, ResolveOfferData, EnquireQuoteData, EnquireQuoteResponse, LookupQuoteData, LookupQuoteResponse, ActivateKeysetData, ActivateKeysetResponse, DebitData, CreditData, ECashBalance, OnChainBalanceData, OnChainData, KeysetInfoData, KeySetInfo} from './types.gen'; import { client as _heyApiClient } from './client.gen'; export type Options = ClientOptions & { @@ -91,7 +91,7 @@ export const lookupQuote = (options: Optio */ export const activateKeyset = (options: Options) => { return (options.client ?? _heyApiClient).post({ - url: '/v1/admin/keys/activate', + url: '/v1/admin/keys/enable', ...options, headers: { 'Content-Type': 'application/json', @@ -125,3 +125,14 @@ export const onchainBalance = (options: Op ...options }); }; + +/** + * --------------------------- KeySetInfo +*/ + +export const keysetInfo = (options: Options) => { + return (options.client ?? _heyApiClient).get({ + url: '/v1/admin/keysets/{keyset_id}', + ...options + }); +}; diff --git a/src/generated/client/types.gen.ts b/src/generated/client/types.gen.ts index 5e0a1be..4515483 100644 --- a/src/generated/client/types.gen.ts +++ b/src/generated/client/types.gen.ts @@ -135,9 +135,21 @@ export type InfoReply = { } | { bill: BillInfo; id: string; - signatures: Array; + status: 'Canceled'; + tstamp: string; +} | { + bill: BillInfo; + id: string; + keyset_id: string; status: 'Offered'; + discounted: number; ttl: string; +} | { + bill: BillInfo; + id: string; + status: 'OfferExpired'; + discounted: number; + tstamp: string; } | { bill: BillInfo; id: string; @@ -145,12 +157,14 @@ export type InfoReply = { } | { bill: BillInfo; id: string; - signatures: Array; + keyset_id: string; + discounted: number; status: 'Accepted'; } | { bill: BillInfo; id: string; status: 'Rejected'; + discounted: number; tstamp: string; }; @@ -402,7 +416,7 @@ export type ActivateKeysetData = { body: ActivateKeysetRequest; path?: never; query?: never; - url: '/v1/admin/keys/activate'; + url: '/v1/admin/keys/enable'; }; export type ActivateKeysetErrors = { @@ -455,10 +469,30 @@ export type OnChainBalanceData = { confirmed: number; }; - export type OnChainData = { body?: never; path?: never; query?: never; url: '/v1/admin/onchain/balance'; }; + +/** + * Keyset information + */ + +export type KeySetInfo = { + id: string; + unit: CurrencyUnit; + active: boolean; + input_fee_ppk: number; +}; + + +export type KeysetInfoData = { + body?: never; + path: { + keyset_id: string; + }; + query?: never; + url: '/v1/admin/keysets/{keyset_id}'; +}; diff --git a/src/main.tsx b/src/main.tsx index c145461..c047c76 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -20,10 +20,6 @@ const queryClient = new QueryClient() const prepare = async () => { await initKeycloak() - // if (meta.apiMocksEnabled) { - // const { worker } = await import("./mocks/browser") - // await worker.start() - // } } function App() { @@ -39,10 +35,11 @@ function App() { } /> } /> } /> + } /> } /> + } /> } /> } /> - {/* } /> */} } /> } /> } /> diff --git a/src/pages/quotes/QuotePage.tsx b/src/pages/quotes/QuotePage.tsx index 59f30b1..daff027 100644 --- a/src/pages/quotes/QuotePage.tsx +++ b/src/pages/quotes/QuotePage.tsx @@ -12,12 +12,12 @@ import { adminLookupQuoteQueryKey, adminUpdateQuoteMutation, } from "@/generated/client/@tanstack/react-query.gen" -import { activateKeyset } from "@/generated/client/sdk.gen" +import { activateKeyset, keysetInfo } from "@/generated/client/sdk.gen" import { cn, getInitials } from "@/lib/utils" import { formatDate, humanReadableDuration } from "@/utils/dates" import { formatNumber, truncateString } from "@/utils/strings" -import { useMutation, useQueryClient, useSuspenseQuery } from "@tanstack/react-query" +import { useMutation, useQuery, useQueryClient, useSuspenseQuery } from "@tanstack/react-query" import { getDeterministicColor } from "@/utils/dev" import { LoaderIcon } from "lucide-react" @@ -211,7 +211,7 @@ function DenyConfirmDrawer({ children, onSubmit, ...drawerProps }: DenyConfirmDr ) } -function QuoteActions({ value, isFetching }: { value: InfoReply; isFetching: boolean }) { +function QuoteActions({ value, isFetching, newKeyset }: { value: InfoReply; isFetching: boolean; newKeyset: boolean }) { const [offerFormData, setOfferFormData] = useState() const [offerFormDrawerOpen, setOfferFormDrawerOpen] = useState(false) const [offerConfirmDrawerOpen, setOfferConfirmDrawerOpen] = useState(false) @@ -289,13 +289,7 @@ function QuoteActions({ value, isFetching }: { value: InfoReply; isFetching: boo }, onSuccess: () => { toast.success("Keyset has been activated.") - void queryClient.invalidateQueries({ - queryKey: adminLookupQuoteQueryKey({ - path: { - id: value.id, - }, - }), - }) + void queryClient.invalidateQueries() }, }) @@ -331,42 +325,50 @@ function QuoteActions({ value, isFetching }: { value: InfoReply; isFetching: boo const onActivateKeyset = () => { activateKeysetMutation.mutate() } - return (
- { - onDenyQuote() - setDenyConfirmDrawerOpen(false) - }} - > - - - { - setOfferFormData(data) - setOfferConfirmDrawerOpen(true) - setOfferFormDrawerOpen(false) - }} - > - - + + + ) : ( + <> + )} + {value.status === "Pending" ? ( + { + setOfferFormData(data) + setOfferConfirmDrawerOpen(true) + setOfferFormDrawerOpen(false) + }} + > + + + ) : ( + <> + )} + - { - onActivateKeyset() - setActivateKeysetConfirmDrawerOpen(false) - }} - submitButtonText="Yes, activate keyset" - trigger={ - - } - /> + {value.status === "Accepted" && "keyset_id" in value ? ( + { + onActivateKeyset() + setActivateKeysetConfirmDrawerOpen(false) + }} + submitButtonText="Yes, activate keyset" + trigger={ + + } + /> + ) : ( + <> + )}
) } @@ -565,8 +571,6 @@ function AnonPublicDataCard({ value }: { value?: AnonPublicData }) { function PayeePublicDataCard({ value }: { value?: PayeePublicData }) { if (!value) return null - console.log("Payee public data", value) - if ("Ident" in value) { const identData = (value as { Ident: IdentityPublicData }).Ident return IdentityPublicDataCard({ value: identData }) @@ -579,6 +583,22 @@ function PayeePublicDataCard({ value }: { value?: PayeePublicData }) { } function Quote({ value, isFetching }: { value: InfoReply; isFetching: boolean }) { + const shouldFetchKeyset = (value.status === "Offered" || value.status === "Accepted") && "keyset_id" in value + + const keysetId = "keyset_id" in value ? value.keyset_id : "" + + const { data: keysetData } = useQuery({ + queryKey: ["keyset", keysetId], + queryFn: () => + keysetInfo({ + path: { keyset_id: keysetId }, + }), + enabled: shouldFetchKeyset, + }) + + const ebillPaid = keysetData?.data && "active" in keysetData.data && keysetData.data.active === false + const newKeyset = "keyset_id" in value && (!keysetData?.data || !("active" in keysetData.data)) + return (
@@ -589,6 +609,28 @@ function Quote({ value, isFetching }: { value: InfoReply; isFetching: boolean }) {value.id} + {(value.status === "Offered" || value.status === "Accepted") && "keyset_id" in value ? ( + + Keyset ID: + + {keysetId} + + {ebillPaid ? "Paid" : "Unpaid"} + + + {newKeyset ? "Disabled" : "Enabled"} + + + + ) : ( + <> + )} Status: @@ -601,6 +643,18 @@ function Quote({ value, isFetching }: { value: InfoReply; isFetching: boolean }) Sum: {formatNumber("en", value.bill?.sum)} sat + {(value.status === "Offered" || + value.status === "Accepted" || + value.status === "Rejected" || + value.status === "OfferExpired") && + "discounted" in value ? ( + + Discounted: + {formatNumber("en", value.discounted)} crsat + + ) : ( + <> + )} Maturity date: @@ -646,7 +700,7 @@ function Quote({ value, isFetching }: { value: InfoReply; isFetching: boolean })
- +
) } diff --git a/src/pages/quotes/StatusQuotePage.tsx b/src/pages/quotes/StatusQuotePage.tsx index 2465c42..c74ff73 100644 --- a/src/pages/quotes/StatusQuotePage.tsx +++ b/src/pages/quotes/StatusQuotePage.tsx @@ -16,7 +16,7 @@ import { formatNumber, truncateString } from "@/utils/strings" import { Badge } from "@/components/ui/badge" import { cn } from "@/lib/utils" -type QuoteStatus = "Accepted" | "Denied" | "Expired" | "Offered" | "Pending" | "Rejected" | "Cancelled" +type QuoteStatus = "Accepted" | "Denied" | "OfferExpired" | "Offered" | "Pending" | "Rejected" | "Canceled" interface StatusQuotePageProps { status?: QuoteStatus