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!
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/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 { 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 { 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 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; 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 */} 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 ( -
-
-
-
-

- Contact Us -

-
- - - -
-

Email Us

- - tedx@sjec.ac.in - +
+
+
+
+

Contact Us

+
+ + + +
+

Email Us

+ + tedx@sjec.ac.in + +
+
+
+ + + +
+

Call Us

+

Dr. Binu KG

+ + +91-9739866947 + +
+
+
+ + +
+ +
+

Visit Us

+
+ St Joseph Engineering College, +
+ Vamanjoor, Mangalore - 575028 +
+ Karnataka, India +
+
+
+
+ + + + + + +
+
+
+
- - - - - -
-

Call Us

-

Dr. Binu KG

- - +91-9739866947 - +
+
+
+
- - - - -
- -
-

Visit Us

-
- St Joseph Engineering College, -
- Vamanjoor, Mangalore - 575028 -
- Karnataka, India -
-
-
-
- -
+
+
+

+ © 2024 TEDxSJEC. All Rights Reserved. This independent TEDx event is operated under + license from TED. +

+
+ + Privacy Policy + + - Instagram -
- - -
-
-
-
-
- -
-
-
-
-
-

- © 2024 TEDxSJEC. All Rights Reserved. This independent TEDx event - is operated under license from TED. -

-
- - Privacy Policy - - - Terms of Service - +
-
-
-
+
); } 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/common/cta-section-2.tsx b/src/components/common/cta-section-2.tsx index 6b7fd81..3d02b2e 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!

*/} -
+
+
-
); } diff --git a/src/components/common/registration-form.tsx b/src/components/common/registration-form.tsx index c1a213d..bace413 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", { @@ -165,10 +163,11 @@ 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); 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" && ( diff --git a/src/components/navbar/nav-header.tsx b/src/components/navbar/nav-header.tsx index 8855624..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; @@ -34,7 +33,7 @@ const NavHeader: React.FC = ({ handleClick }) => { height={200} width={200} alt="logo" - layout="fixed" + // layout="fixed" priority={true} /> 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} +
+ ); +} 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} + + ); +} 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 diff --git a/src/components/widget/header.tsx b/src/components/widget/header.tsx index fb9f323..ec0ded1 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} /> @@ -146,84 +146,76 @@ const Nav = () => {
-
-
- logo -
-
-
- - - -
- -
-
- logo -
-
-

- Life - Explore What's Worth Living -

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

+ Life - Explore What's Worth Living +

+
+
+
+
+ ); }; 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) => ( + + ))} +
+
+
+ ); } 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" 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; 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. `, + }, + ], +}; 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