diff --git a/src/app/(auth)/layout.tsx b/src/app/(auth)/layout.tsx
new file mode 100644
index 00000000..f3ea9db6
--- /dev/null
+++ b/src/app/(auth)/layout.tsx
@@ -0,0 +1,7 @@
+import type { ReactNode } from "react";
+
+export default function AuthLayout({ children }: { children: ReactNode }) {
+ return (
+
{children}
+ );
+}
diff --git a/src/app/(auth)/signin/page.tsx b/src/app/(auth)/signin/page.tsx
new file mode 100644
index 00000000..44169beb
--- /dev/null
+++ b/src/app/(auth)/signin/page.tsx
@@ -0,0 +1,74 @@
+import { Footer } from "@/components/footer";
+import { Header } from "@/components/header";
+import { getCurrentSession } from "@/server/auth";
+import type { Metadata } from "next";
+import Image from "next/image";
+import Link from "next/link";
+import { redirect } from "next/navigation";
+
+export const metadata: Metadata = {
+ title: "EasyInvoice | Simple Invoice Management",
+ description: "Create, manage and track invoices easily with Request Network",
+};
+
+export default async function LoginPage() {
+ const { user } = await getCurrentSession();
+
+ if (user) {
+ return redirect("/home");
+ }
+
+ const termsUrl =
+ process.env.NEXT_PUBLIC_API_TERMS_CONDITIONS ||
+ "https://request.network/api-terms";
+
+ return (
+ <>
+
+
+
+
+
+ EASY TO USE CRYPTO INVOICING
+
+
+ Welcome to EasyInvoice
+
+
+ Easily create and send invoices to your customers using crypto.
+
+
+
+
+
+
+ Continue with Google
+
+
+ By continuing, you agree to our{" "}
+
+ Terms and Conditions
+
+ .
+
+
+
+
+
+ >
+ );
+}
diff --git a/src/components/compliance-form.tsx b/src/app/(dashboard)/crypto-to-fiat/_components/compliance-form.tsx
similarity index 99%
rename from src/components/compliance-form.tsx
rename to src/app/(dashboard)/crypto-to-fiat/_components/compliance-form.tsx
index e27c7005..acfce9e5 100644
--- a/src/components/compliance-form.tsx
+++ b/src/app/(dashboard)/crypto-to-fiat/_components/compliance-form.tsx
@@ -31,6 +31,7 @@ import {
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
+import { Skeleton } from "@/components/ui/skeleton";
import { COMPLIANCE_COUNTRIES } from "@/lib/constants/compliance";
import {
BeneficiaryType,
@@ -45,7 +46,6 @@ import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import { useForm } from "react-hook-form";
import { toast } from "sonner";
import { ComplianceStatus, type StatusType } from "./compliance-status";
-import { Skeleton } from "./ui/skeleton";
type ComplianceResponse = {
agreementUrl: string | null;
diff --git a/src/components/compliance-status.tsx b/src/app/(dashboard)/crypto-to-fiat/_components/compliance-status.tsx
similarity index 98%
rename from src/components/compliance-status.tsx
rename to src/app/(dashboard)/crypto-to-fiat/_components/compliance-status.tsx
index 56c910e8..ec99aab3 100644
--- a/src/components/compliance-status.tsx
+++ b/src/app/(dashboard)/crypto-to-fiat/_components/compliance-status.tsx
@@ -1,6 +1,6 @@
import { Card, CardContent } from "@/components/ui/card";
+import { Skeleton } from "@/components/ui/skeleton";
import { AlertCircle, CheckCircle, Clock } from "lucide-react";
-import { Skeleton } from "./ui/skeleton";
export type StatusType =
| "not_started"
diff --git a/src/components/crypto-to-fiat.tsx b/src/app/(dashboard)/crypto-to-fiat/_components/crypto-to-fiat.tsx
similarity index 100%
rename from src/components/crypto-to-fiat.tsx
rename to src/app/(dashboard)/crypto-to-fiat/_components/crypto-to-fiat.tsx
diff --git a/src/app/(dashboard)/crypto-to-fiat/page.tsx b/src/app/(dashboard)/crypto-to-fiat/page.tsx
new file mode 100644
index 00000000..ba4c4f6f
--- /dev/null
+++ b/src/app/(dashboard)/crypto-to-fiat/page.tsx
@@ -0,0 +1,15 @@
+import { PageDescription, PageTitle } from "@/components/page-elements";
+import { requireAuth } from "@/lib/auth";
+import { CryptoToFiat } from "./_components/crypto-to-fiat";
+
+export default async function CryptoToFiatPage() {
+ const user = await requireAuth();
+
+ return (
+ <>
+ Crypto-to-fiat
+ Pay fiat invoices with crypto
+
+ >
+ );
+}
diff --git a/src/components/dashboard-navigation.tsx b/src/app/(dashboard)/dashboard/_components/dashboard-navigation.tsx
similarity index 58%
rename from src/components/dashboard-navigation.tsx
rename to src/app/(dashboard)/dashboard/_components/dashboard-navigation.tsx
index 0ac17820..d504d77a 100644
--- a/src/components/dashboard-navigation.tsx
+++ b/src/app/(dashboard)/dashboard/_components/dashboard-navigation.tsx
@@ -7,29 +7,21 @@ import { useEffect, useState } from "react";
export function DashboardNavigation() {
const pathname = usePathname();
- const [activeTab, setActiveTab] = useState("get-paid");
+ const [activeTab, setActiveTab] = useState(() =>
+ pathname.includes("/subscriptions") ? "subscriptions" : "receipts",
+ );
useEffect(() => {
- if (pathname.includes("/pay")) {
- setActiveTab("pay");
- } else if (pathname.includes("/subscriptions")) {
+ if (pathname.includes("/subscriptions")) {
setActiveTab("subscriptions");
- } else if (pathname.includes("/receipts")) {
- setActiveTab("receipts");
} else {
- setActiveTab("get-paid");
+ setActiveTab("receipts");
}
}, [pathname]);
return (
-
-
- Get Paid
-
-
- Pay
-
+
Subscriptions
diff --git a/src/app/(dashboard)/dashboard/layout.tsx b/src/app/(dashboard)/dashboard/layout.tsx
new file mode 100644
index 00000000..9fb00306
--- /dev/null
+++ b/src/app/(dashboard)/dashboard/layout.tsx
@@ -0,0 +1,19 @@
+import { PageDescription, PageTitle } from "@/components/page-elements";
+import { DashboardNavigation } from "./_components/dashboard-navigation";
+
+export default function DashboardLayout({
+ children,
+}: {
+ children: React.ReactNode;
+}) {
+ return (
+ <>
+ Dashboard
+
+ Overview of your payments, invoices, and subscriptions
+
+
+
{children}
+ >
+ );
+}
diff --git a/src/app/dashboard/page.tsx b/src/app/(dashboard)/dashboard/page.tsx
similarity index 68%
rename from src/app/dashboard/page.tsx
rename to src/app/(dashboard)/dashboard/page.tsx
index 401a3051..cc7d4bd5 100644
--- a/src/app/dashboard/page.tsx
+++ b/src/app/(dashboard)/dashboard/page.tsx
@@ -1,5 +1,5 @@
import { redirect } from "next/navigation";
export default function DashboardPage() {
- redirect("/dashboard/get-paid");
+ redirect("/dashboard/subscriptions");
}
diff --git a/src/components/dashboard/receipts.tsx b/src/app/(dashboard)/dashboard/receipts/_components/receipts.tsx
similarity index 98%
rename from src/components/dashboard/receipts.tsx
rename to src/app/(dashboard)/dashboard/receipts/_components/receipts.tsx
index 709254c3..961ea7b3 100644
--- a/src/components/dashboard/receipts.tsx
+++ b/src/app/(dashboard)/dashboard/receipts/_components/receipts.tsx
@@ -9,6 +9,7 @@ import {
SelectValue,
} from "@/components/ui/select";
import { EmptyState } from "@/components/ui/table/empty-state";
+import { ErrorState } from "@/components/ui/table/error-state";
import { Pagination } from "@/components/ui/table/pagination";
import {
Table,
@@ -23,7 +24,6 @@ import { api } from "@/trpc/react";
import { format } from "date-fns";
import { Filter, Receipt } from "lucide-react";
import { useState } from "react";
-import { ErrorState } from "../ui/table/error-state";
interface DashboardReceiptsProps {
initialClientPayments: ClientPaymentWithEcommerceClient[];
diff --git a/src/app/(dashboard)/dashboard/receipts/page.tsx b/src/app/(dashboard)/dashboard/receipts/page.tsx
new file mode 100644
index 00000000..d5e643be
--- /dev/null
+++ b/src/app/(dashboard)/dashboard/receipts/page.tsx
@@ -0,0 +1,11 @@
+import { requireAuth } from "@/lib/auth";
+import { api } from "@/trpc/server";
+import { DashboardReceipts } from "./_components/receipts";
+
+export default async function ReceiptsPage() {
+ await requireAuth();
+
+ const clientPayments = await api.ecommerce.getAllUserReceipts.query();
+
+ return ;
+}
diff --git a/src/components/dashboard/subscriptions.tsx b/src/app/(dashboard)/dashboard/subscriptions/_components/subscriptions.tsx
similarity index 94%
rename from src/components/dashboard/subscriptions.tsx
rename to src/app/(dashboard)/dashboard/subscriptions/_components/subscriptions.tsx
index 40906541..d8274d07 100644
--- a/src/components/dashboard/subscriptions.tsx
+++ b/src/app/(dashboard)/dashboard/subscriptions/_components/subscriptions.tsx
@@ -1,6 +1,10 @@
"use client";
+import { RecurringPaymentStatusBadge } from "@/components/recurring-payment-status-badge";
+import { CompletedPayments } from "@/components/recurring-payments/completed-payments";
+import { FrequencyBadge } from "@/components/recurring-payments/frequency-badge";
import { ShortAddress } from "@/components/short-address";
+import { StatCard } from "@/components/stat-card";
import {
AlertDialog,
AlertDialogAction,
@@ -11,7 +15,10 @@ import {
AlertDialogHeader,
AlertDialogTitle,
} from "@/components/ui/alert-dialog";
+import { Button } from "@/components/ui/button";
import { Card, CardContent } from "@/components/ui/card";
+import { EmptyState } from "@/components/ui/table/empty-state";
+import { Pagination } from "@/components/ui/table/pagination";
import {
Table,
TableBody,
@@ -19,8 +26,7 @@ import {
TableHeader,
TableRow,
} from "@/components/ui/table/table";
-import { CompletedPayments } from "@/components/view-recurring-payments/blocks/completed-payments";
-import { FrequencyBadge } from "@/components/view-recurring-payments/blocks/frequency-badge";
+import { TableHeadCell } from "@/components/ui/table/table-head-cell";
import { formatCurrencyLabel } from "@/lib/constants/currencies";
import { consolidateRecurringPaymentUsdValues } from "@/lib/helpers/conversion";
import { useCancelRecurringPayment } from "@/lib/hooks/use-cancel-recurring-payment";
@@ -30,12 +36,6 @@ import { api } from "@/trpc/react";
import { addDays, format } from "date-fns";
import { Ban, CreditCard, DollarSign, Loader2 } from "lucide-react";
import { useState } from "react";
-import { StatCard } from "../stat-card";
-import { Button } from "../ui/button";
-import { EmptyState } from "../ui/table/empty-state";
-import { Pagination } from "../ui/table/pagination";
-import { TableHeadCell } from "../ui/table/table-head-cell";
-import { StatusBadge } from "../view-recurring-payments/blocks/status-badge";
const ITEMS_PER_PAGE = 10;
const ACTIVE_STATUSES = ["pending", "active"];
@@ -53,6 +53,7 @@ const SubscriptionTableColumns = () => (
ChainRecipientPayment History
+ Actions
);
@@ -105,7 +106,7 @@ const SubscriptionRow = ({
{subscription.subscription?.label || "Unnamed Plan"}
-
+
{subscription.subscription?.trialDays
diff --git a/src/app/dashboard/subscriptions/page.tsx b/src/app/(dashboard)/dashboard/subscriptions/page.tsx
similarity index 50%
rename from src/app/dashboard/subscriptions/page.tsx
rename to src/app/(dashboard)/dashboard/subscriptions/page.tsx
index 0f6d73d7..f30c6fa7 100644
--- a/src/app/dashboard/subscriptions/page.tsx
+++ b/src/app/(dashboard)/dashboard/subscriptions/page.tsx
@@ -1,14 +1,9 @@
-import { Subscriptions } from "@/components/dashboard/subscriptions";
-import { getCurrentSession } from "@/server/auth";
+import { requireAuth } from "@/lib/auth";
import { api } from "@/trpc/server";
-import { redirect } from "next/navigation";
+import { Subscriptions } from "./_components/subscriptions";
export default async function SubscriptionsPage() {
- const { user } = await getCurrentSession();
-
- if (!user) {
- redirect("/");
- }
+ await requireAuth();
const subscriptions =
await api.subscriptionPlan.getUserActiveSubscriptions.query();
diff --git a/src/components/ecommerce/manage/blocks/client-form.tsx b/src/app/(dashboard)/ecommerce/manage/_components/blocks/client-form.tsx
similarity index 100%
rename from src/components/ecommerce/manage/blocks/client-form.tsx
rename to src/app/(dashboard)/ecommerce/manage/_components/blocks/client-form.tsx
diff --git a/src/components/ecommerce/manage/blocks/clients-table.tsx b/src/app/(dashboard)/ecommerce/manage/_components/blocks/clients-table.tsx
similarity index 100%
rename from src/components/ecommerce/manage/blocks/clients-table.tsx
rename to src/app/(dashboard)/ecommerce/manage/_components/blocks/clients-table.tsx
diff --git a/src/components/ecommerce/manage/blocks/create-client.tsx b/src/app/(dashboard)/ecommerce/manage/_components/blocks/create-client.tsx
similarity index 100%
rename from src/components/ecommerce/manage/blocks/create-client.tsx
rename to src/app/(dashboard)/ecommerce/manage/_components/blocks/create-client.tsx
diff --git a/src/components/ecommerce/manage/blocks/create-default-client.tsx b/src/app/(dashboard)/ecommerce/manage/_components/blocks/create-default-client.tsx
similarity index 100%
rename from src/components/ecommerce/manage/blocks/create-default-client.tsx
rename to src/app/(dashboard)/ecommerce/manage/_components/blocks/create-default-client.tsx
diff --git a/src/components/ecommerce/manage/blocks/delete-client.tsx b/src/app/(dashboard)/ecommerce/manage/_components/blocks/delete-client.tsx
similarity index 100%
rename from src/components/ecommerce/manage/blocks/delete-client.tsx
rename to src/app/(dashboard)/ecommerce/manage/_components/blocks/delete-client.tsx
diff --git a/src/components/ecommerce/manage/blocks/edit-client.tsx b/src/app/(dashboard)/ecommerce/manage/_components/blocks/edit-client.tsx
similarity index 100%
rename from src/components/ecommerce/manage/blocks/edit-client.tsx
rename to src/app/(dashboard)/ecommerce/manage/_components/blocks/edit-client.tsx
diff --git a/src/components/ecommerce/manage/blocks/types.ts b/src/app/(dashboard)/ecommerce/manage/_components/blocks/types.ts
similarity index 100%
rename from src/components/ecommerce/manage/blocks/types.ts
rename to src/app/(dashboard)/ecommerce/manage/_components/blocks/types.ts
diff --git a/src/components/ecommerce/manage/index.tsx b/src/app/(dashboard)/ecommerce/manage/_components/index.tsx
similarity index 100%
rename from src/components/ecommerce/manage/index.tsx
rename to src/app/(dashboard)/ecommerce/manage/_components/index.tsx
diff --git a/src/app/(dashboard)/ecommerce/manage/page.tsx b/src/app/(dashboard)/ecommerce/manage/page.tsx
new file mode 100644
index 00000000..7edaa911
--- /dev/null
+++ b/src/app/(dashboard)/ecommerce/manage/page.tsx
@@ -0,0 +1,18 @@
+import { PageDescription, PageTitle } from "@/components/page-elements";
+import { requireAuth } from "@/lib/auth";
+import { api } from "@/trpc/server";
+import { EcommerceManage } from "./_components/index";
+
+export default async function ManagePage() {
+ await requireAuth();
+
+ const ecommerceClients = await api.ecommerce.getAll.query();
+
+ return (
+ <>
+ Ecommerce Management
+ Manage your Ecommerce clients
+
+ >
+ );
+}
diff --git a/src/app/ecommerce/page.tsx b/src/app/(dashboard)/ecommerce/page.tsx
similarity index 100%
rename from src/app/ecommerce/page.tsx
rename to src/app/(dashboard)/ecommerce/page.tsx
diff --git a/src/components/ecommerce/sales/blocks/client-payments-table.tsx b/src/app/(dashboard)/ecommerce/sales/_components/blocks/client-payments-table.tsx
similarity index 100%
rename from src/components/ecommerce/sales/blocks/client-payments-table.tsx
rename to src/app/(dashboard)/ecommerce/sales/_components/blocks/client-payments-table.tsx
diff --git a/src/components/ecommerce/sales/index.tsx b/src/app/(dashboard)/ecommerce/sales/_components/index.tsx
similarity index 70%
rename from src/components/ecommerce/sales/index.tsx
rename to src/app/(dashboard)/ecommerce/sales/_components/index.tsx
index 78ea793c..888f8696 100644
--- a/src/components/ecommerce/sales/index.tsx
+++ b/src/app/(dashboard)/ecommerce/sales/_components/index.tsx
@@ -27,15 +27,5 @@ export function EcommerceSales({ initialClientPayments }: EcommerceSalesProps) {
);
}
- return (
-
-
-
Client Payments
-
- View all payments received through your ecommerce integrations
-
-
-
-
- );
+ return ;
}
diff --git a/src/app/(dashboard)/ecommerce/sales/page.tsx b/src/app/(dashboard)/ecommerce/sales/page.tsx
new file mode 100644
index 00000000..aa87c276
--- /dev/null
+++ b/src/app/(dashboard)/ecommerce/sales/page.tsx
@@ -0,0 +1,18 @@
+import { PageDescription, PageTitle } from "@/components/page-elements";
+import { requireAuth } from "@/lib/auth";
+import { api } from "@/trpc/server";
+import { EcommerceSales } from "./_components/index";
+
+export default async function SalesPage() {
+ await requireAuth();
+
+ const clientPayments = await api.ecommerce.getAllClientPayments.query();
+
+ return (
+ <>
+ Ecommerce Sales
+ View all sales made by your clients
+
+ >
+ );
+}
diff --git a/src/app/(dashboard)/home/page.tsx b/src/app/(dashboard)/home/page.tsx
new file mode 100644
index 00000000..5e5ae65b
--- /dev/null
+++ b/src/app/(dashboard)/home/page.tsx
@@ -0,0 +1,162 @@
+import { Button } from "@/components/ui/button";
+import {
+ Card,
+ CardContent,
+ CardDescription,
+ CardHeader,
+ CardTitle,
+} from "@/components/ui/card";
+import { requireAuth } from "@/lib/auth";
+import {
+ DollarSign,
+ FileText,
+ Globe,
+ Plus,
+ Shield,
+ TrendingUp,
+ Zap,
+} from "lucide-react";
+import Link from "next/link";
+
+export default async function HomePage() {
+ await requireAuth();
+
+ return (
+
+
+
+ Welcome to Request Dashboard
+
+
+ Your journey to integrating seamless crypto payments starts here. This
+ is a white-label application built on the power and reliability of
+ Request Network.
+
+
+
+
+
+
+
+
+
+
+
+ Powered by Request Network
+
+
+ A proven payment infrastructure trusted by thousands of
+ businesses.
+
+
+
+
+
+
+
+
+
2017
+
Operating Since
+
+
+
+
+
+
1B+
+
+ Payments Processed
+
+
+
+
+
+
+
$30M
+
Monthly Volume
+
+
+
+
+
+
20K
+
+ Transactions/Month
+
+
+
+
+
+
+ {/* Quick Actions */}
+
+
+
+
+
+ Create Invoice
+
+
+ Generate a new invoice for your clients
+
+
+
+
+
+
+
+
+
+
+
+ View Invoices
+
+
+ Manage and track all your invoices
+
+
+
+
+
+
+
+
+
+
+
+ Payments
+
+ Track payments and payouts
+
+
+
+
+
+
+
+ );
+}
diff --git a/src/app/i/[id]/helpers.ts b/src/app/(dashboard)/i/[id]/helpers.ts
similarity index 100%
rename from src/app/i/[id]/helpers.ts
rename to src/app/(dashboard)/i/[id]/helpers.ts
diff --git a/src/app/(dashboard)/i/[id]/page.tsx b/src/app/(dashboard)/i/[id]/page.tsx
new file mode 100644
index 00000000..db1638ee
--- /dev/null
+++ b/src/app/(dashboard)/i/[id]/page.tsx
@@ -0,0 +1,56 @@
+import { InvoiceCreator } from "@/components/invoice/invoice-creator";
+import { PageTitle } from "@/components/page-elements";
+import { requireAuth } from "@/lib/auth";
+import { getInvoiceCount } from "@/lib/helpers/invoice";
+import type { Metadata } from "next";
+import { notFound, redirect } from "next/navigation";
+import { getInvoiceMeLink } from "./helpers";
+
+export const metadata: Metadata = {
+ title: "Invoice Me | EasyInvoice",
+ description: "Create an invoice for a service provider",
+};
+
+export default async function InvoiceMePage({
+ params,
+}: {
+ params: { id: string };
+}) {
+ const user = await requireAuth();
+ const invoiceMeLink = await getInvoiceMeLink(params.id);
+
+ if (!invoiceMeLink) {
+ notFound();
+ }
+
+ if (user.id === invoiceMeLink.user.id) {
+ redirect("/home");
+ }
+
+ const invoiceCount = await getInvoiceCount(invoiceMeLink.user.id);
+
+ return (
+ <>
+
+ Create Invoice for {invoiceMeLink.label}
+
+
+ >
+ );
+}
diff --git a/src/components/payment-route.tsx b/src/app/(dashboard)/invoices/[ID]/_components/payment-route.tsx
similarity index 100%
rename from src/components/payment-route.tsx
rename to src/app/(dashboard)/invoices/[ID]/_components/payment-route.tsx
diff --git a/src/components/payment-section.tsx b/src/app/(dashboard)/invoices/[ID]/_components/payment-section.tsx
similarity index 99%
rename from src/components/payment-section.tsx
rename to src/app/(dashboard)/invoices/[ID]/_components/payment-section.tsx
index 441d77a1..b713c22f 100644
--- a/src/components/payment-section.tsx
+++ b/src/app/(dashboard)/invoices/[ID]/_components/payment-section.tsx
@@ -1,6 +1,5 @@
"use client";
-import { PaymentRoute } from "@/components/payment-route";
import { Button } from "@/components/ui/button";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { Label } from "@/components/ui/label";
@@ -29,6 +28,7 @@ import {
} from "@/lib/invoice-status";
import { useEffect, useState } from "react";
import { toast } from "sonner";
+import { PaymentRoute } from "./payment-route";
type InvoiceStatus =
| "pending"
diff --git a/src/app/invoices/[ID]/helpers.ts b/src/app/(dashboard)/invoices/[ID]/helpers.ts
similarity index 100%
rename from src/app/invoices/[ID]/helpers.ts
rename to src/app/(dashboard)/invoices/[ID]/helpers.ts
diff --git a/src/app/(dashboard)/invoices/[ID]/page.tsx b/src/app/(dashboard)/invoices/[ID]/page.tsx
new file mode 100644
index 00000000..cbead46d
--- /dev/null
+++ b/src/app/(dashboard)/invoices/[ID]/page.tsx
@@ -0,0 +1,278 @@
+import { PageDescription, PageTitle } from "@/components/page-elements";
+import { Badge } from "@/components/ui/badge";
+import { Card, CardContent } from "@/components/ui/card";
+import { requireAuth } from "@/lib/auth";
+import { formatCurrencyLabel } from "@/lib/constants/currencies";
+import { formatDate } from "@/lib/date-utils";
+import { api } from "@/trpc/server";
+import { ArrowLeft } from "lucide-react";
+import type { Metadata } from "next";
+import Link from "next/link";
+import { notFound } from "next/navigation";
+import { PaymentSection } from "./_components/payment-section";
+import { getInvoice } from "./helpers";
+export const metadata: Metadata = {
+ title: "Invoice Payment | EasyInvoice",
+ description: "Process payment for your invoice",
+};
+
+type InvoiceItem = {
+ description: string;
+ quantity: number;
+ price: number;
+};
+
+export default async function PaymentPage({
+ params,
+}: {
+ params: { ID: string };
+}) {
+ await requireAuth();
+ const invoice = await getInvoice(params.ID);
+
+ if (!invoice) {
+ notFound();
+ }
+
+ const paymentDetailsData = invoice.paymentDetailsId
+ ? await api.compliance.getPaymentDetailsById.query(invoice.paymentDetailsId)
+ : null;
+
+ return (
+ <>
+