139 lines
3.8 KiB
TypeScript
Raw Normal View History

"use client";
import {
useMutation,
useQuery,
type UseMutationOptions,
type UseMutationResult,
type UseQueryOptions,
type UseQueryResult,
} from "@tanstack/react-query";
import { apiClient, queryKeys, getDataOrDefault, getDataOrThrow } from "@/lib/api";
import type { InvoiceQueryParams } from "@/lib/api/types";
import type {
Invoice,
InvoiceList,
InvoiceSsoLink,
PaymentMethodList,
} from "@customer-portal/domain";
import {
invoiceListSchema,
invoiceSchema as sharedInvoiceSchema,
} from "@customer-portal/domain/validation/shared/entities";
const emptyInvoiceList: InvoiceList = {
invoices: [],
pagination: {
page: 1,
totalItems: 0,
totalPages: 0,
},
};
const emptyPaymentMethods: PaymentMethodList = {
paymentMethods: [],
totalCount: 0,
};
type InvoicesQueryKey = ReturnType<typeof queryKeys.billing.invoices>;
type InvoiceQueryKey = ReturnType<typeof queryKeys.billing.invoice>;
type PaymentMethodsQueryKey = ReturnType<typeof queryKeys.billing.paymentMethods>;
type InvoicesQueryOptions = Omit<
UseQueryOptions<InvoiceList, Error, InvoiceList, InvoicesQueryKey>,
"queryKey" | "queryFn"
>;
type InvoiceQueryOptions = Omit<
UseQueryOptions<Invoice, Error, Invoice, InvoiceQueryKey>,
"queryKey" | "queryFn"
>;
type PaymentMethodsQueryOptions = Omit<
UseQueryOptions<PaymentMethodList, Error, PaymentMethodList, PaymentMethodsQueryKey>,
"queryKey" | "queryFn"
>;
type SsoLinkMutationOptions = UseMutationOptions<
InvoiceSsoLink,
Error,
{ invoiceId: number; target?: "view" | "download" | "pay" }
>;
async function fetchInvoices(params?: InvoiceQueryParams): Promise<InvoiceList> {
const response = await apiClient.GET<InvoiceList>(
"/invoices",
params ? { params: { query: params as Record<string, unknown> } } : undefined
);
const data = getDataOrDefault<InvoiceList>(response, emptyInvoiceList);
return invoiceListSchema.parse(data);
}
async function fetchInvoice(id: string): Promise<Invoice> {
const response = await apiClient.GET<Invoice>("/invoices/{id}", {
params: { path: { id } },
});
const invoice = getDataOrThrow<Invoice>(response, "Invoice not found");
return sharedInvoiceSchema.parse(invoice);
}
async function fetchPaymentMethods(): Promise<PaymentMethodList> {
const response = await apiClient.GET<PaymentMethodList>("/invoices/payment-methods");
return getDataOrDefault<PaymentMethodList>(response, emptyPaymentMethods);
}
export function useInvoices(
params?: InvoiceQueryParams,
options?: InvoicesQueryOptions
): UseQueryResult<InvoiceList, Error> {
const queryParams = params ? (params as Record<string, unknown>) : {};
return useQuery({
queryKey: queryKeys.billing.invoices(queryParams),
queryFn: () => fetchInvoices(params),
...options,
});
}
export function useInvoice(
id: string,
options?: InvoiceQueryOptions
): UseQueryResult<Invoice, Error> {
return useQuery({
queryKey: queryKeys.billing.invoice(id),
queryFn: () => fetchInvoice(id),
enabled: Boolean(id),
...options,
});
}
export function usePaymentMethods(
options?: PaymentMethodsQueryOptions
): UseQueryResult<PaymentMethodList, Error> {
return useQuery({
queryKey: queryKeys.billing.paymentMethods(),
queryFn: fetchPaymentMethods,
...options,
});
}
export function useCreateInvoiceSsoLink(
options?: SsoLinkMutationOptions
): UseMutationResult<
InvoiceSsoLink,
Error,
{ invoiceId: number; target?: "view" | "download" | "pay" }
> {
return useMutation({
mutationFn: async ({ invoiceId, target }) => {
const response = await apiClient.POST<InvoiceSsoLink>("/invoices/{id}/sso-link", {
params: {
path: { id: invoiceId },
query: target ? { target } : undefined,
},
});
return getDataOrThrow<InvoiceSsoLink>(response, "Failed to create SSO link");
},
...options,
});
}