diff --git a/package-lock.json b/package-lock.json index 036096c..e857530 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,6 +12,7 @@ "@emotion/styled": "^11.12.0", "@mui/material": "^5.16.4", "@radix-ui/react-avatar": "^1.1.0", + "@radix-ui/react-checkbox": "^1.1.1", "@radix-ui/react-dialog": "^1.1.1", "@radix-ui/react-dropdown-menu": "^2.1.1", "@radix-ui/react-icons": "^1.3.0", @@ -24,6 +25,7 @@ "axios": "^1.7.2", "class-variance-authority": "^0.7.0", "clsx": "^2.1.1", + "formik": "^2.4.6", "ldrs": "^1.0.2", "lucide-react": "^0.408.0", "next": "14.2.5", @@ -37,7 +39,8 @@ "sass": "^1.77.8", "scss": "^0.2.4", "tailwind-merge": "^2.4.0", - "tailwindcss-animate": "^1.0.7" + "tailwindcss-animate": "^1.0.7", + "yup": "^1.4.0" }, "devDependencies": { "@types/node": "^20", @@ -976,6 +979,36 @@ } } }, + "node_modules/@radix-ui/react-checkbox": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-checkbox/-/react-checkbox-1.1.1.tgz", + "integrity": "sha512-0i/EKJ222Afa1FE0C6pNJxDq1itzcl3HChE9DwskA4th4KRse8ojx8a1nVcOjwJdbpDLcz7uol77yYnQNMHdKw==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.0", + "@radix-ui/react-compose-refs": "1.1.0", + "@radix-ui/react-context": "1.1.0", + "@radix-ui/react-presence": "1.1.0", + "@radix-ui/react-primitive": "2.0.0", + "@radix-ui/react-use-controllable-state": "1.1.0", + "@radix-ui/react-use-previous": "1.1.0", + "@radix-ui/react-use-size": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-collection": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.1.0.tgz", @@ -1487,6 +1520,21 @@ } } }, + "node_modules/@radix-ui/react-use-previous": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-previous/-/react-use-previous-1.1.0.tgz", + "integrity": "sha512-Z/e78qg2YFnnXcW88A4JmTtm4ADckLno6F7OXotmkQfeuCVaKuYzqAATPhVzl3delXE7CxIV8shofPn3jPc5Og==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-use-rect": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@radix-ui/react-use-rect/-/react-use-rect-1.1.0.tgz", @@ -1678,6 +1726,16 @@ "tslib": "^2.4.0" } }, + "node_modules/@types/hoist-non-react-statics": { + "version": "3.3.5", + "resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.5.tgz", + "integrity": "sha512-SbcrWzkKBw2cdwRTwQAswfpB9g9LJWfjtUeW/jvNwbhC8cpmmNYVePa+ncbUe0rGTQ7G3Ff6mYUN2VMfLVr+Sg==", + "license": "MIT", + "dependencies": { + "@types/react": "*", + "hoist-non-react-statics": "^3.3.0" + } + }, "node_modules/@types/node": { "version": "20.14.10", "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.10.tgz", @@ -2363,6 +2421,15 @@ } } }, + "node_modules/deepmerge": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-2.2.1.tgz", + "integrity": "sha512-R9hc1Xa/NOBi9WRVUWg19rl1UB7Tt4kuPd+thNJgFZoxXsTz7ncaPaeIm+40oSGuP33DfMb4sZt1QIGiJzC4EA==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", @@ -2590,6 +2657,31 @@ "node": ">=12.20.0" } }, + "node_modules/formik": { + "version": "2.4.6", + "resolved": "https://registry.npmjs.org/formik/-/formik-2.4.6.tgz", + "integrity": "sha512-A+2EI7U7aG296q2TLGvNapDNTZp1khVt5Vk0Q/fyfSROss0V/V6+txt2aJnwEos44IxTCW/LYAi/zgWzlevj+g==", + "funding": [ + { + "type": "individual", + "url": "https://opencollective.com/formik" + } + ], + "license": "Apache-2.0", + "dependencies": { + "@types/hoist-non-react-statics": "^3.3.1", + "deepmerge": "^2.1.1", + "hoist-non-react-statics": "^3.3.0", + "lodash": "^4.17.21", + "lodash-es": "^4.17.21", + "react-fast-compare": "^2.0.1", + "tiny-warning": "^1.0.2", + "tslib": "^2.0.0" + }, + "peerDependencies": { + "react": ">=16.8.0" + } + }, "node_modules/fraction.js": { "version": "4.3.7", "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz", @@ -2938,6 +3030,18 @@ "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", "license": "MIT" }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "license": "MIT" + }, + "node_modules/lodash-es": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", + "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==", + "license": "MIT" + }, "node_modules/loose-envify": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", @@ -3562,6 +3666,12 @@ "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", "license": "MIT" }, + "node_modules/property-expr": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/property-expr/-/property-expr-2.0.6.tgz", + "integrity": "sha512-SVtmxhRE/CGkn3eZY1T6pC8Nln6Fr/lu1mKSgRud0eC73whjGfoAogbn78LkD8aFL0zz3bAFerKSnOl7NlErBA==", + "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", @@ -3613,6 +3723,12 @@ "react": "^18.3.1" } }, + "node_modules/react-fast-compare": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-2.0.4.tgz", + "integrity": "sha512-suNP+J1VU1MWFKcyt7RtjiSWUjvidmQSlqu+eHslq+342xCbGTYmC0mEhPCOHxlW0CywylOC1u2DFAT+bv4dBw==", + "license": "MIT" + }, "node_modules/react-icons": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-5.2.1.tgz", @@ -4257,6 +4373,18 @@ "node": ">=0.8" } }, + "node_modules/tiny-case": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tiny-case/-/tiny-case-1.0.3.tgz", + "integrity": "sha512-Eet/eeMhkO6TX8mnUteS9zgPbUMQa4I6Kkp5ORiBD5476/m+PIRiumP5tmh5ioJpH7k51Kehawy2UDfsnxxY8Q==", + "license": "MIT" + }, + "node_modules/tiny-warning": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz", + "integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==", + "license": "MIT" + }, "node_modules/to-fast-properties": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", @@ -4278,6 +4406,12 @@ "node": ">=8.0" } }, + "node_modules/toposort": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/toposort/-/toposort-2.0.2.tgz", + "integrity": "sha512-0a5EOkAUp8D4moMi2W8ZF8jcga7BgZd91O/yabJCFY8az+XSzeGyTKs0Aoo897iV1Nj6guFq8orWDS96z91oGg==", + "license": "MIT" + }, "node_modules/tr46": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", @@ -4297,6 +4431,18 @@ "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==", "license": "0BSD" }, + "node_modules/type-fest": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", + "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/typescript": { "version": "5.5.3", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.3.tgz", @@ -4594,6 +4740,18 @@ "engines": { "node": ">= 14" } + }, + "node_modules/yup": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/yup/-/yup-1.4.0.tgz", + "integrity": "sha512-wPbgkJRCqIf+OHyiTBQoJiP5PFuAXaWiJK6AmYkzQAh5/c2K9hzSApBZG5wV9KoKSePF7sAxmNSvh/13YHkFDg==", + "license": "MIT", + "dependencies": { + "property-expr": "^2.0.5", + "tiny-case": "^1.0.3", + "toposort": "^2.0.2", + "type-fest": "^2.19.0" + } } } } diff --git a/package.json b/package.json index f5234fc..1395dd8 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,7 @@ "@emotion/styled": "^11.12.0", "@mui/material": "^5.16.4", "@radix-ui/react-avatar": "^1.1.0", + "@radix-ui/react-checkbox": "^1.1.1", "@radix-ui/react-dialog": "^1.1.1", "@radix-ui/react-dropdown-menu": "^2.1.1", "@radix-ui/react-icons": "^1.3.0", diff --git a/public/home/homebg.jpeg b/public/home/homebg.jpeg new file mode 100644 index 0000000..ca7de7b Binary files /dev/null and b/public/home/homebg.jpeg differ diff --git a/public/home/placeholder.png b/public/home/placeholder.png new file mode 100644 index 0000000..d973bc2 Binary files /dev/null and b/public/home/placeholder.png differ diff --git a/src/app/api/rest/v1/isUsername/route.ts b/src/app/api/rest/v1/isUsername/route.ts index 1be0ff4..6e60734 100644 --- a/src/app/api/rest/v1/isUsername/route.ts +++ b/src/app/api/rest/v1/isUsername/route.ts @@ -1,29 +1,25 @@ import {NextRequest, NextResponse} from "next/server"; +import { createClient } from "@/utils/supabase/server"; export async function POST(req: NextRequest): Promise { - let response = NextResponse.next({ - request: { - headers: req.headers, - }, - }) + try { + const supabase = createClient(); + const body = await req.json(); + if (!body.username) { + return NextResponse.json({ error: 'username is required' }, { status: 400 }); + } - const body = await req.json() + const { data, error } = await supabase + .rpc('is_username_exist', + { username: body.username } + ); - if ( !body.username ) { - return NextResponse.json({ error: 'username is required' }) - } + if (error) { + return NextResponse.json({ error: error.message }, { status: 500 }); + } - let res = await fetch(`${process.env.NEXT_PUBLIC_SUPABASE_URL}/rest/v1/rpc/is_username_exist`, { - method: 'POST', - headers: { - "apikey": process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!, - "Authorization": `Bearer ${process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!}`, - "Content-Type": "application/json", - }, - body: JSON.stringify(body) - }); - - let data = await res.json(); - - return NextResponse.json({ state: data }); + return NextResponse.json({ state: data }, { status: 200 }); + } catch (error: any) { + return NextResponse.json({ error: error.message }, { status: 500 }); + } } \ No newline at end of file diff --git a/src/app/api/update-password/route.ts b/src/app/api/update-password/route.ts new file mode 100644 index 0000000..c6f45c0 --- /dev/null +++ b/src/app/api/update-password/route.ts @@ -0,0 +1,19 @@ +import {NextRequest, NextResponse} from "next/server"; +import { cookies } from 'next/headers'; +import {createClient} from "@/utils/supabase/server"; + +export async function GET(req: NextRequest) { + const requestUrl = new URL(req.nextUrl.href) + const code = requestUrl.searchParams.get('code') + + if( code ) { + const supabase = createClient() + const { error } = await supabase.auth.exchangeCodeForSession(code) + + return NextResponse.redirect(new URL(`${req.nextUrl.origin}/auth/update_password`, req.nextUrl.href)) + } + + console.log({error : 'ERROR: Invalid auth code or no auth code found'}, { status: 500 }) + + return NextResponse.redirect(new URL(`${req.nextUrl.origin}/auth`, req.nextUrl.href)) +} \ No newline at end of file diff --git a/src/app/auth/component/component.tsx b/src/app/auth/component/component.tsx index 3a5579f..0f32c2d 100644 --- a/src/app/auth/component/component.tsx +++ b/src/app/auth/component/component.tsx @@ -1,9 +1,11 @@ import React, { FormEvent, use, useEffect, useState } from "react"; +import Link from "next/link"; import axios from "axios"; import { Label } from "@/components/ui/label" import { Input } from "@/components/ui/input" import { Button } from "@/components/ui/button" +import { Checkbox } from "@/components/ui/checkbox" import Loader from '@/components/ui/loader' import { VscEye, VscEyeClosed } from "react-icons/vsc" @@ -165,6 +167,27 @@ export function Component( props : Props) { setRevealPassword(!revealPassword)}>{revealPassword?:} ))} + + {auth === 'login' && +
+
+ + +
+
+ + Forgot your password? + +
+
}
+
+ + + + Return to Login + + + + +

