From 0e82f975633f3db0d50f7553c152da8ff39214b7 Mon Sep 17 00:00:00 2001 From: vyshnav Date: Wed, 13 Nov 2024 21:59:20 +0530 Subject: [PATCH 01/20] update the price details --- src/components/common/registration-form.tsx | 25 ++++++++++----------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/src/components/common/registration-form.tsx b/src/components/common/registration-form.tsx index c1a213d..55649f6 100644 --- a/src/components/common/registration-form.tsx +++ b/src/components/common/registration-form.tsx @@ -34,7 +34,7 @@ import { Label } from "@/components/ui/label"; import { getPrice } from "@/app/actions/get-price"; import { toast } from "sonner"; import getErrorMessage from "@/utils/getErrorMessage"; -import { basePrice, initialdiscount, sjecPrice } from "@/constants"; +import { basePrice, initialdiscount, sjecStudentPrice,sjecFacultyPrice } from "@/constants"; import { invalidateCouponCode } from "@/app/actions/invalidate-coupon"; import { useSession } from "next-auth/react"; import Script from "next/script"; @@ -44,7 +44,7 @@ import { PaymentLoading } from "../payment/payment-loading"; import { PaymentSuccessfulComponent } from "../payment/payment-successful"; import { RadioGroup, RadioGroupItem } from "../ui/radio-group"; import { FileUpload } from "../ui/file-upload"; -import { isSjecMember } from "@/lib/helper"; +import { getSjecMemberType } from "@/lib/helper"; import { FormDataInterface } from "@/types"; declare global { @@ -83,25 +83,23 @@ export default function RegistrationForm() { const [uploadedFiles, setUploadedFiles] = useState([]); const [isProcessing, setIsProcessing] = useState(false); const [success, setSuccess] = useState(false); - const [isSJECMember, setIsSJECMember] = useState(false); + const [sjecMemberType, setSjecMemberType] = useState<"student" | "faculty" | "unknown">("unknown"); const [pricing, setPricing] = useState({ basePrice: basePrice, discountAmount: initialdiscount, - finalPrice: isSJECMember ? sjecPrice : basePrice, // Updated to set sjecPrice if isSJECMember is true + finalPrice: basePrice, }); const { data: session } = useSession(); useEffect(() => { - setIsSJECMember(isSjecMember(session?.user.email!)); + setSjecMemberType(getSjecMemberType(session?.user.email!)); setPricing((prevPricing) => ({ ...prevPricing, - finalPrice: isSJECMember ? sjecPrice : basePrice, // Update finalPrice based on isSJECMember + finalPrice: sjecMemberType === "student" ? sjecStudentPrice : sjecMemberType === "faculty" ? sjecFacultyPrice : basePrice, })); - }, [session?.user.email, isSJECMember]); + }, [session?.user.email, sjecMemberType]); - if (isSJECMember) { - } const form = useForm({ resolver: zodResolver(baseSchema), @@ -151,7 +149,7 @@ export default function RegistrationForm() { }; const handlePayment = async () => { - setIsProcessing(true); + const couponCode = form.getValues("couponCode"); try { const response = await fetch("/api/create-order", { @@ -169,6 +167,7 @@ export default function RegistrationForm() { description: "Test Transaction", order_id: data.orderId, handler: async (response: any) => { + setIsProcessing(true); const resp = await fetch("/api/verify-order", { method: "POST", headers: { "Content-Type": "application/json" }, @@ -428,7 +427,7 @@ export default function RegistrationForm() { )} /> - {!isSJECMember && ( + {sjecMemberType === "unknown" && ( From 6ab506aaf7c987b92eb806edd01af8088bc09735 Mon Sep 17 00:00:00 2001 From: vyshnav Date: Wed, 13 Nov 2024 21:59:29 +0530 Subject: [PATCH 02/20] update price --- src/constants/index.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/constants/index.ts b/src/constants/index.ts index ba31293..da0c2da 100644 --- a/src/constants/index.ts +++ b/src/constants/index.ts @@ -1,3 +1,4 @@ export const basePrice = 1000; export const initialdiscount = 0; -export const sjecPrice = 800; +export const sjecStudentPrice = 750; +export const sjecFacultyPrice = 800; From 67f428397703b058e3fd7d51f97bb8b426e2a18f Mon Sep 17 00:00:00 2001 From: vyshnav Date: Wed, 13 Nov 2024 21:59:45 +0530 Subject: [PATCH 03/20] Refactor isSjecMember to getSjecMemberType for improved clarity and functionality --- src/lib/helper.ts | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/lib/helper.ts b/src/lib/helper.ts index f6953aa..fb1af3a 100644 --- a/src/lib/helper.ts +++ b/src/lib/helper.ts @@ -25,9 +25,11 @@ export const generatedSignature = ( return sig; }; -export const isSjecMember = (email: string) => { - if (email.endsWith("@sjec.ac.in")) { - return true; - } - return false; -}; + +export const getSjecMemberType = (email: string): "student" | "faculty" | "unknown" => { + if (email.endsWith("@sjec.ac.in")) { + // Check if the email starts with a number + return /^\d/.test(email) ? "student" : "faculty"; + } + return "unknown"; +}; \ No newline at end of file From 59bfdbe7342299f509ee308c1e11165f9f4c5c30 Mon Sep 17 00:00:00 2001 From: Joywin Bennis <107112207+joywin2003@users.noreply.github.com> Date: Thu, 14 Nov 2024 11:51:11 +0530 Subject: [PATCH 04/20] adding superscript X to tedx --- src/components/common/About.tsx | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/components/common/About.tsx b/src/components/common/About.tsx index 97ec72a..1bacb48 100644 --- a/src/components/common/About.tsx +++ b/src/components/common/About.tsx @@ -33,14 +33,17 @@ const AboutSection: React.FC = () => { transition={{ duration: 1, ease: "easeOut" }} >

- About TEDxSJEC + About TEDx + SJEC

- 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. + TEDx + SJEC 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.

{/* Decorative line */} From caa3ee0bc4023192b9ae2fe656d1554635810ea3 Mon Sep 17 00:00:00 2001 From: Joywin Bennis <107112207+joywin2003@users.noreply.github.com> Date: Thu, 14 Nov 2024 14:48:24 +0530 Subject: [PATCH 05/20] fix: remove legacy layout prop from image --- src/components/common/Footer.tsx | 2 +- src/components/navbar/nav-header.tsx | 2 +- src/components/widget/header.tsx | 2 +- src/components/widget/performers.tsx | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/components/common/Footer.tsx b/src/components/common/Footer.tsx index cc09320..7e5daf5 100644 --- a/src/components/common/Footer.tsx +++ b/src/components/common/Footer.tsx @@ -110,7 +110,7 @@ const Footer = (props: Props) => { height={150} width={150} alt="logo" - layout="fixed" + // layout="fixed" priority={true} className="hidden md:block" /> diff --git a/src/components/navbar/nav-header.tsx b/src/components/navbar/nav-header.tsx index 8855624..a3a90ea 100644 --- a/src/components/navbar/nav-header.tsx +++ b/src/components/navbar/nav-header.tsx @@ -34,7 +34,7 @@ const NavHeader: React.FC = ({ handleClick }) => { height={200} width={200} alt="logo" - layout="fixed" + // layout="fixed" priority={true} /> diff --git a/src/components/widget/header.tsx b/src/components/widget/header.tsx index fb9f323..b4da721 100644 --- a/src/components/widget/header.tsx +++ b/src/components/widget/header.tsx @@ -109,7 +109,7 @@ const Nav = () => { height={200} width={200} alt="logo" - layout="fixed" + // layout="fixed" priority={true} /> diff --git a/src/components/widget/performers.tsx b/src/components/widget/performers.tsx index 12bb0f8..cd25d88 100644 --- a/src/components/widget/performers.tsx +++ b/src/components/widget/performers.tsx @@ -156,7 +156,7 @@ export default function Component() { alt={`Performer section ${sectionIndex + 1}, slide ${imageIndex + 1} of ${ section.images.length }`} - className={`absolute inset-0 w-full h-full object-cover transition-opacity duration-1000 ${ + className={`absolute inset-0 w-full h-full object-cover transition-opacity duration-8000 ${ imageIndex === currentImageIndices[sectionIndex] ? "opacity-100" : "opacity-0" From 06ee3a6aa5a4cf92728ee6ae99345d028d281688 Mon Sep 17 00:00:00 2001 From: Joywin Bennis <107112207+joywin2003@users.noreply.github.com> Date: Thu, 14 Nov 2024 15:25:11 +0530 Subject: [PATCH 06/20] refactor: remove unused verification and email API routes; add SpringModal component --- src/app/api/(verification)/send-mail/route.ts | 68 ------ .../api/(verification)/verify-mail/route.ts | 66 ------ src/components/navbar/nav-header.tsx | 3 +- src/components/ui/cursor.js | 198 ------------------ .../ui/{SpringModal.tsx => spring-modal.tsx} | 0 5 files changed, 1 insertion(+), 334 deletions(-) delete mode 100644 src/app/api/(verification)/send-mail/route.ts delete mode 100644 src/app/api/(verification)/verify-mail/route.ts delete mode 100644 src/components/ui/cursor.js rename src/components/ui/{SpringModal.tsx => spring-modal.tsx} (100%) diff --git a/src/app/api/(verification)/send-mail/route.ts b/src/app/api/(verification)/send-mail/route.ts deleted file mode 100644 index e2a7fa5..0000000 --- a/src/app/api/(verification)/send-mail/route.ts +++ /dev/null @@ -1,68 +0,0 @@ -import { MailUsingResend } from "@/lib/resend-mailer"; -import prisma from "@/server/db"; -import getErrorMessage from "@/utils/getErrorMessage"; -import { emailSchema } from "@/utils/zod-schemas"; -import { NextRequest, NextResponse } from "next/server"; -import otpGenerator from "otp-generator"; -import { z } from "zod"; - -export async function POST(req: NextRequest) { - try { - const body = await req.json(); - const parsedBody = emailSchema.parse(body); - - // const otp = otpGenerator.generate(6, { - // upperCaseAlphabets: false, - // lowerCaseAlphabets: false, - // specialChars: false, - // }); - - // const expiresIn = 10; // OTP valid for 10 minutes - // const expiresAt = new Date(Date.now() + expiresIn * 60 * 1000); - - // await prisma.verificationRequest.create({ - // data: { - // identifier: parsedBody.email, - // otp, - // expires: expiresAt, - // }, - // }); - - // const mailResponse = await MailUsingResend({ - // email: parsedBody.email, - // name: parsedBody.name, - // OTP: otp, - // }); - - // const mailResponse1 = await addToQueue({ - // email: parsedBody.email, - // name: parsedBody.name, - // OTP: otp, - // }) - - return NextResponse.json({ - message: "Email sent successfully!", - // mailResponse, - }); - } catch (error: unknown) { - const errorMessage = getErrorMessage(error); - - if (error instanceof z.ZodError) { - return NextResponse.json( - { message: "Validation error", errors: errorMessage }, - { status: 400 }, - ); - } - - // Handle general server errors - return NextResponse.json( - { message: "Internal Server Error", errorMessage }, - { status: 500 }, - ); - } -} - -// Test endpoint -export async function GET() { - return NextResponse.json({ message: "Hello from the Send mail!" }); -} diff --git a/src/app/api/(verification)/verify-mail/route.ts b/src/app/api/(verification)/verify-mail/route.ts deleted file mode 100644 index a75e73b..0000000 --- a/src/app/api/(verification)/verify-mail/route.ts +++ /dev/null @@ -1,66 +0,0 @@ -import prisma from "@/server/db"; -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, - // }, - // }); - // }); - - 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!" }); -} diff --git a/src/components/navbar/nav-header.tsx b/src/components/navbar/nav-header.tsx index a3a90ea..ac26be4 100644 --- a/src/components/navbar/nav-header.tsx +++ b/src/components/navbar/nav-header.tsx @@ -1,9 +1,8 @@ -"use client"; +"use client";; import { tedxsjecAssetsPrefix } from "@/lib/utils"; import Image from "next/image"; import Link from "next/link"; import React, { useRef } from "react"; -import RegisterButton from "./register-button"; interface NavHeaderProps { handleClick: () => void; diff --git a/src/components/ui/cursor.js b/src/components/ui/cursor.js deleted file mode 100644 index 78af5b5..0000000 --- a/src/components/ui/cursor.js +++ /dev/null @@ -1,198 +0,0 @@ -import { useEffect } from "react"; - -const useCanvasCursor = () => { - function n(e) { - this.init(e || {}); - } - n.prototype = { - init: function (e) { - this.phase = e.phase || 0; - this.offset = e.offset || 0; - this.frequency = e.frequency || 0.001; - this.amplitude = e.amplitude || 1; - }, - update: function () { - return ( - (this.phase += this.frequency), - (e = this.offset + Math.sin(this.phase) * this.amplitude) - ); - }, - value: function () { - return e; - }, - }; - - function Line(e) { - this.init(e || {}); - } - - Line.prototype = { - init: function (e) { - this.spring = e.spring + 0.1 * Math.random() - 0.02; - this.friction = E.friction + 0.01 * Math.random() - 0.002; - this.nodes = []; - for (var t, n = 0; n < E.size; n++) { - t = new Node(); - t.x = pos.x; - t.y = pos.y; - this.nodes.push(t); - } - }, - update: function () { - var e = this.spring, - t = this.nodes[0]; - t.vx += (pos.x - t.x) * e; - t.vy += (pos.y - t.y) * e; - for (var n, i = 0, a = this.nodes.length; i < a; i++) - (t = this.nodes[i]), - 0 < i && - ((n = this.nodes[i - 1]), - (t.vx += (n.x - t.x) * e), - (t.vy += (n.y - t.y) * e), - (t.vx += n.vx * E.dampening), - (t.vy += n.vy * E.dampening)), - (t.vx *= this.friction), - (t.vy *= this.friction), - (t.x += t.vx), - (t.y += t.vy), - (e *= E.tension); - }, - draw: function () { - var e, - t, - n = this.nodes[0].x, - i = this.nodes[0].y; - ctx.beginPath(); - ctx.moveTo(n, i); - for (var a = 1, o = this.nodes.length - 2; a < o; a++) { - e = this.nodes[a]; - t = this.nodes[a + 1]; - n = 0.5 * (e.x + t.x); - i = 0.5 * (e.y + t.y); - ctx.quadraticCurveTo(e.x, e.y, n, i); - } - e = this.nodes[a]; - t = this.nodes[a + 1]; - ctx.quadraticCurveTo(e.x, e.y, t.x, t.y); - ctx.stroke(); - ctx.closePath(); - }, - }; - - function onMousemove(e) { - function o() { - lines = []; - for (var e = 0; e < E.trails; e++) - lines.push(new Line({ spring: 0.4 + (e / E.trails) * 0.025 })); - } - function c(e) { - e.touches - ? ((pos.x = e.touches[0].pageX), (pos.y = e.touches[0].pageY)) - : ((pos.x = e.clientX), (pos.y = e.clientY)), - e.preventDefault(); - } - function l(e) { - 1 == e.touches.length && - ((pos.x = e.touches[0].pageX), (pos.y = e.touches[0].pageY)); - } - document.removeEventListener("mousemove", onMousemove), - document.removeEventListener("touchstart", onMousemove), - document.addEventListener("mousemove", c), - document.addEventListener("touchmove", c), - document.addEventListener("touchstart", l), - c(e), - o(), - render(); - } - - function render() { - if (ctx.running) { - ctx.globalCompositeOperation = "source-over"; - ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height); - ctx.globalCompositeOperation = "lighter"; - ctx.strokeStyle = "#E62B1E"; // TEDx red color - ctx.lineWidth = 1; - for (let e, t = 0; t < E.trails; t++) { - e = lines[t]; - e.update(); - e.draw(); - } - ctx.frame++; - window.requestAnimationFrame(render); - } - } - - function resizeCanvas() { - ctx.canvas.width = window.innerWidth - 20; - ctx.canvas.height = window.innerHeight; - } - - var ctx, - f, - e = 0, - pos = {}, - lines = [], - E = { - debug: true, - friction: 0.5, - trails: 20, - size: 50, - dampening: 0.25, - tension: 0.98, - }; - function Node() { - this.x = 0; - this.y = 0; - this.vy = 0; - this.vx = 0; - } - - const renderCanvas = function () { - ctx = document.getElementById("canvas").getContext("2d"); - ctx.running = true; - ctx.frame = 1; - f = new n({ - phase: Math.random() * 2 * Math.PI, - amplitude: 85, - frequency: 0.0015, - offset: 285, - }); - document.addEventListener("mousemove", onMousemove); - document.addEventListener("touchstart", onMousemove); - document.body.addEventListener("orientationchange", resizeCanvas); - window.addEventListener("resize", resizeCanvas); - window.addEventListener("focus", () => { - if (!ctx.running) { - ctx.running = true; - render(); - } - }); - window.addEventListener("blur", () => { - ctx.running = true; - }); - resizeCanvas(); - }; - - useEffect(() => { - renderCanvas(); - - return () => { - ctx.running = false; - document.removeEventListener("mousemove", onMousemove); - document.removeEventListener("touchstart", onMousemove); - document.body.removeEventListener("orientationchange", resizeCanvas); - window.removeEventListener("resize", resizeCanvas); - window.removeEventListener("focus", () => { - if (!ctx.running) { - ctx.running = true; - render(); - } - }); - window.removeEventListener("blur", () => { - ctx.running = true; - }); - }; - }, []); -}; - -export default useCanvasCursor; diff --git a/src/components/ui/SpringModal.tsx b/src/components/ui/spring-modal.tsx similarity index 100% rename from src/components/ui/SpringModal.tsx rename to src/components/ui/spring-modal.tsx From a5096394cbc16fbab25b4f013f301c74614655c5 Mon Sep 17 00:00:00 2001 From: vyshnav Date: Thu, 14 Nov 2024 19:48:12 +0530 Subject: [PATCH 07/20] Refactor preview text in user registration email template --- emails/user-registration-email-template.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/emails/user-registration-email-template.tsx b/emails/user-registration-email-template.tsx index 0a436ac..7ce8e3f 100644 --- a/emails/user-registration-email-template.tsx +++ b/emails/user-registration-email-template.tsx @@ -23,7 +23,7 @@ export const TedxRegistrationEmail = ({ name, registrationLink, }: TedxRegistrationEmailProps) => { - const previewText = `TEDxSJEC Talk Registration Successful!`; + const previewText = `TEDxSJEC 2024 Registration Successful!`; return ( @@ -43,7 +43,7 @@ export const TedxRegistrationEmail = ({ {/* Heading Section */}
- TEDxSJEC Talk Registration Confirmed! + TEDxSJEC 2024 Registration Confirmed!
From b97b0663c468a56db0b4438f4e24857213ad4c2c Mon Sep 17 00:00:00 2001 From: vyshnav Date: Thu, 14 Nov 2024 19:48:19 +0530 Subject: [PATCH 08/20] Refactor dynamic import in user route --- src/app/api/users/route.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/api/users/route.ts b/src/app/api/users/route.ts index d9b0026..4a99ef6 100644 --- a/src/app/api/users/route.ts +++ b/src/app/api/users/route.ts @@ -1,6 +1,6 @@ import prisma from "@/server/db"; import { NextResponse } from "next/server"; - +export const dynamic = "force-dynamic"; export async function GET(req: Request) { const { searchParams } = new URL(req.url); try { From a718ed44dd0aa32c8b91437819c59496f3dc29eb Mon Sep 17 00:00:00 2001 From: vyshnav Date: Thu, 14 Nov 2024 19:48:25 +0530 Subject: [PATCH 09/20] Refactor dynamic import in user route --- src/app/api/users/payment/route.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/app/api/users/payment/route.ts b/src/app/api/users/payment/route.ts index 9099f5e..e375a60 100644 --- a/src/app/api/users/payment/route.ts +++ b/src/app/api/users/payment/route.ts @@ -2,6 +2,8 @@ import { getServerSideSession } from "@/lib/get-server-session"; import prisma from "@/server/db"; import { NextRequest, NextResponse } from "next/server"; +export const dynamic = "force-dynamic"; + export async function GET(request: NextRequest) { const { searchParams } = new URL(request.url); try { From 30778f7eb425cb1599aef411b377375c18d42469 Mon Sep 17 00:00:00 2001 From: vyshnav Date: Thu, 14 Nov 2024 19:48:34 +0530 Subject: [PATCH 10/20] Add refund page component --- src/app/refund/page.tsx | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 src/app/refund/page.tsx diff --git a/src/app/refund/page.tsx b/src/app/refund/page.tsx new file mode 100644 index 0000000..226c0cb --- /dev/null +++ b/src/app/refund/page.tsx @@ -0,0 +1,26 @@ +"use client" + +import Container from "@/components/shared/container"; +import { Text } from "@/components/shared/text"; +import {legalInfo} from "@/data/legal-info"; +import { cn } from "@/lib/utils"; + +export default function Refund() { + return ( + +
+ + Refund Policy + + {legalInfo.Refund.map((refund, index) => ( +
+ + {refund.title} + +

+
+ ))} +
+
+ ); +} \ No newline at end of file From 3da12dde37c007271ac9f60411dc9295440937a1 Mon Sep 17 00:00:00 2001 From: vyshnav Date: Thu, 14 Nov 2024 19:48:48 +0530 Subject: [PATCH 11/20] Refactor getSjecMemberType for improved clarity and functionality --- src/components/admin/user-list.tsx | 290 ++++++++++++++--------------- 1 file changed, 139 insertions(+), 151 deletions(-) diff --git a/src/components/admin/user-list.tsx b/src/components/admin/user-list.tsx index 143a674..5738343 100644 --- a/src/components/admin/user-list.tsx +++ b/src/components/admin/user-list.tsx @@ -3,13 +3,7 @@ import React, { useState, useEffect, useRef, useCallback } from "react"; import axios from "axios"; -import { - Card, - CardContent, - CardDescription, - CardHeader, - CardTitle, -} from "../ui/card"; +import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "../ui/card"; import { Avatar, AvatarFallback, AvatarImage } from "../ui/avatar"; import { Popover, PopoverContent, PopoverTrigger } from "../ui/popover"; import { Button } from "../ui/button"; @@ -19,161 +13,155 @@ import debounce from "lodash.debounce"; import ChangeRole from "./change-role"; export interface User { - id: string; - name: string | null; - email: string | null; - role: string; - image: string | null; + id: string; + name: string | null; + email: string | null; + role: string; + image: string | null; } interface UsersListProps { - initialUsers: User[]; - initialPage: number; + initialUsers: User[]; + initialPage: number; } export const dynamic = "force-dynamic"; const UsersList: React.FC = ({ initialUsers, initialPage }) => { - const [userList, setUserList] = useState(initialUsers); - const [currentPage, setCurrentPage] = useState(initialPage); - const [loading, setLoading] = useState(false); - const [hasMore, setHasMore] = useState(true); - const [searchQuery, setSearchQuery] = useState(""); // Search query state - const loader = useRef(null); + const [userList, setUserList] = useState(initialUsers); + const [currentPage, setCurrentPage] = useState(initialPage); + const [loading, setLoading] = useState(false); + const [hasMore, setHasMore] = useState(true); + const [searchQuery, setSearchQuery] = useState(""); // Search query state + const loader = useRef(null); - const fetchUsers = async (page: number, query: string) => { - if (loading) return; - setLoading(true); - try { - const response = await axios.get( - `/api/users?page=${page}&search=${encodeURIComponent(query)}`, - ); - if (response.data.users.length > 0) { - setUserList((prevUsers) => [...prevUsers, ...response.data.users]); - setCurrentPage(page); - } else { - setHasMore(false); - } - } catch (error) { - console.error("Error fetching users:", error); - } - setLoading(false); - }; - const loadMoreUsers = useCallback(() => { - if (hasMore) { - fetchUsers(currentPage + 1, searchQuery); - } - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [currentPage, hasMore, searchQuery]); + const fetchUsers = async (page: number, query: string) => { + if (loading) return; + setLoading(true); + try { + const response = await axios.get(`/api/users?page=${page}&search=${encodeURIComponent(query)}`, { + headers: { "Cache-Control": "no-cache" }, + }); + if (response.data.users.length > 0) { + setUserList((prevUsers) => [...prevUsers, ...response.data.users]); + setCurrentPage(page); + } else { + setHasMore(false); + } + } catch (error) { + console.error("Error fetching users:", error); + } + setLoading(false); + }; + const loadMoreUsers = useCallback(() => { + if (hasMore) { + fetchUsers(currentPage + 1, searchQuery); + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [currentPage, hasMore, searchQuery]); - const debouncedFetchUsers = useCallback( - debounce(async (query: string) => { - setCurrentPage(1); // Reset page number - setHasMore(true); // Reset hasMore - try { - const response = await axios.get( - `/api/users?page=1&search=${encodeURIComponent(query)}`, - ); - setUserList(response.data.users); - } catch (error) { - console.error("Error fetching users:", error); - } - }, 500), - [], - ); - const handleSearchChange = (e: React.ChangeEvent) => { - const query = e.target.value; - setSearchQuery(query); - debouncedFetchUsers(query); // Use debounced fetch function - }; + const debouncedFetchUsers = useCallback( + debounce(async (query: string) => { + setCurrentPage(1); // Reset page number + setHasMore(true); // Reset hasMore + try { + const response = await axios.get(`/api/users?page=1&search=${encodeURIComponent(query)}`); + setUserList(response.data.users); + } catch (error) { + console.error("Error fetching users:", error); + } + }, 500), + [] + ); + const handleSearchChange = (e: React.ChangeEvent) => { + const query = e.target.value; + setSearchQuery(query); + debouncedFetchUsers(query); // Use debounced fetch function + }; - // Observe scroll and load more users when scrolled to the bottom - useEffect(() => { - if (loader.current) { - const observer = new IntersectionObserver( - (entries) => { - if (entries[0].isIntersecting && hasMore) { - loadMoreUsers(); - } - }, - { threshold: 1.0 }, - ); - observer.observe(loader.current); - return () => observer.disconnect(); - } - }, [loader.current, hasMore, loadMoreUsers]); + // Observe scroll and load more users when scrolled to the bottom + useEffect(() => { + if (loader.current) { + const observer = new IntersectionObserver( + (entries) => { + if (entries[0].isIntersecting && hasMore) { + loadMoreUsers(); + } + }, + { threshold: 1.0 } + ); + observer.observe(loader.current); + return () => observer.disconnect(); + } + }, [loader.current, hasMore, loadMoreUsers]); - return ( - <> -
-
- -
-
- - -
+ return ( + <> +
+
+ +
+
+ + +
+
+ + Users + Manage user roles and permissions. + + +
+ {userList.map((user) => ( +
+
+ + + + {user.name ? user.name[0] : "N/A"} + + +
+

+ {user.name || "Unknown"} +

+

+ {user.email || "No email"} +

+
+
+ + + + + + + + +
+ ))} +
+ {hasMore && ( +
+ {loading ? "Loading..." : "Load more"} +
+ )} +
+
+
- - Users - - Manage user roles and permissions. - - - -
- {userList.map((user) => ( -
-
- - - - {user.name ? user.name[0] : "N/A"} - - -
-

- {user.name || "Unknown"} -

-

- {user.email || "No email"} -

-
-
- - - - - - - - -
- ))} -
- {hasMore && ( -
- {loading ? "Loading..." : "Load more"} -
- )} -
- -
-
- - ); + + ); }; export default UsersList; From ec9d6e6c8ffc09cf2e4d21aa2f90fd685501c6d9 Mon Sep 17 00:00:00 2001 From: vyshnav Date: Thu, 14 Nov 2024 19:49:05 +0530 Subject: [PATCH 12/20] register button --- src/components/common/cta-section-2.tsx | 160 ++++++++++++------------ 1 file changed, 81 insertions(+), 79 deletions(-) diff --git a/src/components/common/cta-section-2.tsx b/src/components/common/cta-section-2.tsx index 6b7fd81..2417ab1 100644 --- a/src/components/common/cta-section-2.tsx +++ b/src/components/common/cta-section-2.tsx @@ -1,93 +1,95 @@ import { Users, Mic2, Guitar, Calendar, MapPin } from "lucide-react"; import { Button } from "@/components/ui/button"; import { Card, CardContent } from "@/components/ui/card"; +import Link from "next/link"; export default function FullScreenCTA() { return ( -
-
-

- Explore What's Worth Living:
- {/* Inspiration Unleashed: Join Us at TEDx 2024 */} -

+
+
+

+ Explore What's Worth Living:
+ {/* Inspiration Unleashed: Join Us at TEDx 2024 */} +

-
-
-

- Join us for an extraordinary day of inspiration, innovation, and - connection. Our TEDx event brings together visionaries, thought - leaders, and change-makers from diverse fields to share ideas that - will challenge your perspective and ignite your curiosity. -

-
-
- - December 14, 2024 | 9:00 AM - 6:00 PM -
-
- - St Joseph Engineering College - Kalam Hall -
-
-

- Experience powerful talks, interactive workshops, and networking - opportunities that will leave you inspired and ready to make a - difference in your community and beyond. -

-
+
+
+

+ Join us for an extraordinary day of inspiration, innovation, and connection. Our + TEDx event brings together visionaries, thought leaders, and change-makers from + diverse fields to share ideas that will challenge your perspective and ignite your + curiosity. +

+
+
+ + December 14, 2024 | 9:00 AM - 6:00 PM +
+
+ + St Joseph Engineering College - Kalam Hall +
+
+

+ Experience powerful talks, interactive workshops, and networking opportunities that + will leave you inspired and ready to make a difference in your community and beyond. +

+
-
-
- - - -

300+

-

Attendees

-
-
- - - -

12

-

Speakers

-
-
- - - -

4

-

Performers

-
-
-
-
-

What to Expect:

-
    -
  • Thought-provoking talks from industry leaders
  • -
  • Interactive workshops and breakout sessions
  • -
  • Networking opportunities with like-minded individuals
  • -
  • Live musical and artistic performances
  • -
  • Delicious catered meals and refreshments
  • -
-
-
-
+
+
+ + + +

300+

+

Attendees

+
+
+ + + +

12

+

Speakers

+
+
+ + + +

4

+

Performers

+
+
+
+
+

What to Expect:

+
    +
  • Thought-provoking talks from industry leaders
  • +
  • Interactive workshops and breakout sessions
  • +
  • Networking opportunities with like-minded individuals
  • +
  • Live musical and artistic performances
  • +
  • Delicious catered meals and refreshments
  • +
+
+
+
-
-

- Limited spots available. Don't miss this life-changing opportunity! -

- - {/*

+

+

+ Limited spots available. Don't miss this life-changing opportunity! +

+ + + + {/*

Early bird pricing ends May 1st. Secure your spot today and save!

*/} -
+
+
-
); } From d3a3b649750e6832317303ef1855bbe8878aaf18 Mon Sep 17 00:00:00 2001 From: vyshnav Date: Thu, 14 Nov 2024 19:49:15 +0530 Subject: [PATCH 13/20] update the name --- src/components/common/registration-form.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/common/registration-form.tsx b/src/components/common/registration-form.tsx index 55649f6..bace413 100644 --- a/src/components/common/registration-form.tsx +++ b/src/components/common/registration-form.tsx @@ -163,8 +163,8 @@ export default function RegistrationForm() { key: process.env.NEXT_PUBLIC_RAZORPAY_KEY_ID, amount: pricing.finalPrice * 100, currency: "INR", - name: "Test Name", - description: "Test Transaction", + name: "TEDxSJEC", + description: "Registration Fee", order_id: data.orderId, handler: async (response: any) => { setIsProcessing(true); From 740cdef5ba70a0f373675a7a44b8d85dc6d0806d Mon Sep 17 00:00:00 2001 From: vyshnav Date: Thu, 14 Nov 2024 19:49:24 +0530 Subject: [PATCH 14/20] add container --- src/components/shared/container.tsx | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 src/components/shared/container.tsx diff --git a/src/components/shared/container.tsx b/src/components/shared/container.tsx new file mode 100644 index 0000000..ed651f7 --- /dev/null +++ b/src/components/shared/container.tsx @@ -0,0 +1,25 @@ +import { cn } from "@/lib/utils"; +import React from "react"; + +type Props = Readonly<{ + children: React.ReactNode; + className?: string; + variant?: "md" | "sm" | "xs" | "lg"; +}>; + +export default function Container({ children, className, variant = "md" }: Props) { + return ( +
+ {children} +
+ ); +} From 7a3aebd052b092b79ec13d380980385ed6f2b0e9 Mon Sep 17 00:00:00 2001 From: vyshnav Date: Thu, 14 Nov 2024 19:49:29 +0530 Subject: [PATCH 15/20] text component --- src/components/shared/text.tsx | 106 +++++++++++++++++++++++++++++++++ 1 file changed, 106 insertions(+) create mode 100644 src/components/shared/text.tsx diff --git a/src/components/shared/text.tsx b/src/components/shared/text.tsx new file mode 100644 index 0000000..7f6fe29 --- /dev/null +++ b/src/components/shared/text.tsx @@ -0,0 +1,106 @@ +import { cn } from "@/lib/utils"; +import { cva } from "class-variance-authority"; +import React from "react"; + +export type Intent = "body" | "h1" | "h2" | "h3" | "leading" | "title"; + +export interface TextProps { + intent?: Intent; + weight?: "bold" | "default" | "medium" | "semi"; + color?: "default" | "primary"; + tag?: T; +} + +export type TagOptions = keyof JSX.IntrinsicElements; + +const styles = cva<{ + intent: { + [K in Intent]: string; + }; + weight: { + bold: string; + semi: string; + medium: string; + default: string; + }; + color: { + primary: string; + default: string; + }; +}>("", { + variants: { + intent: { + body: "text-md", + leading: "text-[1.125rem] font-medium", + title: "text-[8rem] font-bold", + h1: "text-[3rem] font-bold [&>small]:text-[0.7em] [&>small]:dark:text-foreground [&>small]:text-foreground", + h2: "text-[2rem] font-semibold [&>small]:text-[0.7em] [&>small]:dark:text-foreground [&>small]:text-foreground", + h3: "font-bold text-[1.5rem] [&>small]:text-[0.7em] [&>small]:dark:text-foreground [&>small]:text-foreground", + }, + weight: { + bold: "font-bold", + semi: "font-semibold", + medium: "font-medium", + default: "font-default", + }, + color: { + primary: "dark:text-blue-400 text-blue-500", + default: "", + }, + }, + defaultVariants: { + intent: "body", + weight: "default", + color: "default", + }, +}); + +export type CorrectProps = + JSX.IntrinsicElements[T]; + +export type Combined = T & U; + +export interface TextProps { + intent?: Intent; + weight?: "bold" | "default" | "medium" | "semi"; + color?: "default" | "primary"; + tag?: T; + className?: string; +} + +export function Text({ + intent = "body", + weight, + tag, + color, + children, + className, + ...props +}: React.PropsWithChildren, TextProps>>) { + let tagStr: TagOptions = tag ?? "div"; + if (tagStr === undefined) { + switch (intent) { + case "body": + case "leading": + tagStr = "p"; + break; + case "h1": + case "h2": + case "h3": + tagStr = intent; + break; + case "title": + tagStr = "h1"; + break; + default: + tagStr = "div"; + } + } + + const Tag = tagStr as string; + return ( + + {children} + + ); +} From a8102bed21054c829f4ae956697f06e8aae391cb Mon Sep 17 00:00:00 2001 From: vyshnav Date: Thu, 14 Nov 2024 19:49:38 +0530 Subject: [PATCH 16/20] update registartion --- src/components/widget/header.tsx | 226 ++++++++++++++----------------- 1 file changed, 102 insertions(+), 124 deletions(-) diff --git a/src/components/widget/header.tsx b/src/components/widget/header.tsx index fb9f323..05a6b3f 100644 --- a/src/components/widget/header.tsx +++ b/src/components/widget/header.tsx @@ -99,131 +99,109 @@ const Nav = () => { }; return ( - <> -
-
-
- - logo - -
-
-
  • - -
    -
    -
    + <> +
    +
    +
    + + logo + +
    +
    +
  • + +
    +
    +
    -
    -
    - logo -
    -
    -
    - - - -
    - -
    -
    - logo -
    -
    -

    - Life - Explore What's Worth Living -

    -
    -
    -
    -
    - +
    +
    + logo +
    +
    +
    + + + +
    + +
    +
    + logo +
    +
    +

    + Life - Explore What's Worth Living +

    +
    +
    +
    +
    + ); }; From 331366094294a055d6da2ac737e7185b87340a71 Mon Sep 17 00:00:00 2001 From: vyshnav Date: Thu, 14 Nov 2024 19:49:45 +0530 Subject: [PATCH 17/20] Update registration functionality --- src/components/widget/hero.tsx | 282 ++++++++++++++++----------------- 1 file changed, 140 insertions(+), 142 deletions(-) diff --git a/src/components/widget/hero.tsx b/src/components/widget/hero.tsx index f0b5345..d5cd6a3 100644 --- a/src/components/widget/hero.tsx +++ b/src/components/widget/hero.tsx @@ -4,168 +4,166 @@ import { tedxsjecAssetsPrefix } from "@/lib/utils"; import { useState, useEffect, useRef } from "react"; import Image from "next/image"; import { Button } from "@/components/ui/button"; -import { - motion, - useScroll, - useTransform, - AnimatePresence, -} from "framer-motion"; +import { motion, useScroll, useTransform, AnimatePresence } from "framer-motion"; import { ArrowRight, Calendar, MapPin } from "lucide-react"; +import Link from "next/link"; type TimeLeft = { - days: number; - hours: number; - minutes: number; - seconds: number; + days: number; + hours: number; + minutes: number; + seconds: number; }; const StaticShadow = ({ children }: { children: React.ReactNode }) => { - return ( -
    - {children} -
    - ); + return ( +
    + {children} +
    + ); }; const FlipCard = ({ value, label }: { value: number; label: string }) => { - return ( -
    -
    - - - {value.toString().padStart(2, "0")} - - -
    - - {label} - -
    - ); + return ( +
    +
    + + + {value.toString().padStart(2, "0")} + + +
    + + {label} + +
    + ); }; export default function HeroHighlight() { - const [isLoaded, setIsLoaded] = useState(false); - const [timeLeft, setTimeLeft] = useState({ - days: 0, - hours: 0, - minutes: 0, - seconds: 0, - }); - const svgRef = useRef(null); - const targetDate = new Date("2024-12-14"); + const [isLoaded, setIsLoaded] = useState(false); + const [timeLeft, setTimeLeft] = useState({ + days: 0, + hours: 0, + minutes: 0, + seconds: 0, + }); + const svgRef = useRef(null); + const targetDate = new Date("2024-12-14"); - const { scrollYProgress } = useScroll(); - const pathLength = useTransform(scrollYProgress, [0, 0.8], [0, 1]); + const { scrollYProgress } = useScroll(); + const pathLength = useTransform(scrollYProgress, [0, 0.8], [0, 1]); - useEffect(() => { - setIsLoaded(true); + useEffect(() => { + setIsLoaded(true); - const intervalId = setInterval(() => { - const now = new Date(); - const difference = targetDate.getTime() - now.getTime(); + const intervalId = setInterval(() => { + const now = new Date(); + const difference = targetDate.getTime() - now.getTime(); - if (difference > 0) { - setTimeLeft({ - days: Math.floor(difference / (1000 * 60 * 60 * 24)), - hours: Math.floor((difference / (1000 * 60 * 60)) % 24), - minutes: Math.floor((difference / 1000 / 60) % 60), - seconds: Math.floor((difference / 1000) % 60), - }); - } else { - clearInterval(intervalId); - setTimeLeft({ days: 0, hours: 0, minutes: 0, seconds: 0 }); - } - }, 1000); + if (difference > 0) { + setTimeLeft({ + days: Math.floor(difference / (1000 * 60 * 60 * 24)), + hours: Math.floor((difference / (1000 * 60 * 60)) % 24), + minutes: Math.floor((difference / 1000 / 60) % 60), + seconds: Math.floor((difference / 1000) % 60), + }); + } else { + clearInterval(intervalId); + setTimeLeft({ days: 0, hours: 0, minutes: 0, seconds: 0 }); + } + }, 1000); - return () => clearInterval(intervalId); - }, [targetDate]); + return () => clearInterval(intervalId); + }, [targetDate]); - const timeUnits: (keyof TimeLeft)[] = ["days", "hours", "minutes", "seconds"]; + const timeUnits: (keyof TimeLeft)[] = ["days", "hours", "minutes", "seconds"]; - return ( -
    - {/* Semi-transparent overlay to allow stars to show through */} -
    + return ( +
    + {/* Semi-transparent overlay to allow stars to show through */} +
    - - - - -
    -
    -

    - Ideas Worth Spreading -

    -

    - Join us for an inspiring TEDx event featuring thought-provoking - talks, innovative ideas, and transformative experiences. -

    -
    - -
    -
    -
    - -

    Date: December 14, 2024

    + + + +
    +
    +

    + Ideas Worth Spreading +

    +

    + Join us for an inspiring TEDx event featuring thought-provoking talks, innovative + ideas, and transformative experiences. +

    +
    + + + +
    +
    +
    + +

    Date: December 14, 2024

    +
    +
    +
    +
    + + TEDx Event Logo + +

    + Life - Explore What's Worth Living +

    +
    -
    -
    -
    - - TEDx Event Logo - -

    - Life - Explore What's Worth Living -

    -
    -
    -
    -

    - Event Starts In -

    -
    - {timeUnits.map((unit) => ( - - ))} -
    -
    -
    - ); +
    +

    + Event Starts In +

    +
    + {timeUnits.map((unit) => ( + + ))} +
    +
    +
    + ); } From b74779e584cf81fc8464156a5bdabcd1a2d9cf20 Mon Sep 17 00:00:00 2001 From: vyshnav Date: Thu, 14 Nov 2024 19:49:54 +0530 Subject: [PATCH 18/20] Add legal information for refund policy and payment process --- src/data/legal-info.ts | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 src/data/legal-info.ts diff --git a/src/data/legal-info.ts b/src/data/legal-info.ts new file mode 100644 index 0000000..3a509b9 --- /dev/null +++ b/src/data/legal-info.ts @@ -0,0 +1,28 @@ +export const legalInfo = { + Refund: [ + { + title: "Introduction", + description: `We offer a seamless registration process using Razorpay, a secure payment gateway. This page outlines our refund policy to provide clarity and peace of mind in case of any issues with your payment.`, + }, + { + title: "Payment Process", + description: `Our payment process is designed to be easy and convenient for you. We offer multiple payment options, including credit/debit cards, net banking, and UPI. Once you select your preferred payment method, you will be redirected to Razorpay${"'"}s secure payment gateway to complete the payment process.`, + }, + { + title: "Refund Policy", + description: `We understand that sometimes processing errors or technical glitches can occur during the payment process, leading to an unsuccessful transaction. In such cases, the amount paid by you will be credited back to your account automatically within 5-7 business days. Please note that this refund is only applicable in the case of an unsuccessful transaction due to processing errors and not for any other reasons. Please fill out the form : here`, + }, + { + title: "Non-Refundable Services", + description: `Please note that our registration services are non-refundable and cannot be canceled once payment has been made. This policy is in place to ensure that we can deliver the best possible experience for all our customers.`, + }, + { + title: "Payment Security", + description: `We take the safety and security of your payment information very seriously. Our payment gateway partner, Razorpay, ensures that all transactions are secure and protected by industry-standard encryption. You can be confident that your payment information is safe when you use our website for registration. `, + }, + { + title: "Contact Information", + description: `If you have any questions or concerns about our refund policy or payment process, please do not hesitate to contact our team. You can reach us at tiara@sjec.ac.in, and we will be happy to assist you. `, + }, + ], +}; From 3679cb780fac2583b581848b2062a423e914f6cc Mon Sep 17 00:00:00 2001 From: vyshnav Date: Thu, 14 Nov 2024 21:13:31 +0530 Subject: [PATCH 19/20] Update CTA section with margin-top for better spacing --- src/components/common/cta-section-2.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/common/cta-section-2.tsx b/src/components/common/cta-section-2.tsx index 2417ab1..3d02b2e 100644 --- a/src/components/common/cta-section-2.tsx +++ b/src/components/common/cta-section-2.tsx @@ -80,7 +80,7 @@ export default function FullScreenCTA() { From 3488686ec4bd7fe62100714289d3314a134c1322 Mon Sep 17 00:00:00 2001 From: vyshnav Date: Thu, 14 Nov 2024 21:43:12 +0530 Subject: [PATCH 20/20] add refund policy in footer --- src/components/common/Footer-1.tsx | 242 +++++++++++++++-------------- 1 file changed, 123 insertions(+), 119 deletions(-) diff --git a/src/components/common/Footer-1.tsx b/src/components/common/Footer-1.tsx index 6638c64..5ff1900 100644 --- a/src/components/common/Footer-1.tsx +++ b/src/components/common/Footer-1.tsx @@ -16,130 +16,134 @@ import { Card, CardContent } from "@/components/ui/card"; export default function Footer() { return ( - ); }