From 36f22c0614eba151dd50ddee36b4e000c9971762 Mon Sep 17 00:00:00 2001 From: i701 Date: Mon, 9 Dec 2024 22:59:13 +0500 Subject: [PATCH] Enhance payment processing and user interaction features - Updated createPayment function to log payment data more clearly. - Introduced verifyPayment function for validating payments via an external API. - Enhanced DevicesToPay component to include user information and payment verification functionality. - Added formatDate utility for consistent date formatting across the application. - Updated Prisma schema to include account number for users. - Refactored layout and device cart components for improved user experience and responsiveness. --- actions/payment.ts | 47 +++++- app/(dashboard)/payments/[paymentId]/page.tsx | 16 +- app/favicon.ico | Bin 15406 -> 15406 bytes app/layout.tsx | 50 +++---- components/device-cart.tsx | 2 +- components/devices-to-pay.tsx | 139 +++++++++++++++--- lib/utils.ts | 12 ++ .../20241209164451_add/migration.sql | 2 + prisma/schema.prisma | 1 + 9 files changed, 218 insertions(+), 51 deletions(-) create mode 100644 prisma/migrations/20241209164451_add/migration.sql diff --git a/actions/payment.ts b/actions/payment.ts index e1f75f9..1ff1204 100644 --- a/actions/payment.ts +++ b/actions/payment.ts @@ -5,7 +5,7 @@ import type { PaymentType } from "@/lib/types"; import { revalidatePath } from "next/cache"; export async function createPayment(data: PaymentType) { - console.log("hi", data); + console.log("data", data); const payment = await prisma.payment.create({ data: { amount: data.amount, @@ -24,3 +24,48 @@ export async function createPayment(data: PaymentType) { revalidatePath("/devices"); return payment; } + +type VerifyPaymentType = { + paymentId?: string; + benefName: string; + accountNo?: string; + absAmount: string; + time: string; +}; + +export async function verifyPayment(data: VerifyPaymentType) { + console.log({ data }); + try { + const payment = await prisma.payment.findUnique({ + where: { + id: data.paymentId, + }, + }); + const response = await fetch( + "https://verifypaymentsapi.baraveli.dev/verify-payment", + { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify(data), + }, + ); + const json = await response.json(); + console.log(json); + if (json.success === true) { + await prisma.payment.update({ + where: { + id: payment?.id, + }, + data: { + paid: true, + }, + }); + } + revalidatePath("/payment[paymentId]"); + return json; + } catch (error) { + console.error(error); + } +} diff --git a/app/(dashboard)/payments/[paymentId]/page.tsx b/app/(dashboard)/payments/[paymentId]/page.tsx index 40ce820..075605c 100644 --- a/app/(dashboard)/payments/[paymentId]/page.tsx +++ b/app/(dashboard)/payments/[paymentId]/page.tsx @@ -1,11 +1,22 @@ import DevicesToPay from "@/components/devices-to-pay"; +import { auth } from "@/lib/auth"; import { hasSession } from "@/lib/auth-guard"; import prisma from "@/lib/db"; +import { headers } from "next/headers"; import React from "react"; - export default async function PaymentPage({ params, -}: { params: Promise<{ paymentId: string }> }) { +}: { + params: Promise<{ paymentId: string }>; +}) { + const session = await auth.api.getSession({ + headers: await headers() + }) + const user = await prisma.user.findUnique({ + where: { + id: session?.session.userId + } + }) const paymentId = (await params).paymentId; const payment = await prisma.payment.findUnique({ where: { @@ -28,6 +39,7 @@ export default async function PaymentPage({ className="pb-4 gap-4 flex sm:flex-row flex-col items-start justify-start" > diff --git a/app/favicon.ico b/app/favicon.ico index 86f721702aa8741da5932c8d00f4db7b3b326dbb..ff78cbf0b066289e2478238f392662c8529ad9dc 100644 GIT binary patch literal 15406 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 Zw42>xE+Te*SNN1Dan=0)$p5=7@Sig#DSZF{ diff --git a/app/layout.tsx b/app/layout.tsx index 54221f1..ccefdb5 100644 --- a/app/layout.tsx +++ b/app/layout.tsx @@ -8,37 +8,37 @@ import { Toaster } from "sonner"; import "./globals.css"; import QueryProvider from "@/components/query-provider"; const barlow = Barlow({ - subsets: ["latin"], - weight: ["100", "300", "400", "500", "600", "700", "800", "900"], - variable: "--font-barlow", + subsets: ["latin"], + weight: ["100", "300", "400", "500", "600", "700", "800", "900"], + variable: "--font-barlow", }); export const metadata: Metadata = { - title: "SAR Link Portal", - description: "Sarlink Portal", + title: "SAR Link Portal", + description: "Sarlink Portal", }; export default function RootLayout({ - children, + children, }: Readonly<{ - children: React.ReactNode; + children: React.ReactNode; }>) { - return ( - - - - - - - {children} - - - - - ); + return ( + + + + + + + {children} + + + + + ); } diff --git a/components/device-cart.tsx b/components/device-cart.tsx index 5249bea..4922536 100644 --- a/components/device-cart.tsx +++ b/components/device-cart.tsx @@ -59,7 +59,7 @@ export function DeviceCartDrawer({ } else { setMessage(""); } - setTotal(baseAmount + (devices.length - 1) * discountPercentage); + setTotal(baseAmount + ((devices.length + 1) - 1) * discountPercentage); }, [months, devices.length, baseAmount, discountPercentage]); if (pathname === "/payment") { diff --git a/components/devices-to-pay.tsx b/components/devices-to-pay.tsx index 6d1227b..53dfbe8 100644 --- a/components/devices-to-pay.tsx +++ b/components/devices-to-pay.tsx @@ -1,3 +1,5 @@ +'use client' +import { verifyPayment } from "@/actions/payment"; import { Table, TableBody, @@ -5,35 +7,50 @@ import { TableCell, TableFooter, TableRow, -} from "@/components/ui/table" -import type { BillFormula, Prisma } from "@prisma/client" -import React from 'react' - +} from "@/components/ui/table"; +import { formatDate } from "@/lib/utils"; +import type { BillFormula, Prisma, User } from "@prisma/client"; +import { Clipboard, ClipboardCheck, Loader2, Wallet } from "lucide-react"; +import { useState } from "react"; +import { toast } from "sonner"; +import { Button } from "./ui/button"; type PaymentWithDevices = Prisma.PaymentGetPayload<{ include: { - devices: true - } -}> + devices: true; + }; +}>; -export default function DevicesToPay({ billFormula, payment }: { billFormula?: BillFormula, payment?: PaymentWithDevices }) { - const devices = payment?.devices +export default function DevicesToPay({ + billFormula, + payment, + user +}: { billFormula?: BillFormula; payment?: PaymentWithDevices, user?: User }) { + const [verifying, setVerifying] = useState(false) + + const devices = payment?.devices; if (devices?.length === 0) { - return null + return null; } - const baseAmount = billFormula?.baseAmount ?? 100 - const discountPercentage = billFormula?.discountPercentage ?? 75 + const baseAmount = billFormula?.baseAmount ?? 100; + const discountPercentage = billFormula?.discountPercentage ?? 75; // 100+(n−1)×75 - const total = baseAmount + (devices?.length ?? 1 - 1) * discountPercentage + const total = baseAmount + (devices?.length ?? 1 - 1) * discountPercentage; + + + return ( -
-
-

- {!payment?.paid ? 'Devices to pay' : 'Devices Paid'} +
+
+

+ {!payment?.paid ? "Devices to pay" : "Devices Paid"}

{devices?.map((device) => ( -
+
{device.name}
@@ -44,9 +61,49 @@ export default function DevicesToPay({ billFormula, payment }: { billFormula?: B ))}
-
+
- Please send the following amount to the payment address + +
+

Please send the following amount to the payment address

+ + {payment?.paid ? ( + + ) : ( + + )} + +
+
Total Devices @@ -62,6 +119,44 @@ export default function DevicesToPay({ billFormula, payment }: { billFormula?: B
- - ) + ); +} + +function AccountInfomation({ + accountNo, + accName, +}: { + accountNo: string; + accName: string; +}) { + const [accNo, setAccNo] = useState(false) + return ( +
+
+ Account Information +
+
+
Account Name
+ {accName} +
+
+
+

Account No

+ {accountNo} +
+ +
+
+ ); } diff --git a/lib/utils.ts b/lib/utils.ts index ac680b3..e0d51a2 100644 --- a/lib/utils.ts +++ b/lib/utils.ts @@ -4,3 +4,15 @@ import { twMerge } from "tailwind-merge"; export function cn(...inputs: ClassValue[]) { return twMerge(clsx(inputs)); } + +export const formatDate = (date: Date): string => { + const pad = (num: number): string => num.toString().padStart(2, "0"); + + const year = date.getFullYear(); + const month = pad(date.getMonth() + 1); // Months are zero-based + const day = pad(date.getDate()); + const hours = pad(date.getHours()); + const minutes = pad(date.getMinutes() + 5); + + return `${year}-${month}-${day} ${hours}:${minutes}`; +}; diff --git a/prisma/migrations/20241209164451_add/migration.sql b/prisma/migrations/20241209164451_add/migration.sql new file mode 100644 index 0000000..299138a --- /dev/null +++ b/prisma/migrations/20241209164451_add/migration.sql @@ -0,0 +1,2 @@ +-- AlterTable +ALTER TABLE "user" ADD COLUMN "accNo" TEXT; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 6b731de..91199ad 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -20,6 +20,7 @@ model User { emailVerified Boolean @default(false) firstPaymentDone Boolean @default(false) verified Boolean @default(false) + accNo String? // island String? address String? id_card String? @unique