diff --git a/src/components/invoice-creator.tsx b/src/components/invoice-creator.tsx index 44fb227c..3aae045a 100644 --- a/src/components/invoice-creator.tsx +++ b/src/components/invoice-creator.tsx @@ -1,6 +1,6 @@ "use client"; -import { InvoiceForm } from "@/components/invoice-form"; +import { InvoiceForm } from "@/components/invoice-form/invoice-form"; import { InvoicePreview } from "@/components/invoice-preview"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { generateInvoiceNumber } from "@/lib/helpers/client"; diff --git a/src/components/invoice-form/blocks/payment-currency-selector.tsx b/src/components/invoice-form/blocks/payment-currency-selector.tsx new file mode 100644 index 00000000..921fd344 --- /dev/null +++ b/src/components/invoice-form/blocks/payment-currency-selector.tsx @@ -0,0 +1,116 @@ +import { Label } from "@/components/ui/label"; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from "@/components/ui/select"; +import { + type InvoiceCurrency, + formatCurrencyLabel, +} from "@/lib/constants/currencies"; +import { api } from "@/trpc/react"; +import { Loader2 } from "lucide-react"; + +interface PaymentCurrencySelectorProps { + onChange: (value: string) => void; + targetCurrency: InvoiceCurrency; + network: string; +} + +export function PaymentCurrencySelector({ + onChange, + targetCurrency, + network, +}: PaymentCurrencySelectorProps) { + const { + data: conversionData, + isLoading, + error, + refetch, + } = api.currency.getConversionCurrencies.useQuery({ + targetCurrency, + network, + }); + + if (isLoading) { + return ( +
+ Failed to load payment currencies: {error.message} +
++ {" "} + or refresh the page. +
++ No payment currencies are available for {targetCurrency} on {network} +
+
{form.formState.errors.paymentCurrency.message}
diff --git a/src/server/index.ts b/src/server/index.ts
index 5364df09..64442c73 100644
--- a/src/server/index.ts
+++ b/src/server/index.ts
@@ -1,5 +1,6 @@
import { authRouter } from "./routers/auth";
import { complianceRouter } from "./routers/compliance";
+import { currencyRouter } from "./routers/currency";
import { invoiceRouter } from "./routers/invoice";
import { invoiceMeRouter } from "./routers/invoice-me";
import { paymentRouter } from "./routers/payment";
@@ -15,6 +16,7 @@ export const appRouter = router({
compliance: complianceRouter,
recurringPayment: recurringPaymentRouter,
subscriptionPlan: subscriptionPlanRouter,
+ currency: currencyRouter,
});
export type AppRouter = typeof appRouter;
diff --git a/src/server/routers/currency.ts b/src/server/routers/currency.ts
new file mode 100644
index 00000000..ed6d9cbd
--- /dev/null
+++ b/src/server/routers/currency.ts
@@ -0,0 +1,64 @@
+import { apiClient } from "@/lib/axios";
+import { TRPCError } from "@trpc/server";
+import type { AxiosResponse } from "axios";
+import axios from "axios";
+import { z } from "zod";
+import { publicProcedure, router } from "../trpc";
+
+export type ConversionCurrency = {
+ id: string;
+ symbol: string;
+ decimals: number;
+ address: string;
+ type: "ERC20" | "ETH" | "ISO4217";
+ network: string;
+};
+
+export interface GetConversionCurrenciesResponse {
+ currencyId: string;
+ network: string;
+ conversionRoutes: ConversionCurrency[];
+}
+
+export const currencyRouter = router({
+ getConversionCurrencies: publicProcedure
+ .input(
+ z.object({
+ targetCurrency: z.string(),
+ network: z.string(),
+ }),
+ )
+ .query(async ({ input }): Promise