{successMsg}

+ + + {errorMsg && } + + ); +}; + +export default ResetPassword; \ No newline at end of file diff --git a/src/app/auth/update_password/page.tsx b/src/app/auth/update_password/page.tsx new file mode 100644 index 0000000..6c1073e --- /dev/null +++ b/src/app/auth/update_password/page.tsx @@ -0,0 +1,76 @@ +'use client'; + +import React, { useState } from "react" +import { supabase } from "@/utils/supabase/client" +import { useRouter } from "next/navigation" + +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 ErrorDialog from "@/components/error_dialog" +import Link from "next/link" + +export default function Update_password() { + const router = useRouter() + const [errorMsg, setErrorMsg] = useState(null) + const [loading, setLoading] = useState(false) + + async function updatePassword(e: React.FormEvent) { + e.preventDefault() + setLoading(true) + if( e.currentTarget.password.value !== e.currentTarget.confirmPassword.value ) { + setErrorMsg("Passwords do not match") + setLoading(false) + return + } + const { error } = await supabase.auth.updateUser({ + password: e.currentTarget.password.value, + }); + setLoading(false) + + if (error) { + setErrorMsg(error.message) + } else { + router.replace("/form_create") + } + } + + + return ( +
+
+
+

Update Password

+

Enter a new password to update your account.

+
+
+
+ + +
+
+ + +
+
+ +
+
+
+ + Back to Reset Password + +
+
+ {errorMsg && } +
+ ) +} \ No newline at end of file diff --git a/src/app/form_create/components/dropdown_menu.tsx b/src/app/form_create/components/dropdown_menu.tsx index e92d885..22389fe 100644 --- a/src/app/form_create/components/dropdown_menu.tsx +++ b/src/app/form_create/components/dropdown_menu.tsx @@ -21,7 +21,7 @@ export function Dropdown_Menu({ <> -