diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index a6f85d8..13668b9 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -37,7 +37,7 @@ jobs: echo "TURSO_AUTH_TOKEN is set: ${{ env.TURSO_AUTH_TOKEN != '' }}" echo "TURSO_DATABASE_URL is set: ${{ env.TURSO_DATABASE_URL != '' }}" echo "RESEND_API_KEY" is set ${{ env.RESEND_API_KEY != '' }} - echo + echo env: NEXT_PUBLIC_SITE_URL: ${{ secrets.NEXT_PUBLIC_SITE_URL }} NEXTAUTH_SECRET: ${{ secrets.NEXTAUTH_SECRET }} diff --git a/emails/user-registration-email-template.tsx b/emails/user-registration-email-template.tsx index 8c3de85..0a436ac 100644 --- a/emails/user-registration-email-template.tsx +++ b/emails/user-registration-email-template.tsx @@ -1,88 +1,95 @@ import { tedxsjecAssetsPrefix } from "@/lib/utils"; import { - Body, - Button, - Container, - Head, - Heading, - Hr, - Html, - Img, - Preview, - Section, - Text, + Body, + Button, + Container, + Head, + Heading, + Hr, + Html, + Img, + Preview, + Section, + Text, } from "@react-email/components"; import { Tailwind } from "@react-email/tailwind"; interface TedxRegistrationEmailProps { - name?: string; - registrationLink: string; + name?: string; + registrationLink: string; } -export const TedxRegistrationEmail = ({ name, registrationLink }: TedxRegistrationEmailProps) => { - const previewText = `TEDxSJEC Talk Registration Successful!`; +export const TedxRegistrationEmail = ({ + name, + registrationLink, +}: TedxRegistrationEmailProps) => { + const previewText = `TEDxSJEC Talk Registration Successful!`; - return ( - - - {previewText} - - - - {/* Logo Section */} -
- TEDxSJEC Logo -
- {/* Heading Section */} -
- - TEDxSJEC Talk Registration Confirmed! - -
- - Dear {name ?? "Participant"}, - - - We are excited to confirm your registration for TEDxSJEC Talk.
- You are all set to join us for an inspiring day filled with ideas worth sharing. - Please bring this email on the event day for a smooth entry process. -
- {/* QR Code Section */} -
- - Below is your unique QR code for registration. Kindly keep it accessible on - event day for quick check-in: - - QR Code -
- - We look forward to seeing you at TEDxSJEC!
-
-
- - Thanks & Regards,
TEDxSJEC Team
- For any queries, feel free to contact us at: tedxsjec@sjec.ac.in -
-
- -  |  - -  |  - -
-
- -
- - ); + return ( + + + {previewText} + + + + {/* Logo Section */} +
+ TEDxSJEC Logo +
+ {/* Heading Section */} +
+ + TEDxSJEC Talk Registration Confirmed! + +
+ + Dear {name ?? "Participant"}, + + + We are excited to confirm your registration for TEDxSJEC Talk.{" "} +
+ You are all set to join us for an inspiring day filled with ideas + worth sharing. Please bring this email on the event day for a + smooth entry process. +
+ {/* QR Code Section */} +
+ + Below is your unique QR code for registration. Kindly keep it + accessible on event day for quick check-in: + + QR Code +
+ + We look forward to seeing you at TEDxSJEC!
+
+
+ + Thanks & Regards,
TEDxSJEC Team
+ For any queries, feel free to contact us at: tedxsjec@sjec.ac.in +
+
+ +  |  + +  |  + +
+
+ +
+ + ); }; export default TedxRegistrationEmail; diff --git a/src/app/actions/invalidate-coupon.ts b/src/app/actions/invalidate-coupon.ts index d51ab6b..8eb1672 100644 --- a/src/app/actions/invalidate-coupon.ts +++ b/src/app/actions/invalidate-coupon.ts @@ -2,19 +2,19 @@ import prisma from "@/server/db"; import { type Session as NextAuthSession } from "next-auth"; -export async function invalidateCouponCode(couponCode: string, session: NextAuthSession) { - console.log("coupon code = "+couponCode , "session = " + session.user.id) - if (!couponCode) return; - return await prisma.referral.update({ - where:{ - code:couponCode, - }, - data:{ - isUsed:true, - usedById:session.user.id - } - - }) - - +export async function invalidateCouponCode( + couponCode: string, + session: NextAuthSession, +) { + console.log("coupon code = " + couponCode, "session = " + session.user.id); + if (!couponCode) return; + return await prisma.referral.update({ + where: { + code: couponCode, + }, + data: { + isUsed: true, + usedById: session.user.id, + }, + }); } diff --git a/src/app/actions/submit-form.ts b/src/app/actions/submit-form.ts index 60dc64a..3d19454 100644 --- a/src/app/actions/submit-form.ts +++ b/src/app/actions/submit-form.ts @@ -5,24 +5,24 @@ import prisma from "@/server/db"; import { FormDataInterface } from "@/types"; export async function submitForm(data: FormDataInterface, amount: number) { - const session = await getServerSideSession(); - if (!session) { - return; - } + const session = await getServerSideSession(); + if (!session) { + return; + } - return await prisma.form.create({ - data: { - name: data.name, - usn: data.usn, - email: data.email, - foodPreference:data.foodPreference, - contact: data.phone, - designation: data.designation, - paidAmount: amount, - photo: data.photo, - collegeIdCard: data.idCard, - createdById: session.user.id, - entityName: data.entityName, - }, - }); + return await prisma.form.create({ + data: { + name: data.name, + usn: data.usn, + email: data.email, + foodPreference: data.foodPreference, + contact: data.phone, + designation: data.designation, + paidAmount: amount, + photo: data.photo, + collegeIdCard: data.idCard, + createdById: session.user.id, + entityName: data.entityName, + }, + }); } diff --git a/src/app/admin/layout.tsx b/src/app/admin/layout.tsx index ff9d814..27062f5 100644 --- a/src/app/admin/layout.tsx +++ b/src/app/admin/layout.tsx @@ -10,32 +10,42 @@ import { useSession } from "next-auth/react"; const inter = Inter({ subsets: ["latin"] }); export default function RootLayout({ - children, + children, }: Readonly<{ - children: React.ReactNode; + children: React.ReactNode; }>) { - const { data: session } = useSession({ - required: true, - }); + const { data: session } = useSession({ + required: true, + }); - if (!session) { - return
Unauthorized
; - } - - if (session.user.role !== "ADMIN") { - return
Forbidden
; - } + if (!session) { + return ( +
+ Unauthorized +
+ ); + } + if (session.user.role !== "ADMIN") { return ( - - - -
- -
{children}
-
-
- - +
+ Forbidden +
); + } + + return ( + + + +
+ +
+ {children} +
+
+
+ + + ); } diff --git a/src/app/admin/razorpay/[id]/page.tsx b/src/app/admin/razorpay/[id]/page.tsx index 5e05abc..d9197d1 100644 --- a/src/app/admin/razorpay/[id]/page.tsx +++ b/src/app/admin/razorpay/[id]/page.tsx @@ -1,177 +1,190 @@ "use client"; import { Button } from "@/components/ui/button"; -import { Card, CardContent, CardFooter, CardHeader, CardTitle } from "@/components/ui/card"; +import { + Card, + CardContent, + CardFooter, + CardHeader, + CardTitle, +} from "@/components/ui/card"; import { Input } from "@/components/ui/input"; import { Label } from "@radix-ui/react-label"; import React, { useEffect, useState } from "react"; import { toast } from "sonner"; export interface Root { - id: string; - entity: string; - amount: number; - currency: string; - status: string; - order_id: string; - invoice_id: any; - international: boolean; - method: string; - amount_refunded: number; - refund_status: any; - captured: boolean; - description: string; - card_id: any; - bank: any; - wallet: any; - vpa: string; - email: string; - contact: string; - notes: Notes; - fee: number; - tax: number; - error_code: any; - error_description: any; - error_source: any; - error_step: any; - error_reason: any; - acquirer_data: AcquirerData; - created_at: number; - upi: Upi; + id: string; + entity: string; + amount: number; + currency: string; + status: string; + order_id: string; + invoice_id: any; + international: boolean; + method: string; + amount_refunded: number; + refund_status: any; + captured: boolean; + description: string; + card_id: any; + bank: any; + wallet: any; + vpa: string; + email: string; + contact: string; + notes: Notes; + fee: number; + tax: number; + error_code: any; + error_description: any; + error_source: any; + error_step: any; + error_reason: any; + acquirer_data: AcquirerData; + created_at: number; + upi: Upi; } export interface AcquirerData { - rrn: string; - upi_transaction_id: string; + rrn: string; + upi_transaction_id: string; } export interface Upi { - vpa: string; + vpa: string; } export interface Notes { - customerName: string; - customerEmail: string; - customerContact: string; + customerName: string; + customerEmail: string; + customerContact: string; } function FetchRazorpayPaymentData({ params }: { params: { id: string } }) { - const { id } = params; - const [paymentData, setPaymentData] = useState(null); - const [loading, setLoading] = useState(true); - const [loadingForButton, setLoadingForButton] = useState(false); + const { id } = params; + const [paymentData, setPaymentData] = useState(null); + const [loading, setLoading] = useState(true); + const [loadingForButton, setLoadingForButton] = useState(false); - async function sendEmail(paymentId: string) { - setLoadingForButton(true); - try { - const response = await fetch(`/api/send-email/${paymentId}`, { - method: "POST", - }); + async function sendEmail(paymentId: string) { + setLoadingForButton(true); + try { + const response = await fetch(`/api/send-email/${paymentId}`, { + method: "POST", + }); - if (response.status === 200) { - toast.success("Email sent successfully", { - description: "An email has been sent to the customer", - }); - } else { - toast.error("Error", { - description: "An error occurred while sending the email", - }); - } - } catch (error) { - toast.error("Error", { - description: "An error occurred while sending the email", - }); - } finally { - // Ensure the button is enabled again after the operation - setLoadingForButton(false); - } + if (response.status === 200) { + toast.success("Email sent successfully", { + description: "An email has been sent to the customer", + }); + } else { + toast.error("Error", { + description: "An error occurred while sending the email", + }); + } + } catch (error) { + toast.error("Error", { + description: "An error occurred while sending the email", + }); + } finally { + // Ensure the button is enabled again after the operation + setLoadingForButton(false); } + } - useEffect(() => { - const fetchData = async () => { - try { - const res = await fetch(`/api/verify-order/${id}`); - const data = await res.json(); - setPaymentData(data); - } catch (error) { - console.error("Error fetching payment data:", error); - } finally { - setLoading(false); - } - }; - fetchData(); - }, [id]); + useEffect(() => { + const fetchData = async () => { + try { + const res = await fetch(`/api/verify-order/${id}`); + const data = await res.json(); + setPaymentData(data); + } catch (error) { + console.error("Error fetching payment data:", error); + } finally { + setLoading(false); + } + }; + fetchData(); + }, [id]); - if (loading) { - return ( -
-

Loading...

-
- ); - } - - if (!paymentData) { - return ( -
-

No payment data found.

-
- ); - } + if (loading) { + return ( +
+

Loading...

+
+ ); + } + if (!paymentData) { return ( -
- - - - Payment Data of {paymentData.notes.customerName || "Unknown"} - - - - - - - - - - - - - -
+
+

No payment data found.

+
); + } + + return ( +
+ + + + Payment Data of {paymentData.notes.customerName || "Unknown"} + + + + + + + + + + + + + +
+ ); } export default FetchRazorpayPaymentData; diff --git a/src/app/admin/razorpay/page.tsx b/src/app/admin/razorpay/page.tsx index 0468bc8..afeab50 100644 --- a/src/app/admin/razorpay/page.tsx +++ b/src/app/admin/razorpay/page.tsx @@ -1,12 +1,12 @@ "use client"; import { - Form, - FormControl, - FormDescription, - FormField, - FormItem, - FormLabel, - FormMessage, + Form, + FormControl, + FormDescription, + FormField, + FormItem, + FormLabel, + FormMessage, } from "@/components/ui/form"; import { Input } from "@/components/ui/input"; import { zodResolver } from "@hookform/resolvers/zod"; @@ -16,59 +16,61 @@ import { useForm } from "react-hook-form"; import { z } from "zod"; const formSchema = z.object({ - razorpayPaymentId: z.string().nonempty("Payment ID is required"), + razorpayPaymentId: z.string().nonempty("Payment ID is required"), }); const FetchRazorpayPaymentData = () => { - const form = useForm>({ - resolver: zodResolver(formSchema), - }); - const router = useRouter() + const form = useForm>({ + resolver: zodResolver(formSchema), + }); + const router = useRouter(); - const onSubmit = async (data: z.infer) => { - router.push(`/admin/razorpay/${data.razorpayPaymentId}`) - }; + const onSubmit = async (data: z.infer) => { + router.push(`/admin/razorpay/${data.razorpayPaymentId}`); + }; - return ( -
-

- Search by Razorpay Payment ID -

-
- - ( - - Razorpay Payment ID: - - - - - Search for a payment by its Razorpay Payment ID - - - - )} - /> - - - -
- ); + return ( +
+

+ Search by Razorpay Payment ID +

+
+ + ( + + + Razorpay Payment ID: + + + + + + Search for a payment by its Razorpay Payment ID + + + + )} + /> + + + +
+ ); }; export default FetchRazorpayPaymentData; diff --git a/src/app/admin/verify/[id]/page.tsx b/src/app/admin/verify/[id]/page.tsx index 9f9441b..d1af8ba 100644 --- a/src/app/admin/verify/[id]/page.tsx +++ b/src/app/admin/verify/[id]/page.tsx @@ -1,22 +1,26 @@ /* eslint-disable react/no-unescaped-entities */ -import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card" -import { Button } from "@/components/ui/button" -import { AlertCircle, CheckCircle } from "lucide-react" -import Link from "next/link" -import React from "react" +import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; +import { Button } from "@/components/ui/button"; +import { AlertCircle, CheckCircle } from "lucide-react"; +import Link from "next/link"; +import React from "react"; async function getPaymentData(id: string) { // Simulate API call //Hardcoded the url because the other one just did'nt work - const response = await fetch(`http://localhost:3000/api/verify-order/${id}`) - const data = await response.json() + const response = await fetch(`http://localhost:3000/api/verify-order/${id}`); + const data = await response.json(); if (response.status === 200) { - return data + return data; } - return null + return null; } -export default async function PaymentPage({ params }: { params: { id: string } }) { - const paymentData = await getPaymentData(params.id) +export default async function PaymentPage({ + params, +}: { + params: { id: string }; +}) { + const paymentData = await getPaymentData(params.id); return (
@@ -29,7 +33,8 @@ export default async function PaymentPage({ params }: { params: { id: string } }

- Payment details for ID: {params.id} + Payment details for ID:{" "} + {params.id}

{paymentData ? ( <> @@ -45,7 +50,9 @@ export default async function PaymentPage({ params }: { params: { id: string } }

Amount Paid:

-

₹{(paymentData.amount / 100).toFixed(2)}

+

+ ₹{(paymentData.amount / 100).toFixed(2)} +

Paid By:

@@ -75,5 +82,5 @@ export default async function PaymentPage({ params }: { params: { id: string } }
- ) -} \ No newline at end of file + ); +} diff --git a/src/app/admin/verify/page.tsx b/src/app/admin/verify/page.tsx index 91e6567..ffa6f57 100644 --- a/src/app/admin/verify/page.tsx +++ b/src/app/admin/verify/page.tsx @@ -5,82 +5,85 @@ import { useRouter } from "next/navigation"; import { IDetectedBarcode } from "@yudiel/react-qr-scanner"; const QRCodeScanner = () => { - const [isMobile, setIsMobile] = useState(false); - const [error, setError] = useState(null); - const router = useRouter(); + const [isMobile, setIsMobile] = useState(false); + const [error, setError] = useState(null); + const router = useRouter(); - useEffect(() => { - // Check if the device is mobile - const checkMobile = () => { - const userAgent = navigator.userAgent || navigator.vendor || (window as any).opera; - return /android|webos|iphone|ipad|ipod|blackberry|iemobile|opera mini/i.test( - userAgent.toLowerCase() - ); - }; - setIsMobile(checkMobile()); - }, []); - - const handleScan = (detectedCodes: IDetectedBarcode[]) => { - if (detectedCodes.length > 0) { - const result = detectedCodes[0].rawValue; - if (result) { - try { - // Validate if the scanned result is a valid URL - const url = new URL(result); - - // if (!url.href.startsWith("https://tedxsjec")) { - // throw new Error("Invalid QR code . Please scan a valid QR code"); - // } - // Redirect to the scanned URL - router.push(url.toString()); - } catch { - setError("Invalid QR code. Please scan a valid URL."); - } - } - } + useEffect(() => { + // Check if the device is mobile + const checkMobile = () => { + const userAgent = + navigator.userAgent || navigator.vendor || (window as any).opera; + return /android|webos|iphone|ipad|ipod|blackberry|iemobile|opera mini/i.test( + userAgent.toLowerCase(), + ); }; + setIsMobile(checkMobile()); + }, []); + + const handleScan = (detectedCodes: IDetectedBarcode[]) => { + if (detectedCodes.length > 0) { + const result = detectedCodes[0].rawValue; + if (result) { + try { + // Validate if the scanned result is a valid URL + const url = new URL(result); - const handleError = (error: unknown) => { - if (error instanceof Error) { - setError("Error accessing camera: " + error.message); - } else { - setError("An unknown error occurred."); + // if (!url.href.startsWith("https://tedxsjec")) { + // throw new Error("Invalid QR code . Please scan a valid QR code"); + // } + // Redirect to the scanned URL + router.push(url.toString()); + } catch { + setError("Invalid QR code. Please scan a valid URL."); } - }; + } + } + }; - if (isMobile) { - return ( -
-
-

Error

-

- This feature is only available on mobile devices. Please access this page from your - smartphone or tablet. -

-
-
- ); + const handleError = (error: unknown) => { + if (error instanceof Error) { + setError("Error accessing camera: " + error.message); + } else { + setError("An unknown error occurred."); } + }; + if (isMobile) { return ( -
-
-

QR Code Scanner

- {error ? ( -

{error}

- ) : ( - - )} -

- Position the QR code within the frame to scan. -

-
+
+
+

+ Error +

+

+ This feature is only available on mobile devices. Please access this + page from your smartphone or tablet. +

+
); + } + + return ( +
+
+

QR Code Scanner

+ {error ? ( +

{error}

+ ) : ( + + )} +

+ Position the QR code within the frame to scan. +

+
+
+ ); }; export default QRCodeScanner; diff --git a/src/app/api/(verification)/verify-mail/route.ts b/src/app/api/(verification)/verify-mail/route.ts index 068cb8c..a75e73b 100644 --- a/src/app/api/(verification)/verify-mail/route.ts +++ b/src/app/api/(verification)/verify-mail/route.ts @@ -3,64 +3,64 @@ import getErrorMessage from "@/utils/getErrorMessage"; import { NextRequest, NextResponse } from "next/server"; export async function POST(req: NextRequest) { - const body = await req.json(); - console.log(body); - const { identifier, otp } = body; - if (!identifier || !otp) { - return NextResponse.json( - { message: "Identifier and OTP are required", status: 400 }, - { status: 400 } - ); - } - // try { - // await prisma.$transaction(async (tx) => { - // const request = await tx.verificationRequest.findFirst({ - // where: { - // identifier, - // otp, - // expires: { - // gte: new Date(), - // }, - // }, - // orderBy: { - // created_at: "desc", - // }, - // }); - // if (!request) { - // throw new Error("Verification failed: Invalid or expired OTP"); - // } - // await tx.form.updateMany({ - // where: { - // email: identifier, - // }, - // data: { - // emailVerified: true, - // }, - // }); - // await tx.verificationRequest.deleteMany({ - // where: { - // identifier, - // }, - // }); - // }); - + const body = await req.json(); + console.log(body); + const { identifier, otp } = body; + if (!identifier || !otp) { return NextResponse.json( - { - message: "OTP verified successfully back!", - status: 200, - }, - { status: 200 } + { message: "Identifier and OTP are required", status: 400 }, + { status: 400 }, ); - // catch (error: unknown) { - // const errorMessage = getErrorMessage(error); - // console.error("OTP verification failed:", errorMessage); - // return NextResponse.json( - // { message: errorMessage, status: 400 }, - // { status: 400 }, - // ); - // } + } + // try { + // await prisma.$transaction(async (tx) => { + // const request = await tx.verificationRequest.findFirst({ + // where: { + // identifier, + // otp, + // expires: { + // gte: new Date(), + // }, + // }, + // orderBy: { + // created_at: "desc", + // }, + // }); + // if (!request) { + // throw new Error("Verification failed: Invalid or expired OTP"); + // } + // await tx.form.updateMany({ + // where: { + // email: identifier, + // }, + // data: { + // emailVerified: true, + // }, + // }); + // await tx.verificationRequest.deleteMany({ + // where: { + // identifier, + // }, + // }); + // }); + + return NextResponse.json( + { + message: "OTP verified successfully back!", + status: 200, + }, + { status: 200 }, + ); + // catch (error: unknown) { + // const errorMessage = getErrorMessage(error); + // console.error("OTP verification failed:", errorMessage); + // return NextResponse.json( + // { message: errorMessage, status: 400 }, + // { status: 400 }, + // ); + // } } export async function GET() { - return NextResponse.json({ message: "Hello from the Send mail!" }); + return NextResponse.json({ message: "Hello from the Send mail!" }); } diff --git a/src/app/api/create-order/route.ts b/src/app/api/create-order/route.ts index 6d35e7e..1cbf024 100644 --- a/src/app/api/create-order/route.ts +++ b/src/app/api/create-order/route.ts @@ -2,31 +2,31 @@ import { NextRequest, NextResponse } from "next/server"; import { razorpay } from "@/lib/razorpay"; export async function POST(request: NextRequest) { - const { amount } = await request.json(); - try { - const order = await razorpay.orders.create({ - amount: amount * 100, - currency: "INR", - receipt: "receipt_" + Math.random().toString(36).substring(7), - }); + const { amount } = await request.json(); + try { + const order = await razorpay.orders.create({ + amount: amount * 100, + currency: "INR", + receipt: "receipt_" + Math.random().toString(36).substring(7), + }); - return NextResponse.json( - { - orderId: order.id, - }, - { - status: 200, - } - ); - } catch (error) { - console.log(error); - return NextResponse.json( - { - error: "Error creating order ", - }, - { - status: 500, - } - ); - } + return NextResponse.json( + { + orderId: order.id, + }, + { + status: 200, + }, + ); + } catch (error) { + console.log(error); + return NextResponse.json( + { + error: "Error creating order ", + }, + { + status: 500, + }, + ); + } } diff --git a/src/app/api/send-email/[paymentId]/route.ts b/src/app/api/send-email/[paymentId]/route.ts index 0f755d5..3f36a9b 100644 --- a/src/app/api/send-email/[paymentId]/route.ts +++ b/src/app/api/send-email/[paymentId]/route.ts @@ -5,56 +5,68 @@ import prisma from "@/server/db"; import { sendRegistrationEmail } from "@/lib/send-registration-email"; import { generatedSignature } from "@/lib/helper"; -export async function POST(request: NextRequest, context: { params: { paymentId: string } }) { - const session = await getServerSideSession(); - if (!session) { - return NextResponse.json({ message: "Unauthorized", isOk: false }, { status: 401 }); - } - if (session.user.role !== "ADMIN") { - return NextResponse.json({ message: "Forbidden", isOk: false }, { status: 403 }); - } +export async function POST( + request: NextRequest, + context: { params: { paymentId: string } }, +) { + const session = await getServerSideSession(); + if (!session) { + return NextResponse.json( + { message: "Unauthorized", isOk: false }, + { status: 401 }, + ); + } + if (session.user.role !== "ADMIN") { + return NextResponse.json( + { message: "Forbidden", isOk: false }, + { status: 403 }, + ); + } - const { paymentId } = context.params; - const payment = await razorpay.payments.fetch(paymentId); - const signature = generatedSignature(payment.order_id, payment.id); + const { paymentId } = context.params; + const payment = await razorpay.payments.fetch(paymentId); + const signature = generatedSignature(payment.order_id, payment.id); - const user = await prisma.user.findUnique({ - where: { - email: payment.email, - }, + const user = await prisma.user.findUnique({ + where: { + email: payment.email, + }, + }); + + const prismaPayment = prisma.payment.findUnique({ + where: { + razorpayPaymentId: payment.id, + }, + }); + try { + await sendRegistrationEmail({ + email: payment.email, + name: user?.name!, + registrationLink: `http://localhost:3000/admin/verify/${payment.id}`, }); + } catch (error) { + console.log(error); + } - const prismaPayment = prisma.payment.findUnique({ - where: { - razorpayPaymentId: payment.id, + if (!prismaPayment) { + await prisma.$transaction(async (prisma) => { + await prisma.payment.create({ + data: { + amount: parseFloat(payment.amount.toString()), + signature: signature, + razorpayPaymentId: payment.id, + orderCreationId: payment.order_id, + user: { + connect: { + email: session?.user.email!, + }, + }, }, + }); }); - try { - await sendRegistrationEmail({ - email: payment.email, - name: user?.name!, - registrationLink: `http://localhost:3000/admin/verify/${payment.id}`, - }); - } catch (error) { - console.log(error); - } - - if (!prismaPayment) { - await prisma.$transaction(async (prisma) => { - await prisma.payment.create({ - data: { - amount: parseFloat(payment.amount.toString()), - signature: signature, - razorpayPaymentId: payment.id, - orderCreationId: payment.order_id, - user: { - connect: { - email: session?.user.email!, - }, - }, - }, - }); - }); - } - return NextResponse.json({ message: "Payment verified successfully", isOk: true }, { status: 200 }); + } + return NextResponse.json( + { message: "Payment verified successfully", isOk: true }, + { status: 200 }, + ); } diff --git a/src/app/api/uploadthing/core.ts b/src/app/api/uploadthing/core.ts index 94b6f92..cb1c652 100644 --- a/src/app/api/uploadthing/core.ts +++ b/src/app/api/uploadthing/core.ts @@ -5,29 +5,29 @@ import { UploadThingError } from "uploadthing/server"; const f = createUploadthing(); const auth = async (req: Request) => { - const session = await getServerSession(); + const session = await getServerSession(); - return session?.user; + return session?.user; }; export const ourFileRouter = { - imageUploader: f({ image: { maxFileSize: "4MB", maxFileCount: 2 } }) - .middleware(async ({ req }) => { - console.log("Middleware for imageUploader", req.url); - const user = await auth(req); + imageUploader: f({ image: { maxFileSize: "4MB", maxFileCount: 2 } }) + .middleware(async ({ req }) => { + console.log("Middleware for imageUploader", req.url); + const user = await auth(req); - if (!user) throw new UploadThingError("Unauthorized"); + if (!user) throw new UploadThingError("Unauthorized"); - return { userId: user.id }; - }) - .onUploadComplete(async ({ metadata, file }) => { - // console.log("Upload complete for userId:", metadata.userId); + return { userId: user.id }; + }) + .onUploadComplete(async ({ metadata, file }) => { + // console.log("Upload complete for userId:", metadata.userId); - // console.log("file url", file.url); + // console.log("file url", file.url); - // !!! Whatever is returned here is sent to the clientside `onClientUploadComplete` callback - return { uploadedBy: metadata.userId }; - }), + // !!! Whatever is returned here is sent to the clientside `onClientUploadComplete` callback + return { uploadedBy: metadata.userId }; + }), } satisfies FileRouter; export type OurFileRouter = typeof ourFileRouter; diff --git a/src/app/api/users/payment/route.ts b/src/app/api/users/payment/route.ts index 5f35aed..9099f5e 100644 --- a/src/app/api/users/payment/route.ts +++ b/src/app/api/users/payment/route.ts @@ -3,52 +3,55 @@ import prisma from "@/server/db"; import { NextRequest, NextResponse } from "next/server"; export async function GET(request: NextRequest) { - const { searchParams } = new URL(request.url); - try { - const page = Math.max(1, parseInt(searchParams.get("page") || "1", 10)); - const search = searchParams.get("search") || ""; - const limit = 10; + const { searchParams } = new URL(request.url); + try { + const page = Math.max(1, parseInt(searchParams.get("page") || "1", 10)); + const search = searchParams.get("search") || ""; + const limit = 10; - const [users, totalCount] = await Promise.all([ - prisma.payment.findMany({ - skip: (page - 1) * limit, - take: limit, - where: { - razorpayPaymentId: { - contains: search, - }, - }, - include: { - user: { - select: { - name: true, - email: true, - }, - }, - }, - }), - prisma.payment.count({ - where: { - razorpayPaymentId: { - contains: search, - }, - }, - }), - ]); + const [users, totalCount] = await Promise.all([ + prisma.payment.findMany({ + skip: (page - 1) * limit, + take: limit, + where: { + razorpayPaymentId: { + contains: search, + }, + }, + include: { + user: { + select: { + name: true, + email: true, + }, + }, + }, + }), + prisma.payment.count({ + where: { + razorpayPaymentId: { + contains: search, + }, + }, + }), + ]); - const totalPages = Math.ceil(totalCount / limit); + const totalPages = Math.ceil(totalCount / limit); - return NextResponse.json({ - users, - pagination: { - currentPage: page, - totalCount, - totalPages, - limit, - }, - }); - } catch (error) { - console.error("Error fetching payment details:", error); - return NextResponse.json({ error: "Failed to fetch data" }, { status: 500 }); - } + return NextResponse.json({ + users, + pagination: { + currentPage: page, + totalCount, + totalPages, + limit, + }, + }); + } catch (error) { + console.error("Error fetching payment details:", error); + return NextResponse.json( + { error: "Failed to fetch data" }, + { status: 500 }, + ); + } } diff --git a/src/app/api/users/route.ts b/src/app/api/users/route.ts index 6a742a9..d9b0026 100644 --- a/src/app/api/users/route.ts +++ b/src/app/api/users/route.ts @@ -2,45 +2,48 @@ import prisma from "@/server/db"; import { NextResponse } from "next/server"; export async function GET(req: Request) { - const { searchParams } = new URL(req.url); - try { - const page = Math.max(1, parseInt(searchParams.get("page") || "1", 10)); - const search = searchParams.get("search") || ""; - const limit = 10; + const { searchParams } = new URL(req.url); + try { + const page = Math.max(1, parseInt(searchParams.get("page") || "1", 10)); + const search = searchParams.get("search") || ""; + const limit = 10; - const [users, totalCount] = await Promise.all([ - prisma.user.findMany({ - skip: (page - 1) * limit, - take: limit, - where: { - name: { - contains: search, - }, - }, - }), - prisma.user.count({ - // Get the total number of users for pagination - where: { - name: { - contains: search, - }, - }, - }), - ]); + const [users, totalCount] = await Promise.all([ + prisma.user.findMany({ + skip: (page - 1) * limit, + take: limit, + where: { + name: { + contains: search, + }, + }, + }), + prisma.user.count({ + // Get the total number of users for pagination + where: { + name: { + contains: search, + }, + }, + }), + ]); - const totalPages = Math.ceil(totalCount / limit); + const totalPages = Math.ceil(totalCount / limit); - return NextResponse.json({ - users, - pagination: { - currentPage: page, - totalPages, - totalCount, - limit, - }, - }); - } catch (error) { - console.error("Failed to fetch users:", error); - return NextResponse.json({ message: "Failed to fetch users", status: 500 }, { status: 500 }); - } + return NextResponse.json({ + users, + pagination: { + currentPage: page, + totalPages, + totalCount, + limit, + }, + }); + } catch (error) { + console.error("Failed to fetch users:", error); + return NextResponse.json( + { message: "Failed to fetch users", status: 500 }, + { status: 500 }, + ); + } } diff --git a/src/app/api/verify-order/[id]/route.ts b/src/app/api/verify-order/[id]/route.ts index 5e8d026..569214e 100644 --- a/src/app/api/verify-order/[id]/route.ts +++ b/src/app/api/verify-order/[id]/route.ts @@ -4,21 +4,24 @@ import { getServerSession } from "next-auth"; import { getToken } from "next-auth/jwt"; import { NextRequest, NextResponse } from "next/server"; -export async function GET(request: NextRequest, context: { params: { id: string } }) { - // const session = await getToken({ req: request, secret: process.env.NEXTAUTH_SECRET }); - // if (!session) { - // return NextResponse.json({ message: "Unauthorized", isOk: false }, { status: 401 }); - // } - // if (session.role !== "ADMIN") { - // return NextResponse.json({ message: "Forbidden", isOk: false }, { status: 403 }); - // } +export async function GET( + request: NextRequest, + context: { params: { id: string } }, +) { + // const session = await getToken({ req: request, secret: process.env.NEXTAUTH_SECRET }); + // if (!session) { + // return NextResponse.json({ message: "Unauthorized", isOk: false }, { status: 401 }); + // } + // if (session.role !== "ADMIN") { + // return NextResponse.json({ message: "Forbidden", isOk: false }, { status: 403 }); + // } - const { id } = context.params; - try { - const paymentData = await razorpay.payments.fetch(id); - return NextResponse.json(paymentData, { status: 200 }); - } catch (error) { - console.error("Error fetching payment data:", error); - return NextResponse.json({ error: "Payment not found" }, { status: 404 }); - } + const { id } = context.params; + try { + const paymentData = await razorpay.payments.fetch(id); + return NextResponse.json(paymentData, { status: 200 }); + } catch (error) { + console.error("Error fetching payment data:", error); + return NextResponse.json({ error: "Payment not found" }, { status: 404 }); + } } diff --git a/src/app/api/verify-order/route.ts b/src/app/api/verify-order/route.ts index 57e5014..dcce6d3 100644 --- a/src/app/api/verify-order/route.ts +++ b/src/app/api/verify-order/route.ts @@ -4,45 +4,53 @@ import prisma from "@/server/db"; import { sendRegistrationEmail } from "@/lib/send-registration-email"; import { generatedSignature } from "@/lib/helper"; - - export async function POST(request: NextRequest) { - const { orderId, razorpayPaymentId, razorpaySignature, amount } = await request.json(); - const session = await getServerSideSession(); - if (!session) { - return NextResponse.json({ message: "No session", isOk: false }, { status: 400 }); - } - const signature = generatedSignature(orderId, razorpayPaymentId); - if (signature !== razorpaySignature) { - return NextResponse.json({ message: "payment verification failed", isOk: false }, { status: 400 }); - } - if (signature === razorpaySignature) { - const user = await prisma.user.findUnique({ - where: { - email: session.user?.email!, - }, - }); + const { orderId, razorpayPaymentId, razorpaySignature, amount } = + await request.json(); + const session = await getServerSideSession(); + if (!session) { + return NextResponse.json( + { message: "No session", isOk: false }, + { status: 400 }, + ); + } + const signature = generatedSignature(orderId, razorpayPaymentId); + if (signature !== razorpaySignature) { + return NextResponse.json( + { message: "payment verification failed", isOk: false }, + { status: 400 }, + ); + } + if (signature === razorpaySignature) { + const user = await prisma.user.findUnique({ + where: { + email: session.user?.email!, + }, + }); - try { - await sendRegistrationEmail({ - email: session.user?.email!, - name: session.user?.name!, - registrationLink: `http://localhost:3000/admin/verify/${razorpayPaymentId}`, - }); - } catch (error) { - console.log(error); - } - await prisma.$transaction(async (prisma) => { - await prisma.payment.create({ - data: { - amount: amount, - orderCreationId: orderId, - razorpayPaymentId: razorpayPaymentId, - signature: razorpaySignature, - user: { connect: { email: session.user?.email! } }, - }, - }); - }); - return NextResponse.json({ message: "payment verified successfully", isOk: true }, { status: 200 }); + try { + await sendRegistrationEmail({ + email: session.user?.email!, + name: session.user?.name!, + registrationLink: `http://localhost:3000/admin/verify/${razorpayPaymentId}`, + }); + } catch (error) { + console.log(error); } + await prisma.$transaction(async (prisma) => { + await prisma.payment.create({ + data: { + amount: amount, + orderCreationId: orderId, + razorpayPaymentId: razorpayPaymentId, + signature: razorpaySignature, + user: { connect: { email: session.user?.email! } }, + }, + }); + }); + return NextResponse.json( + { message: "payment verified successfully", isOk: true }, + { status: 200 }, + ); + } } diff --git a/src/app/auth/signin/page.tsx b/src/app/auth/signin/page.tsx index 37c19a9..a978761 100644 --- a/src/app/auth/signin/page.tsx +++ b/src/app/auth/signin/page.tsx @@ -2,9 +2,9 @@ import { Suspense } from "react"; import Signin from "./signin-page"; export default function AuthPage() { - return ( - Loading...
}> - - - ); + return ( + Loading...
}> + + + ); } diff --git a/src/app/auth/signin/signin-page.tsx b/src/app/auth/signin/signin-page.tsx index a68edc8..6ac9886 100644 --- a/src/app/auth/signin/signin-page.tsx +++ b/src/app/auth/signin/signin-page.tsx @@ -1,46 +1,48 @@ -"use client" - -import {useSearchParams,useRouter} from "next/navigation" - -import {signIn,useSession} from "next-auth/react" - -import {useState,useEffect} from "react" - -import {tailChase} from "ldrs" - - -export default function SignIn(){ - const router = useRouter(); - const {status} = useSession(); - const searchParams = useSearchParams(); - const [loading, setLoading] = useState(false); - const callbackUrl = searchParams.get("callbackUrl") || "/"; - - - useEffect(() => { - if (typeof window !== "undefined") { - tailChase.register(); - } - if (status === "unauthenticated") { - setLoading(true); - signIn("google").catch((error) => { - console.error("Sign in failed:", error); - setLoading(false); - }); - } else if (status === "authenticated") { - router.push(callbackUrl); - } - }, [status, router, callbackUrl]); - - return ( -
- {loading ? ( -
- -
- ) : ( -

Redirecting...

- )} +"use client"; + +import { useSearchParams, useRouter } from "next/navigation"; + +import { signIn, useSession } from "next-auth/react"; + +import { useState, useEffect } from "react"; + +import { tailChase } from "ldrs"; + +export default function SignIn() { + const router = useRouter(); + const { status } = useSession(); + const searchParams = useSearchParams(); + const [loading, setLoading] = useState(false); + const callbackUrl = searchParams.get("callbackUrl") || "/"; + + useEffect(() => { + if (typeof window !== "undefined") { + tailChase.register(); + } + if (status === "unauthenticated") { + setLoading(true); + signIn("google").catch((error) => { + console.error("Sign in failed:", error); + setLoading(false); + }); + } else if (status === "authenticated") { + router.push(callbackUrl); + } + }, [status, router, callbackUrl]); + + return ( +
+ {loading ? ( +
+
- ); + ) : ( +

Redirecting...

+ )} +
+ ); } diff --git a/src/app/auth/signout/page.tsx b/src/app/auth/signout/page.tsx index 055935a..684e85e 100644 --- a/src/app/auth/signout/page.tsx +++ b/src/app/auth/signout/page.tsx @@ -5,38 +5,42 @@ import { signOut, useSession } from "next-auth/react"; import { useEffect, useState } from "react"; import { tailChase } from "ldrs"; export default function Signin() { - const router = useRouter(); - const { status } = useSession(); - const [loading, setLoading] = useState(false); + const router = useRouter(); + const { status } = useSession(); + const [loading, setLoading] = useState(false); - useEffect(() => { - if (typeof window !== "undefined") { - tailChase.register(); - } - if (status === "authenticated") { - setLoading(true); - signOut() - .then(() => { - router.push("/"); - }) - .catch((error) => { - console.error("Sign out failed:", error); - setLoading(false); - }); - } else { - router.push("/"); - } - }, [status, router]); + useEffect(() => { + if (typeof window !== "undefined") { + tailChase.register(); + } + if (status === "authenticated") { + setLoading(true); + signOut() + .then(() => { + router.push("/"); + }) + .catch((error) => { + console.error("Sign out failed:", error); + setLoading(false); + }); + } else { + router.push("/"); + } + }, [status, router]); - return ( -
- {loading ? ( -
- -
- ) : ( -

Redirecting...

- )} + return ( +
+ {loading ? ( +
+
- ); + ) : ( +

Redirecting...

+ )} +
+ ); } diff --git a/src/app/layout.tsx b/src/app/layout.tsx index b37cc97..0e5ffb1 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -2,43 +2,52 @@ import Providers from "@/components/layout/Provider"; import type { Metadata } from "next"; import { Inter } from "next/font/google"; import "./globals.css"; -import { StarsCanvas } from "@/components/ui/stars"; +import TEDxStarsCanvas from "@/components/ui/stars"; import Nav from "@/components/widget/header"; import Script from "next/script"; -// import ScrollProgress from "@/components/ui/progressBar"; +import ScrollProgress from "@/components/ui/progressBar"; const inter = Inter({ subsets: ["latin"] }); - export const metadata: Metadata = { - title: "TEDxSJEC", - description: - "TEDxSJEC is an independently organized event bringing together innovators, thinkers, and visionaries from around the world. Our goal is to inspire change, provoke deep discussions, and foster creativity through groundbreaking ideas. Our goal is to inspire change, provoke deep discussions, and foster creativity through groundbreaking ideas.", + title: "TEDxSJEC", + description: + "TEDxSJEC is an independently organized event bringing together innovators, thinkers, and visionaries from around the world. Our goal is to inspire change, provoke deep discussions, and foster creativity through groundbreaking ideas. Our goal is to inspire change, provoke deep discussions, and foster creativity through groundbreaking ideas.", }; export default function RootLayout({ - children, + children, }: Readonly<{ - children: React.ReactNode; + children: React.ReactNode; }>) { - return ( - - - - - - - - - - -
-