From 4926a31760a67007f542bca44a45385349575043 Mon Sep 17 00:00:00 2001 From: Anas-github-acc Date: Thu, 25 Jul 2024 02:13:45 +0530 Subject: [PATCH 01/17] manading form_create from falling down and allowing user to create table if their no entries for them in users table --- package-lock.json | 107 +++++++++++++++ package.json | 2 + src/app/api/logout/route.ts | 10 ++ src/app/api/rest/v1/isUsername/route.ts | 29 ++++ src/app/api/rest/v1/users/route.ts | 39 ++++++ src/app/auth/action.tsx | 56 ++++---- src/app/auth/callback/route.ts | 1 + src/app/auth/component/component.tsx | 23 ++-- src/app/auth/component/oauth.tsx | 9 +- src/app/auth/confirm/route.ts | 15 +-- src/app/auth/confirm_email/page.tsx | 42 ++++-- src/app/auth/page.tsx | 29 ++-- .../form_create/component/styles.module.css | 27 ++++ src/app/form_create/component/userform.tsx | 120 +++++++++++++++++ src/app/form_create/page.tsx | 125 +++++++++++++++--- src/app/layout.tsx | 5 + src/components/ui/loader.tsx | 20 +++ src/utils/supabase/middleware.ts | 43 ++++-- 18 files changed, 596 insertions(+), 106 deletions(-) create mode 100644 src/app/api/logout/route.ts create mode 100644 src/app/api/rest/v1/isUsername/route.ts create mode 100644 src/app/api/rest/v1/users/route.ts create mode 100644 src/app/form_create/component/styles.module.css create mode 100644 src/app/form_create/component/userform.tsx create mode 100644 src/components/ui/loader.tsx diff --git a/package-lock.json b/package-lock.json index 7ec5173..e8a51f5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,8 +16,10 @@ "@radix-ui/react-slot": "^1.1.0", "@reduxjs/toolkit": "^2.2.6", "@supabase/ssr": "^0.4.0", + "axios": "^1.7.2", "class-variance-authority": "^0.7.0", "clsx": "^2.1.1", + "ldrs": "^1.0.2", "lucide-react": "^0.408.0", "next": "14.2.5", "next-client-cookies": "^1.1.1", @@ -1222,6 +1224,12 @@ "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", "license": "MIT" }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "license": "MIT" + }, "node_modules/autoprefixer": { "version": "10.4.19", "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.19.tgz", @@ -1260,6 +1268,17 @@ "postcss": "^8.1.0" } }, + "node_modules/axios": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.2.tgz", + "integrity": "sha512-2A8QhOMrbomlDuiLeK9XibIBzuHeRcqqNOHp0Cyp5EoJ1IFDh+XZH3A6BkXtv0K4gFGCI0Y4BM7B1wOEi0Rmgw==", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, "node_modules/babel-plugin-macros": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz", @@ -1536,6 +1555,18 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "license": "MIT" }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/commander": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", @@ -1634,6 +1665,15 @@ } } }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/didyoumean": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", @@ -1761,6 +1801,26 @@ "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==", "license": "MIT" }, + "node_modules/follow-redirects": { + "version": "1.15.6", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", + "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "license": "MIT", + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, "node_modules/foreground-child": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.2.1.tgz", @@ -1777,6 +1837,20 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/fraction.js": { "version": "4.3.7", "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz", @@ -2064,6 +2138,12 @@ "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", "license": "MIT" }, + "node_modules/ldrs": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/ldrs/-/ldrs-1.0.2.tgz", + "integrity": "sha512-sYJmivdkIiHrUEqTrEWccBoLdaENpzbzkABI5rk8rRxTXrg9i2xVuDvUUuhOhJY3RmQyaoxs046pM1DCRdcIpg==", + "license": "MIT" + }, "node_modules/lilconfig": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", @@ -2128,6 +2208,27 @@ "node": ">=8.6" } }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/minimatch": { "version": "9.0.5", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", @@ -2608,6 +2709,12 @@ "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", "license": "MIT" }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "license": "MIT" + }, "node_modules/queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", diff --git a/package.json b/package.json index ed5222b..ec8026f 100644 --- a/package.json +++ b/package.json @@ -17,8 +17,10 @@ "@radix-ui/react-slot": "^1.1.0", "@reduxjs/toolkit": "^2.2.6", "@supabase/ssr": "^0.4.0", + "axios": "^1.7.2", "class-variance-authority": "^0.7.0", "clsx": "^2.1.1", + "ldrs": "^1.0.2", "lucide-react": "^0.408.0", "next": "14.2.5", "next-client-cookies": "^1.1.1", diff --git a/src/app/api/logout/route.ts b/src/app/api/logout/route.ts new file mode 100644 index 0000000..0970273 --- /dev/null +++ b/src/app/api/logout/route.ts @@ -0,0 +1,10 @@ +import {NextRequest, NextResponse} from "next/server"; +import {createClient} from "@/utils/supabase/server"; + +export async function GET(req: NextRequest) { + const supabase = createClient() + + const { error } = await supabase.auth.signOut() + + return NextResponse.redirect(new URL("/form_create", req.url)) +} \ No newline at end of file diff --git a/src/app/api/rest/v1/isUsername/route.ts b/src/app/api/rest/v1/isUsername/route.ts new file mode 100644 index 0000000..8679bc0 --- /dev/null +++ b/src/app/api/rest/v1/isUsername/route.ts @@ -0,0 +1,29 @@ +import {NextRequest, NextResponse} from "next/server"; + +export async function POST(req: NextRequest) { + let response = NextResponse.next({ + request: { + headers: req.headers, + }, + }) + + const body = await req.json() + + if ( !body.username ) { + return NextResponse.json({ error: 'username is required' }) + } + + let res = await fetch(`${process.env.NEXT_PUBLIC_SUPABASE_URL}/rest/v1/rpc/is_username_exist`, { + method: 'POST', + headers: { + "apikey": process.env.SERVICE_KEY!, + "Authorization": `Bearer ${process.env.SERVICE_KEY!}`, + "Content-Type": "application/json", + }, + body: JSON.stringify(body) + }); + + let data = await res.json(); + + return NextResponse.json({ state: data }); +} \ No newline at end of file diff --git a/src/app/api/rest/v1/users/route.ts b/src/app/api/rest/v1/users/route.ts new file mode 100644 index 0000000..c61b750 --- /dev/null +++ b/src/app/api/rest/v1/users/route.ts @@ -0,0 +1,39 @@ +import {NextRequest, NextResponse} from "next/server"; +import { createClient } from "@/utils/supabase/server"; +import { User } from "@supabase/supabase-js"; + +export async function POST(req: NextRequest) { + let response = NextResponse.next({ + request: { + headers: req.headers, + }, + }) + + const body = await req.json() + const supabase = createClient(); + const searchParams = req.nextUrl.searchParams; + const option = searchParams.get('option'); + + let data: User | User[] | null = null; + + if ( option === 'insert' ) { + const { data: user, error: error } = await supabase + .from('users') + .insert([{id: body.id, username: body.username, admin: body.admin}]) + if (error) { + return NextResponse.json({ error: error.message }, { status: 500 }); + } + data = user; + } else if ( option === 'update' ) { + const { data: user, error: error } = await supabase + .from('users') + .update({username: body.username}) + .match({id: body.id}) + if (error) { + return NextResponse.json({ error: error.message }, { status: 500 }); + } + data = user; + } + + return NextResponse.json({ data: data }); +} \ No newline at end of file diff --git a/src/app/auth/action.tsx b/src/app/auth/action.tsx index 601847b..e06c965 100644 --- a/src/app/auth/action.tsx +++ b/src/app/auth/action.tsx @@ -21,51 +21,53 @@ export const Login = async ( export const SignUp = async ( credentials : { + username: string | null, email: string , password: string , }) => { const origin = headers().get("origin"); - const referer = headers().get("referer"); - const query = referer?.split('?')[1].split('&'); - const org = query?.find((q) => q.includes('organisation')) || ''; - + const username = credentials.username; const supabase = createClient(); - const { data: { session }, error, } = await supabase.auth.signUp({ + + const { data: { user, session }, error, } = await supabase.auth.signUp({ email: credentials.email as string, password: credentials.password as string, options: { - emailRedirectTo: `${origin}/auth/callback`, + emailRedirectTo: `${origin}/auth/confirm`, + data: { username: username }, }, }); + if (error) { + console.log(error); return { error: error.message }; } - if (session) { + if (session || user?.role !== 'authenticated') { return { error: 'Email already exists' }; } - return { error: null }; + return { user_id: user?.id, error: null }; }; export const AuthSignIn = async () => { - const origin = headers().get("origin"); - const gmail = cookies()?.get('email')?.value || ''; - - const supabase = createClient(); - const { data, error } = await supabase.auth.signInWithOAuth({ - provider: 'google', - options: { - redirectTo: `${origin}/auth/callback`, - queryParams: { - include_granted_scopes: 'true', - access_type: 'offline', - prompt: 'select_account', - login_hint: gmail, - }, - }, - }); - if (error) return { error: error.message, url: null }; - if (data.url) return { error: null, url: data.url }; - return { error: 'Error signing in', url: null }; + const origin = headers().get("origin"); + const gmail = cookies()?.get('email')?.value || ''; + + const supabase = createClient(); + const { data, error } = await supabase.auth.signInWithOAuth({ + provider: 'google', + options: { + redirectTo: `${origin}/auth/callback`, + queryParams: { + include_granted_scopes: 'true', + access_type: 'offline', + prompt: 'select_account', + login_hint: gmail, + }, + }, + }); + if (error) return { error: error.message, url: null }; + if (data.url) return { error: null, url: data.url }; + return { error: 'Error signing in', url: null }; } export async function usernameExisits(username: string): Promise { diff --git a/src/app/auth/callback/route.ts b/src/app/auth/callback/route.ts index 96cfad6..4bb206f 100644 --- a/src/app/auth/callback/route.ts +++ b/src/app/auth/callback/route.ts @@ -23,5 +23,6 @@ export async function GET(req: NextRequest, res: NextResponse) { console.log('x ',error); } } + return NextResponse.redirect(url); } \ No newline at end of file diff --git a/src/app/auth/component/component.tsx b/src/app/auth/component/component.tsx index ac64735..13f9eff 100644 --- a/src/app/auth/component/component.tsx +++ b/src/app/auth/component/component.tsx @@ -1,15 +1,16 @@ -import { FormEvent, use, useEffect, useState } from "react"; +import React, { FormEvent, use, useEffect, useState } from "react"; import { usernameExisits } from "@/app/auth/action"; import { Label } from "@/components/ui/label" import { Input } from "@/components/ui/input" import { Button } from "@/components/ui/button" +import Loader from '@/components/ui/loader' -import { VscEye, VscEyeClosed } from "react-icons/vsc"; -import CircularProgress from '@mui/material/CircularProgress'; +import { VscEye, VscEyeClosed } from "react-icons/vsc" import styles from './styles.module.css' import { cn } from "@/lib/utils" + interface Props { auth: string | null SignUp: (e: EventTarget & HTMLFormElement) => Promise @@ -90,22 +91,21 @@ export function Component( props : Props) { } setLoading(true); const data = await usernameExisits(username) - console.log('data = ',data); + if (data) { - const nextUserSibling = current.username.nextSibling as HTMLElement; + const nextUserSibling = current.username.nextElementSibling as HTMLElement; nextUserSibling.innerText = 'Username already exists'; } else { - const nextUserSibling = current.username.nextSibling as HTMLElement; + const nextUserSibling = current.username.nextElementSibling as HTMLElement; nextUserSibling.innerText = ''; if (validatePassword(password) && password.length>=8) { - const bool = await props.SignUp(current) if (!bool) setLoading(false); - const nextSibling = current.password.nextSibling as HTMLElement; + const nextSibling = current.password.nextElementSibling as HTMLElement; nextSibling.innerText = ''; } else { - const nextSibling = current.password.nextSibling as HTMLElement; + const nextSibling = current.password.nextElementSibling as HTMLElement; if (!validatePassword(password, 1)) { nextSibling.innerText = 'Password must be at least 8 characters long'; } else if (!validatePassword(password, 2)) { @@ -171,7 +171,8 @@ export function Component( props : Props) { className="group relative flex w-full justify-center rounded-[8px] bg-primary py-6 px-4 text-md font-bold text-primary-foreground transition-colors focus:opacity-90 focus:outline-none" disabled={loading} > - {loading ? : structure.button.text} + {loading ? + : structure.button.text} @@ -190,7 +191,7 @@ function validateEmail(email: string): boolean { function validatePassword(password: string, customCheck: number = 0): boolean { const re = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[!@#$%^&*()_+])[A-Za-z\d!@#$%^&*()_+]{8,}$/; const special = /[!@#$%^&*()_+]/; - const upper_lower_digit = /[a-z]/ && /[A-Z]/ && /\d/; + const upper_lower_digit = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)[A-Za-z\d]{8,}$/; if (!customCheck) return re.test(password); if (customCheck === 1) return password.length >= 8; if (customCheck === 2) return upper_lower_digit.test(password); diff --git a/src/app/auth/component/oauth.tsx b/src/app/auth/component/oauth.tsx index 9bc48cb..faba5ee 100644 --- a/src/app/auth/component/oauth.tsx +++ b/src/app/auth/component/oauth.tsx @@ -1,10 +1,9 @@ import React, { useState } from "react"; import { Button } from "@/components/ui/button" +import Loader from '@/components/ui/loader' // -- icons -- -import CircularProgress from '@mui/material/CircularProgress'; import { FcGoogle } from "react-icons/fc"; - import { JSX, SVGProps } from "react" interface Props{ @@ -34,10 +33,8 @@ export function OAuthComponent(props : Props) { variant="outline" className="group relative flex w-full justify-center rounded-[8px] border border-input bg-background py-6 px-4 text-md font-medium text-foreground transition-colors hover:bg-accent hover:text-accent-foreground focus:outline-none focus:opacity-90" > - {loading ? : - <> - oogle - } + {loading ? : + <>oogle} ) diff --git a/src/app/auth/confirm/route.ts b/src/app/auth/confirm/route.ts index 55a8b92..b654759 100644 --- a/src/app/auth/confirm/route.ts +++ b/src/app/auth/confirm/route.ts @@ -1,6 +1,5 @@ import { type EmailOtpType } from '@supabase/supabase-js' import { type NextRequest, NextResponse } from 'next/server' -import { cookies } from 'next/headers' import { createClient } from '@/utils/supabase/server' @@ -8,7 +7,7 @@ export async function GET(req: NextRequest) { const { searchParams } = new URL(req.url) const token_hash = searchParams.get('token_hash') const type = searchParams.get('type') as EmailOtpType | null - const next = searchParams.get('next') ?? '/create_form' + const next = searchParams.get('next') ?? '/form_create' const redirectTo = req.nextUrl.clone() redirectTo.pathname = next @@ -21,18 +20,6 @@ export async function GET(req: NextRequest) { type: type || 'email', token_hash: token_hash , }) - const user = data?.user - if (!error && user) { - const getCookies = cookies(); - const username = getCookies?.get('username')?.value; - getCookies?.delete('username'); - const { error: insertError } = await supabase - .from('users') - .insert([ - { id: user?.id, username: username } - ]); - if (insertError) console.error('Error inserting user data:', insertError.message); - } if (!error) { redirectTo.searchParams.delete('next') return NextResponse.redirect(redirectTo) diff --git a/src/app/auth/confirm_email/page.tsx b/src/app/auth/confirm_email/page.tsx index 9928445..00cef0a 100644 --- a/src/app/auth/confirm_email/page.tsx +++ b/src/app/auth/confirm_email/page.tsx @@ -1,9 +1,10 @@ 'use client'; -import React, { useState, useEffect, use } from 'react'; +import React, { useState, useEffect, useCallback } from 'react'; import Link from 'next/link'; -import { Button } from '@/components/ui/button'; + import { useSearchParams } from 'next/navigation'; import { supabase } from '@/utils/supabase/client'; +import { Button } from '@/components/ui/button'; import Image from 'next/image'; @@ -12,10 +13,22 @@ export default function Confirm() { const [error, setError] = useState(null); const [countdown, setCountdown] = useState(10); + useEffect(() => { + supabase.auth.getUser().then(({ data , error }) => { + if (error) { + console.log(error.message); + return; + } + console.log(data); + }); + }, []); + const searchParams = useSearchParams(); - const email = searchParams.get('email') || 'xxxx-xxxx-xxxx-xxxx'; + const user_email = searchParams.get('user_email'); + + if (!user_email) return null; - if(!validateEmail(email)) { + if(!validateEmail(user_email)) { return (
@@ -23,7 +36,7 @@ export default function Confirm() { Invalid email address:

- {email} + {user_email}

); @@ -49,44 +62,47 @@ export default function Confirm() { }, [loading, countdown]); const resent = async () => { + const origin = window.location.origin; setLoading(true) const { error } = await supabase.auth.resend({ type: 'signup', - email: email, + email: user_email, options: { - emailRedirectTo: '/auth/confirm_email?email=' + email, + emailRedirectTo: `${origin}/auth/confirm`, } }) if (error) { setError(error.message) + } else { + setError(null) } } return (
-
+

Email Sent!

- We've sent a confirmation email to {email}. Click the link in + We've sent a confirmation email to {user_email}. Click the link in the email to verify your account.

- Return to Home + Return to Login
diff --git a/src/app/auth/page.tsx b/src/app/auth/page.tsx index d3f1d0f..feb03da 100644 --- a/src/app/auth/page.tsx +++ b/src/app/auth/page.tsx @@ -26,6 +26,11 @@ export default function Auth(){ const auth = searchParams.get('auth'); const organisation = searchParams.get('organisation'); const oauthhidden = organisation==='iiitv'?true:false; + const err = searchParams.get('error'); + + useEffect(() => { + if (err) setError(err); + }, [err]); const cookies = useCookies(); const email = cookies.get('email') || null; @@ -48,22 +53,24 @@ export default function Auth(){ } else { router.push('/form_create'); } - } + } + const signup = async (cur: EventTarget & HTMLFormElement) => { const email = cur.email.value; const username = cur.username.value; const password = cur.password.value; - cookies.set('username', username); setError(null); - const { error } = await SignUp({email, password}) + const { user_id, error } = await SignUp({username, email, password}) + console.log(error); if (error) { setError(error); return false; } else { - router.push('/auth/confirm_email?email=' + email); + router.push(`/auth/confirm_email?id=${user_id}&user_email=${email}`); } } + const Authsignin = async () => { setError(null); const { error, url } = await AuthSignIn(); @@ -88,13 +95,13 @@ export default function Auth(){ EmailSubmit={emailSubmit} email={email}> - { auth && -
- {auth === 'signup' ? -

Have an account? Login

: -

Don't have an account? Create here

} -
- } + { auth && (
+
+ {auth === 'signup' ? +

Have an account? Login

: +

Don't have an account? Create here

} +
+
)} {oauthhidden && } diff --git a/src/app/form_create/component/styles.module.css b/src/app/form_create/component/styles.module.css new file mode 100644 index 0000000..e13e8fd --- /dev/null +++ b/src/app/form_create/component/styles.module.css @@ -0,0 +1,27 @@ +.error { + position: absolute; + left:6px; + top: -17.5px; + height: fit-content !important; + color:red !important; + font-size:0.7rem !important; + word-wrap: no-wrap !important; + white-space: nowrap !important; + z-index: 10; +} +.inputicon { + position:absolute; + top: 50%; + color: rgba(var(--black-light), .45); + font-size: 1rem; + transform: translateY(-50%); + transition: 0.5s ease; +} +.eyeicon { + right: 15px; + padding: 3px; + cursor: pointer; +} +.eyeicon:hover { + color: rgba(var(--black-light), .65); +} \ No newline at end of file diff --git a/src/app/form_create/component/userform.tsx b/src/app/form_create/component/userform.tsx new file mode 100644 index 0000000..c8d6e9d --- /dev/null +++ b/src/app/form_create/component/userform.tsx @@ -0,0 +1,120 @@ +import React, { useState, useEffect, useCallback, use } from "react"; +import axios from "axios"; + +import { Input } from "@/components/ui/input"; +import { Button } from "@/components/ui/button"; +import { Label } from "@/components/ui/label"; +import Loader from '@/components/ui/loader' + +import styles from './styles.module.css' +import { cn } from "@/lib/utils"; + + +interface PropsType { + email: string | null, + user_id: string, +} + +export function UserForm( {user_id, email}: PropsType) { + const [username, setUsername] = useState(null); + const [error, setError] = useState(null); + const [disabled, setDisabled] = useState(true); + const [loading, setLoading] = useState(false); + + const controller = new AbortController(); + const signal = controller.signal; + + const isExist = useCallback(async () => { + const res = await axios.post('/api/rest/v1/isUsername', {username: username}, {signal}); + if (res.data.state) { + setDisabled(true); + setError('Username already exists'); + } else { + setDisabled(false); + setError(''); + } + }, [username]); + + + useEffect(() => { + let timer: NodeJS.Timeout; + if (username) { + timer = setTimeout(() => { + isExist(); + }, 400) + } + return () => { + controller.abort(); + clearTimeout(timer); + } + }, [username]); + + useEffect(() => { + if (!username) { + console.log('username is empty'); + setError(''); + setDisabled(true); + } + }, [username, disabled, error]); + + return ( +
+
+
+

+ Welcome, {email?.split('@')[0]} +

+

Please enter an username

+
+
{ + e.preventDefault(); + setLoading(true); + axios.post(`/api/rest/v1/users?option=insert`, {id: user_id, username: username}) + .then((res) => { + if (res.data.error) { + setError(res.data.error); + setLoading(false); + } else { + setLoading(false); + window.location.href = '/form_create'; + } + }) + .catch((error) => { + setError(error.message); + setLoading(false); + }); + }}> +
+ + setUsername(e.target.value)} + id={'username'} + name={'username'} + type={'text'} + autoComplete={'username'} + required + placeholder={'Username'} + disabled={loading} + className={cn("rounded-[8px] border border-input bg-background px-4 py-6 text-foreground placeholder-muted-foreground focus:z-10 focus:border-primary focus:outline-none sm:text-sm")} + /> + {error} +
+
+ +
+
+
+
+ ); +} \ No newline at end of file diff --git a/src/app/form_create/page.tsx b/src/app/form_create/page.tsx index be456f2..18a0fc2 100644 --- a/src/app/form_create/page.tsx +++ b/src/app/form_create/page.tsx @@ -1,25 +1,118 @@ 'use client'; -import React from 'react'; +import React, { useState, useEffect, useCallback, use } from 'react'; +import Link from 'next/link'; +import { useSearchParams } from 'next/navigation'; import { supabase } from '@/utils/supabase/client'; +import { User } from '@supabase/supabase-js'; +import axios from 'axios'; + +import { UserForm } from './component/userform'; + import { cn } from '@/lib/utils'; -import { Button } from '@/components/ui/button'; +export default function Page() { + const [user, setUser] = useState(null); + const [username , setUsername] = useState(null); + const [useremail , setUserEmail] = useState(null); + const [error_message, setErrorMessage] = useState(null); + + const [usernameInput, setUsernameInput] = useState(false); + + const [loading, setLoading] = useState(false); + + const searchParams = useSearchParams(); + + useEffect(() => { + console.log() + const getUser = async () => { + const { data: { user }, error } = await supabase.auth.getUser(); + if (error) { + console.log(error.message); + return; + } + setUser(user); + setUserEmail(user?.email || null); + } + getUser(); + }, []); + + useEffect(() => { + return () => { + + if ( user ) { + getUserData(); + } + }; + }, [user]); + + const getUsernameFromUser = async () => { + if (searchParams.get('username')) { + const res = await axios.post('/api/rest/v1/isUsername', {username: searchParams.get('username')}); + if (!res.data.state) { + axios.post('/api/rest/v1/users?option=insert', {id: user?.id, username: searchParams.get('username')}) + .then((res) => { + if (res.data.error) { + setErrorMessage(res.data.error); + return {error: res.data.error}; + } + setUsername(searchParams.get('username')); + }) + return {error: null}; + } + } + setUsernameInput(true); + return {error: null}; + } + + let getUserData = useCallback(async () => { + try { + setLoading(true); + if (!user) throw new Error('No user on the session'); + + const { data, error, status } = await supabase + .from('users') + .select('username') + .eq('id', user.id) + .single(); -export default async function Page() { - const { data : {user}} = await supabase.auth.getUser(); - const { data, error } = await supabase.from('users').select('username').eq('id', user?.id); - const userdata = data && data[0]; - const username = userdata && ( 'username' in userdata && userdata.username || user?.identities); + if (status === 406) { + const { error } = await getUsernameFromUser() + if (error) throw error;return; + } + if (error && status !== 406 ) throw error; + if (data) { + setUsername(data.username); + } + } + catch (error: any) { + console.log(error.message); + } + finally { + setLoading(false); + } + } + , [user]); - const Logout = async () => { - const { error } = await supabase.auth.signOut(); - if (error) console.error('Sign out error', error.message); - window.location.reload(); - }; return ( -
-

Welcome, {username}

- -
+ <> + {usernameInput ? ( + + ):( +
+

Welcome, {username}

+

{useremail}

+ {error_message &&

{error_message}

} + {loading &&

Loading...

} + + Logout + +
+ )} + ); } \ No newline at end of file diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 4ff1260..d05d061 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -27,6 +27,11 @@ export default function RootLayout({ + }>{children} diff --git a/src/components/ui/loader.tsx b/src/components/ui/loader.tsx new file mode 100644 index 0000000..9456492 --- /dev/null +++ b/src/components/ui/loader.tsx @@ -0,0 +1,20 @@ +import { useEffect } from 'react' + +export default function Loader() { + useEffect(() => { + async function getLoader() { + const { ring } = await import('ldrs') + ring.register() + } + getLoader() + }, []) + return ( + + ) +} \ No newline at end of file diff --git a/src/utils/supabase/middleware.ts b/src/utils/supabase/middleware.ts index 842f875..ee926c6 100644 --- a/src/utils/supabase/middleware.ts +++ b/src/utils/supabase/middleware.ts @@ -1,5 +1,5 @@ import { createServerClient, type CookieOptions } from '@supabase/ssr' -import { NextResponse, type NextRequest } from 'next/server' +import { NextRequest, NextResponse } from 'next/server' export async function updateSession(request: NextRequest) { let response = NextResponse.next({ @@ -54,16 +54,43 @@ export async function updateSession(request: NextRequest) { } ) - const { data: {user}} = await supabase.auth.getUser() - if (user && !user?.confirmed_at && request.nextUrl.pathname === '/form_create') { - response = NextResponse.redirect(new URL('/auth/confirm_email', request.nextUrl.href)) - } else if (user?.confirmed_at && request.nextUrl.pathname === '/auth/confirm_email') { - response = NextResponse.redirect(new URL('/form_create', request.nextUrl.href)) - } else if (user && request.nextUrl.pathname === '/auth') { + + if (request.nextUrl.pathname === '/auth/callback' || request.nextUrl.pathname === '/auth/confirm') return response + + + let { data: {user}, error} = await supabase.auth.getUser() + + + if (user && (request.nextUrl.pathname === '/auth/confirm_email' || request.nextUrl.pathname === '/auth')) { response = NextResponse.redirect(new URL('/form_create', request.nextUrl.href)) - } else if (!user && request.nextUrl.pathname === '/form_create') { + } else if (!user && ( request.nextUrl.pathname === '/form_create' )) { response = NextResponse.redirect(new URL('/auth', request.nextUrl.href)) } + const searchParams = request.nextUrl.searchParams + + if (request.nextUrl.pathname === '/auth/confirm_email') { + if (searchParams.get('user_email')) { + if (!searchParams.get('id')) return NextResponse.redirect(new URL('/auth?error=No+ID+provided', request.nextUrl.href)) + let res = await fetch(`${process.env.NEXT_PUBLIC_SUPABASE_URL}/auth/v1/admin/users/${searchParams.get('id')}`, { + method: 'GET', + headers: { + "apikey": process.env.SERVICE_KEY!, + "Authorization": `Bearer ${process.env.SERVICE_KEY!}`, + "Content-Type": "application/json", + } + }); + + const res_user = await res.json(); + if (res.status === 404 || !res_user?.email ) return NextResponse.redirect(new URL('/auth?error=user+not+found', request.nextUrl.href)) + if ( request.nextUrl.searchParams.get('user_email') !== res_user?.email ) { + request.nextUrl.searchParams.set('user_email', res_user?.email as string) + response = NextResponse.redirect(new URL(request.nextUrl.href)) + return response + } + if (res_user?.email_confirmed_at) return NextResponse.redirect(new URL('/auth?auth=login', request.nextUrl.href)) + } + } + return response } \ No newline at end of file From 3aa5f03a1bf49d3fab7e9151424b75aef62aedff Mon Sep 17 00:00:00 2001 From: Anas-github-acc Date: Thu, 25 Jul 2024 02:36:54 +0530 Subject: [PATCH 02/17] little debugging --- src/app/auth/action.tsx | 10 ---------- src/app/auth/component/component.tsx | 6 +++--- 2 files changed, 3 insertions(+), 13 deletions(-) diff --git a/src/app/auth/action.tsx b/src/app/auth/action.tsx index e06c965..00f5fcd 100644 --- a/src/app/auth/action.tsx +++ b/src/app/auth/action.tsx @@ -70,16 +70,6 @@ export const AuthSignIn = async () => { return { error: 'Error signing in', url: null }; } -export async function usernameExisits(username: string): Promise { - const supabase = createClient(); - let { data, error } = await supabase - .rpc('is_username_exist', { - username: username, - }); - if (error) console.error(error) - return data; -} - export const checkEmailForOrganisation = ( credentials : { email: string , diff --git a/src/app/auth/component/component.tsx b/src/app/auth/component/component.tsx index 13f9eff..4d4c47c 100644 --- a/src/app/auth/component/component.tsx +++ b/src/app/auth/component/component.tsx @@ -1,5 +1,5 @@ import React, { FormEvent, use, useEffect, useState } from "react"; -import { usernameExisits } from "@/app/auth/action"; +import axios from "axios"; import { Label } from "@/components/ui/label" import { Input } from "@/components/ui/input" @@ -90,9 +90,9 @@ export function Component( props : Props) { return ; } setLoading(true); - const data = await usernameExisits(username) + const res = await axios.post('/api/rest/v1/isUsername', {username: username}); - if (data) { + if (res.data.state) { const nextUserSibling = current.username.nextElementSibling as HTMLElement; nextUserSibling.innerText = 'Username already exists'; } else { From bf52ee1f81b3604ff205c0b6e707f76241235a05 Mon Sep 17 00:00:00 2001 From: Anas-github-acc Date: Sat, 27 Jul 2024 14:42:34 +0530 Subject: [PATCH 03/17] debug --- src/app/form_create/page.tsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/app/form_create/page.tsx b/src/app/form_create/page.tsx index 576f45c..39a282b 100644 --- a/src/app/form_create/page.tsx +++ b/src/app/form_create/page.tsx @@ -42,11 +42,11 @@ export default function Page() { }, []); useEffect(() => { + if ( user ) { + console.log('fetching user data'); + getUserData(); + } return () => { - - if ( user ) { - getUserData(); - } }; }, [user]); From e2540a816f567340549a607c4b02408b2221711c Mon Sep 17 00:00:00 2001 From: Anas-github-acc Date: Mon, 29 Jul 2024 14:41:15 +0530 Subject: [PATCH 04/17] adding home page --- public/home/homebg.jpeg | Bin 0 -> 73214 bytes src/app/form_create/components/form.tsx | 6 +- src/app/home/layout.tsx | 16 ++ src/app/home/page.tsx | 347 ++++++++++++++++++++++++ src/app/layout.tsx | 2 - src/app/page.tsx | 7 +- src/components/navbar.jsx | 2 +- src/utils/supabase/middleware.ts | 2 + 8 files changed, 371 insertions(+), 11 deletions(-) create mode 100644 public/home/homebg.jpeg create mode 100644 src/app/home/layout.tsx create mode 100644 src/app/home/page.tsx diff --git a/public/home/homebg.jpeg b/public/home/homebg.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..ca7de7bf2f86e6da405a71287782cb0f8e7591f6 GIT binary patch literal 73214 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 nuqB7g~_3ZJ;8Gl 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 literal 0 HcmV?d00001 diff --git a/src/app/form_create/components/form.tsx b/src/app/form_create/components/form.tsx index babc943..e75669a 100644 --- a/src/app/form_create/components/form.tsx +++ b/src/app/form_create/components/form.tsx @@ -44,12 +44,12 @@ export function Form({
- - + +
- +
diff --git a/src/app/home/layout.tsx b/src/app/home/layout.tsx new file mode 100644 index 0000000..56953db --- /dev/null +++ b/src/app/home/layout.tsx @@ -0,0 +1,16 @@ +import React from 'react'; +import Navbar from "@/components/navbar" + + +interface RootLayoutProps { + children: React.ReactNode; +} + +export default function RootLayout({ children } : RootLayoutProps) { + return ( + <> + + {children} + + ) +} \ No newline at end of file diff --git a/src/app/home/page.tsx b/src/app/home/page.tsx new file mode 100644 index 0000000..efaf8cd --- /dev/null +++ b/src/app/home/page.tsx @@ -0,0 +1,347 @@ +import Link from "next/link" +import { Card, CardHeader, CardTitle, CardDescription, CardContent, CardFooter } from "@/components/ui/card" +import Image from "next/image" + +export default function Home() { + + return ( +
+
+
+

+ Welcome to the Coding Club +

+

+ Join our vibrant community of passionate coders and unlock a world of learning, collaboration, and growth. +

+ + Join Now + +
+
+
+
+
+
+

Upcoming Events

+

+ Check out our upcoming events and workshops to learn new skills, network with fellow coders, and have + fun! +

+
+
+
+ + + Intro to React Workshop + Learn the fundamentals of React.js in this hands-on workshop. + + +
+
+ +

June 15, 2024

+
+
+ +

6:00 PM - 8:00 PM

+
+
+ +

Online

+
+
+
+ + + Register + + +
+ + + Hackathon: Build a Web App + Join our 24-hour hackathon and build a web application from scratch. + + +
+
+ +

July 20-21, 2024

+
+
+ +

9:00 AM - 9:00 AM

+
+
+ +

Online

+
+
+
+ + + Register + + +
+ + + Intro to Data Structures + Dive into the fundamentals of data structures and algorithms. + + +
+
+ +

August 5, 2024

+
+
+ +

7:00 PM - 9:00 PM

+
+
+ +

Online

+
+
+
+ + + Register + + +
+
+
+
+
+
+
+
+

Club Resources

+

+ Explore our collection of tutorials, projects, and other resources to help you grow as a coder. +

+
+
+
+ + + Tutorials + Learn new technologies and programming languages. + + + +
Intro to JavaScript
+
+ Learn the fundamentals of JavaScript, the most popular programming language for the web. +
+ + +
React.js for Beginners
+
+ Get started with React, a popular JavaScript library for building user interfaces. +
+ + +
Python for Data Analysis
+
+ Explore the power of Python for data manipulation, visualization, and machine learning. +
+ +
+
+ + + Projects + Build real-world applications to showcase your skills. + + + +
Todo List App
+
+ Build a simple todo list application using HTML, CSS, and JavaScript. +
+ + +
Weather App
+
+ Create a weather application that fetches data from a weather API. +
+ + +
E-commerce Website
+
+ Build a full-stack e-commerce website with a shopping cart and checkout process. +
+ +
+
+ + + Community + Connect with fellow coders and get support from the community. + + + +
Discord Server
+
+ Join our vibrant Discord server to chat, ask questions, and collaborate with other members. +
+ + +
Meetups
+
+ Attend our local and virtual meetups to network, learn, and share your projects. +
+ + +
+
+
+
+
+
+ ) +} + +function CalendarIcon(props: React.JSX.IntrinsicAttributes & React.SVGProps) { + return ( + + + + + + + ) +} + + +function ClockIcon(props: React.JSX.IntrinsicAttributes & React.SVGProps) { + return ( + + + + + ) +} + + +function LocateIcon(props: React.JSX.IntrinsicAttributes & React.SVGProps) { + return ( + + + + + + + + ) +} + + +function XIcon(props: React.JSX.IntrinsicAttributes & React.SVGProps) { + return ( + + + + + ) +} \ No newline at end of file diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 757e2dc..4bb417c 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -6,7 +6,6 @@ import "./globals.css"; import { Analytics } from "@vercel/analytics/react" import { SpeedInsights } from "@vercel/speed-insights/next" import { cn } from "@/lib/utils" -import Navbar from "@/components/navbar" const inter = Inter({ subsets: ["latin"] }); @@ -47,7 +46,6 @@ export default function RootLayout({ defer src="https://cdn.jsdelivr.net/npm/ldrs/dist/auto/spiral.js" > - }>{children} diff --git a/src/app/page.tsx b/src/app/page.tsx index e12ee3b..27e381a 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -1,9 +1,6 @@ import Image from "next/image"; export default function Home() { - return ( -
-

Home

-
- ); + + return ; } \ No newline at end of file diff --git a/src/components/navbar.jsx b/src/components/navbar.jsx index f4a1802..ab72c29 100644 --- a/src/components/navbar.jsx +++ b/src/components/navbar.jsx @@ -18,7 +18,7 @@ function Navbar() { <>
- + IIITV Logo

Coding Club

diff --git a/src/utils/supabase/middleware.ts b/src/utils/supabase/middleware.ts index cce4279..ab45b1f 100644 --- a/src/utils/supabase/middleware.ts +++ b/src/utils/supabase/middleware.ts @@ -54,6 +54,8 @@ export async function updateSession(request: NextRequest) { } ) + if ( request.nextUrl.pathname === '/' ) return NextResponse.redirect(new URL('/home', request.nextUrl.href)) + if (request.nextUrl.pathname === '/auth/callback' || request.nextUrl.pathname === '/auth/confirm') return response From 6a22e7f43f118abca05ff2453e29d4d59c1342f4 Mon Sep 17 00:00:00 2001 From: Anas-github-acc Date: Mon, 29 Jul 2024 23:46:53 +0530 Subject: [PATCH 05/17] adding update password --- src/app/auth/component/component.tsx | 2 ++ src/app/auth/update_password/page.tsx | 1 + src/utils/supabase/middleware.ts | 2 +- 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/app/auth/component/component.tsx b/src/app/auth/component/component.tsx index cb98844..0f32c2d 100644 --- a/src/app/auth/component/component.tsx +++ b/src/app/auth/component/component.tsx @@ -175,6 +175,8 @@ export function Component( props : Props) { id="remember-me" name="remember-me" className="h-4 w-4 rounded text-primary focus:ring-primary" + checked + disabled />
))} + {auth === 'signup' && +
    + Your password must be +
  •   {validatePassword(password, 2)?:• } uppercase/lowercase and digits
  • +
  •   {validatePassword(password, 3)?:• } special characters like !@#$%^&*()_+
  • +
  •   {validatePassword(password, 1)?:• } at least 8 characters long
  • +
+ } + {auth === 'login' &&
@@ -214,7 +229,7 @@ function validateEmail(email: string): boolean { function validatePassword(password: string, customCheck: number = 0): boolean { const re = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[!@#$%^&*()_+])[A-Za-z\d!@#$%^&*()_+]{8,}$/; const special = /[!@#$%^&*()_+]/; - const upper_lower_digit = /^(?=.*[a-z])(?=.*[A-Z])(?=.x\d)[A-Za-z\d]{8,}$/; + const upper_lower_digit = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)/; if (!customCheck) return re.test(password); if (customCheck === 1) return password.length >= 8; if (customCheck === 2) return upper_lower_digit.test(password); diff --git a/src/app/auth/component/styles.module.css b/src/app/auth/component/styles.module.css index e13e8fd..77d1624 100644 --- a/src/app/auth/component/styles.module.css +++ b/src/app/auth/component/styles.module.css @@ -12,7 +12,7 @@ .inputicon { position:absolute; top: 50%; - color: rgba(var(--black-light), .45); + border-radius: 50%; font-size: 1rem; transform: translateY(-50%); transition: 0.5s ease; @@ -23,5 +23,11 @@ cursor: pointer; } .eyeicon:hover { - color: rgba(var(--black-light), .65); + background: rgba(var(--white), .03); +} +.mailicon { + left: 15px; +} +.passwordicon { + left: 15px; } \ No newline at end of file diff --git a/src/app/event/[id]/components/eventDetails.jsx b/src/app/event/[id]/components/eventDetails.jsx index fa81f57..8025efb 100644 --- a/src/app/event/[id]/components/eventDetails.jsx +++ b/src/app/event/[id]/components/eventDetails.jsx @@ -15,25 +15,24 @@ const montserratFont = Montserrat({weight: ["100","400"], subsets: ["latin"]}); function EventDetails(props){ - - const [isAdmin,setIsAdmin] = useState(true); //Set default to false - - const [event,setEvent] = useState(props.event); - const [eventName,setEventName] = useState(event.name); - const [eventDescription,setEventDescription] = useState(event.description); - const [registerUntilDate,setRegisterUntilDate] = useState(event.register_until); - const [registrationLink , setRegistrationLink] = useState(event.registration_link); - const [hostedRegistration , setHostedRegistration] = useState(event.hosted_registration); - const [hostLink, setHostLink] = useState(event.host_link); - const [daysLeftToRegister,setDaysLeftToRegister]= useState(CalculateDaysLeft(registerUntilDate)); - const [eventDate,setEventDate] = useState(event.date); - const [eventDuration , setEventDuration]=useState((CalculateEventDuration(event.duration))); - const [eventMode ,setEventMode] = useState(event.mode); - const [eventVenue ,setEventVenue] = useState(event.venue); - const [eventRequirements, setEventRequirements] = useState(event.requirements); - const [eventPrizes , setEventPrizes] = useState(event.prizes); - const [eventConvenors,setEventConvenors] = useState(event.convenors); - const [eventWinners,setEventWinners] = useState(event.winners); + const [isAdmin,setIsAdmin] = useState(true); + + const [event,setEvent] = useState(props.event || ''); + const [eventName,setEventName] = useState(event.name || "Event Name"); + const [eventDescription,setEventDescription] = useState(event.description || "No description available"); + const [registerUntilDate,setRegisterUntilDate] = useState(event.register_until || new Date()); + const [registrationLink , setRegistrationLink] = useState(event.registration_link || "https://www.registration.com"); + const [hostedRegistration , setHostedRegistration] = useState(event.hosted_registration || false); + const [hostLink, setHostLink] = useState(event.host_link || "https://www.hosted.com"); + const [daysLeftToRegister,setDaysLeftToRegister]= useState(CalculateDaysLeft(registerUntilDate) || "Registration closed"); + const [eventDate,setEventDate] = useState(event.date || new Date()); + const [eventDuration , setEventDuration]=useState((CalculateEventDuration(event.duration)) || "Not Specified"); + const [eventMode ,setEventMode] = useState(event.mode || false); + const [eventVenue ,setEventVenue] = useState(event.venue || "Online"); + const [eventRequirements, setEventRequirements] = useState(event.requirements || []); + const [eventPrizes , setEventPrizes] = useState(event.prizes || []); + const [eventConvenors,setEventConvenors] = useState(event.convenors || []); + const [eventWinners,setEventWinners] = useState(event.winners || {}); //To update the remaining registration time each second useEffect(()=>{ diff --git a/src/app/event/[id]/fetchEvent.jsx b/src/app/event/[id]/fetchEvent.jsx index e4ac05d..4a834d2 100644 --- a/src/app/event/[id]/fetchEvent.jsx +++ b/src/app/event/[id]/fetchEvent.jsx @@ -5,6 +5,7 @@ const useFetchEvent = (eventId) => { const [event, setEvent] = useState({}); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); + console.log(eventId); useEffect(() => { const fetchEvent = async () => { diff --git a/src/app/event/[id]/page.jsx b/src/app/event/[id]/page.jsx index 0e1e96b..0e01584 100644 --- a/src/app/event/[id]/page.jsx +++ b/src/app/event/[id]/page.jsx @@ -7,58 +7,59 @@ import Loading from '@/components/loading'; function Event({ params }) { const eventId = params.id; - // const { event, loading, error } = useFetchEvent(eventId); - // const router = useRouter(); + const { event, loading, error } = useFetchEvent(eventId); + const router = useRouter(); + console.log(event); - // if (loading) { - // return <> - // - // ; - // } + if (loading) { + return <> + + ; + } - // if (error) { - // console.error(error); - // router.push('/events'); - // return null; - // } + if (error) { + console.error(error); + router.push('/events'); + return null; + } // To start calling api delete the object below and uncomment the above code - const event = { - "id": 7, - "name": "Codestrike v6.0", - "description": `Join us for an exciting coding event organized by Coding Club IIITV, \nwhere teamwork and innovation take center stage! \nIn this unique competition, teams of three programmers will come together to \n solve complex coding challenges within a set timeframe. Participants will need to collaborate closely, leveraging each other's strengths to develop efficient and creative solutions. This event is designed to foster camaraderie, enhance problem-solving skills, and encourage effective communication among team members. Don't miss this opportunity to test your coding prowess, make new friends, and have a blast working together. Sign up now and be part of a thrilling coding adventure!`, - "date": "2024-08-05T15:30:00", - "duration": 60, - "mode": false, - "host_link": "https://www.hosted.com", - "venue": "Mess Hall", - "requirements": [ - "Laptop", - "Notebook", - "Pen", - "Pencil" - ], - "hosted_registration": true, - "register_until": "2024-08-05T15:32:30", - "registration_link": "https://www.registration.com", - "creator": "b4e05b86-df08-49d8-a118-51c205216401", - "prizes" : ["Rs. 10000","Rs. 5000", "Rs. 1000", - { - "Female Special":"Rs. 1000", - "FY Special":"Rs. 1000" - } - ], - "winners" : { - "Web Dev":["ABCDEGFHIJKL","ABCDEGFHIJKL","ABCDEGFHIJKL"], - "Cloud ":["ABCDEGFHIJKL"], - "CyberSecurity":["ABCDEGFHIJKL","ABCDEGFHIJKL"] - }, - "convenors":[ - "Devyash Saini","Devyash Saini","Devyash Saini","Devyash Saini" - ] - } + // const event = { + // "id": 7, + // "name": "Codestrike v6.0", + // "description": `Join us for an exciting coding event organized by Coding Club IIITV, \nwhere teamwork and innovation take center stage! \nIn this unique competition, teams of three programmers will come together to \n solve complex coding challenges within a set timeframe. Participants will need to collaborate closely, leveraging each other's strengths to develop efficient and creative solutions. This event is designed to foster camaraderie, enhance problem-solving skills, and encourage effective communication among team members. Don't miss this opportunity to test your coding prowess, make new friends, and have a blast working together. Sign up now and be part of a thrilling coding adventure!`, + // "date": "2024-08-05T15:30:00", + // "duration": 60, + // "mode": false, + // "host_link": "https://www.hosted.com", + // "venue": "Mess Hall", + // "requirements": [ + // "Laptop", + // "Notebook", + // "Pen", + // "Pencil" + // ], + // "hosted_registration": true, + // "register_until": "2024-08-05T15:32:30", + // "registration_link": "https://www.registration.com", + // "creator": "b4e05b86-df08-49d8-a118-51c205216401", + // "prizes" : ["Rs. 10000","Rs. 5000", "Rs. 1000", + // { + // "Female Special":"Rs. 1000", + // "FY Special":"Rs. 1000" + // } + // ], + // "winners" : { + // "Web Dev":["ABCDEGFHIJKL","ABCDEGFHIJKL","ABCDEGFHIJKL"], + // "Cloud ":["ABCDEGFHIJKL"], + // "CyberSecurity":["ABCDEGFHIJKL","ABCDEGFHIJKL"] + // }, + // "convenors":[ + // "Devyash Saini","Devyash Saini","Devyash Saini","Devyash Saini" + // ] + // } diff --git a/src/app/globals.css b/src/app/globals.css index 32f1f7c..9840bf0 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -32,6 +32,9 @@ --chart-3: #3366cc; --chart-4: #ffcc33; --chart-5: #ff9933; + + --black: 0, 0, 0; + --white: 255, 255, 255; } } diff --git a/src/app/home/layout.tsx b/src/app/home/layout.tsx index 56ca438..fbe7089 100644 --- a/src/app/home/layout.tsx +++ b/src/app/home/layout.tsx @@ -1,42 +1,33 @@ import React from 'react'; import Navbar from "@/components/navbar" import Footer from "@/components/footer" -<<<<<<< HEAD -======= import type { Metadata } from "next"; ->>>>>>> a53050d3b3abb1d3c6c5c28f33551fa418aba183 +import Head from 'next/head'; interface RootLayoutProps { children: React.ReactNode; } -<<<<<<< HEAD -======= -export const metadata: Metadata = { - title: "Coding Club IIITV", - description: "IIITV Coding Club Community Website | Workshops | Mentorship | Community", - openGraph: { - title: 'Coding Club IIITV', - description: 'IIITV Coding Club Community Website | Workshops | Mentorship | Community', - images: ["https://iiitvcc.vercel.app/LinkPreview.png"], - type: 'website', - locale: 'en_IN', - url: 'https://iiitvcc.vercel.app', - }, -}; - ->>>>>>> a53050d3b3abb1d3c6c5c28f33551fa418aba183 export default function RootLayout({ children } : RootLayoutProps) { return ( <> + + + + + + + + + + {children}