/
durovcode
/
Frontend
Обзор
Документация
Войти
/
durovcode
/
Frontend
Код
Запросы
0
Задачи
Пакеты
0
Релизы
0
Аналитика
master
src/pages/auth.tsx
340 строк
14 KB
Alch3m1st
Add Docker
22 сен 2024, 01:25
22 сен 2024, 01:25
f92ba9d
Код
Авторство
О чём код?
"use client" import { Input } from '@/components/ui/input' import duck4 from '/duck4.gif' import { useState } from 'react' import Confetti from 'react-confetti'; import { toast } from "sonner" import { Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectTrigger, SelectValue, } from "@/components/ui/select" import { InputOTP, InputOTPGroup, InputOTPSeparator, InputOTPSlot, } from "@/components/ui/input-otp" import React from 'react'; import { error } from 'console'; const baseUrl = import.meta.env.REACT_APP_API_BASE_URL; const ConfettiButton = ({ isAuth, setIsOtp, emailValue, passwordValue, nameValue, roleValue }) => { const [showConfetti, setShowConfetti] = useState(false); // const [csrf, setCsrf] = useState(null); const handleMouseEnter = () => { setShowConfetti(true); }; const handleMouseLeave = () => { setShowConfetti(false); }; const authUser = () => { fetch(`${import.meta.env.VITE_API_BASE_URL}${import.meta.env.VITE_API_PATH}/account/auth`, { method: "POST", credentials: 'same-origin', mode: "cors", headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ "email": emailValue, "passwd": passwordValue }) }) .then(response => response.json()) .then(result => { if (result["ok"]) { if (result["otp"]) { setIsOtp(true); localStorage.setItem("otpJwt", result["token"]); } else { localStorage.setItem("jwt", result["token"]); setTimeout(() => { window.location.href = "/profile/" }, 1000) toast.success("Прекрасно! Вы авторизованы!", { action: { label: "Скрыть" }, }) } } else { toast.error("Ошибочка!", { description: result["detail"], action: { label: "Скрыть" }, }) } }) .catch(error => { console.error('Error:', error); }); } const registerUser = () => { console.log(roleValue); console.log( nameValue, emailValue, passwordValue ); fetch(`${import.meta.env.VITE_API_BASE_URL}${import.meta.env.VITE_API_PATH}/account/create`, { method: "POST", credentials: 'include', mode: "cors", headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ "email": emailValue, "passwd": passwordValue, "name": nameValue, "role": roleValue }) }) .then(response => response.json()) .then(result => { if (result["ok"]) { toast.success("Прекрасно! Теперь авторизуйтесь с этими данными", { action: { label: "Скрыть" }, }); } else { toast.error("Ошибочка! Возможно, пароль слишком простой, или какие-то данные не были указаны", { description: result["detail"], action: { label: "Скрыть" }, }); } }) .catch(error => { console.error('Error:', error); }); } return ( <div className="relative"> {showConfetti && ( <div className='fixed top-0 left-0'> <Confetti width={window.innerWidth} height={window.innerHeight} recycle={false} /> </div> )} {!isAuth ? ( <button className="pl-10 pr-10 p-2 text-white rounded-lg transition ease-in-out delay-150 bg-blue-500 hover:-translate-y-1 hover:scale-110 hover:bg-indigo-500 duration-300" onMouseEnter={handleMouseEnter} onMouseLeave={handleMouseLeave} onClick={() => { authUser() }} > Поехали! </button> ) : ( <button className="pl-10 pr-10 p-2 text-white rounded-lg transition ease-in-out delay-150 bg-blue-500 hover:-translate-y-1 hover:scale-110 hover:bg-indigo-500 duration-300" onMouseEnter={handleMouseEnter} onMouseLeave={handleMouseLeave} onClick={() => { registerUser() }} > Поехали! </button> )} </div> ); }; export const Auth = () => { const [isAuth, setIsAuth] = useState(false); const [isOtp, setIsOtp] = useState(false); const [otpValue, setOtpValue] = React.useState(""); const [emailValue, setEmailValue] = React.useState(""); const [nameValue, setNameValue] = React.useState(""); const [passwordValue, setPasswordValue] = React.useState("") const [roleValue, setRoleValue] = React.useState("") React.useEffect(() => { if (localStorage.getItem("jwt")) { window.location.href = "/profile/" } }, []); function checkOtp(otp) { fetch(`${import.meta.env.VITE_API_BASE_URL}${import.meta.env.VITE_API_PATH}/account/verify`, { method: "POST", credentials: 'include', mode: "cors", headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${localStorage.getItem("otpJwt")}` }, body: JSON.stringify({ 'otp': otp }) }) .then(response => response.json()) .then(result => { if (result["ok"]) { localStorage.setItem("jwt", result["token"]); window.location.href = "/"; } else { toast.error("Ошибочка!", { description: result["detail"], action: { label: "Скрыть" }, }); } }) .catch(error => { console.error('Error:', error); }); } return ( <> <div className="mt-10 w-full flex items-center justify-center"> <div className='flex flex-col items-center max-w-[300px]'> <img src={duck4} className="w-20 h-20" alt="gif" /> <br /> {isOtp ? ( <> <h1 className="text-center scroll-m-20 text-4xl font-extrabold tracking-tight lg:text-4xl"> Введи код <br /> из приложения! </h1> <br /> <div className='flex w-full flex-col gap-6 flex flex-col items-center justify-center'> <div className="space-y-2"> <InputOTP maxLength={6} value={otpValue} onChange={(value) => { setOtpValue(value) if (value.length == 6) { checkOtp(value); } }} > <InputOTPGroup> <InputOTPSlot index={0} /> <InputOTPSlot index={1} /> <InputOTPSlot index={2} /> <InputOTPSlot index={3} /> <InputOTPSlot index={4} /> <InputOTPSlot index={5} /> </InputOTPGroup> </InputOTP> <div className="text-center text-sm"> <>Enter your one-time password.</> </div> </div> </div> </> ) : isAuth ? ( <> <h1 className="scroll-m-20 text-4xl font-extrabold tracking-tight lg:text-4xl"> Давай познакомимся <br /> ближе! </h1> <br /> <div className='flex w-full flex-col gap-6'> <div> <p className='text-sm'>Как тебя зовут?</p> <Input onChange={(e) => setNameValue(e.target.value)} type="text" placeholder="Твоё имя" /> <p className='text-sm text-gray-400'>Укажи любое имя, или ник</p> </div> <div> <p className='text-sm'>Укажи почту</p> <Input onChange={(e) => setEmailValue(e.target.value)} type="email" placeholder="Email" /> </div> <div> <p className='text-sm'>Придумай сложный пароль</p> <Input onChange={(e) => setPasswordValue(e.target.value)} type="password" placeholder="Пароль" /> </div> <div> <p className='text-sm'>Укажи роль</p> <Select onValueChange={(e) => { setRoleValue(e) }}> <SelectTrigger className="w-full"> <SelectValue placeholder="Твоя роль..." /> </SelectTrigger> <SelectContent> <SelectGroup> <SelectItem value="student">Студент</SelectItem> <SelectItem value="lecturer">Преподаватель</SelectItem> </SelectGroup> </SelectContent> </Select> </div> <p onClick={() => { setIsAuth(!isAuth) }} className="w-fit text-sm text-gray-400 cursor-pointer hover:text-black hover:border-b-4">Уже есть профиль</p> <div className='flex items-center justify-center mb-10'> <ConfettiButton isAuth={isAuth} setIsOtp={setIsOtp} roleValue={roleValue} passwordValue={passwordValue} emailValue={emailValue} nameValue={nameValue} /> </div> </div> </> ) : ( <> <h1 className="scroll-m-20 text-4xl font-extrabold tracking-tight lg:text-4xl"> И вот мы <br /> встретились снова! </h1> <br /> <div className='flex w-full flex-col gap-6'> <div> <p className='text-sm'>Напиши почту</p> <Input onChange={(e) => setEmailValue(e.target.value)} type="email" placeholder="Email" /> </div> <div> <p className='text-sm'>Вспомни свой пароль</p> <Input onChange={(e) => setPasswordValue(e.target.value)} type="password" placeholder="Пароль" /> </div> <p onClick={() => { setIsAuth(!isAuth) }} className="w-fit text-sm text-gray-400 cursor-pointer hover:text-black hover:border-b-4">Ещё не использовал сервис? Создай профиль</p> <div className='flex items-center justify-center mb-10'> <ConfettiButton isAuth={isAuth} setIsOtp={setIsOtp} roleValue={roleValue} passwordValue={passwordValue} emailValue={emailValue} nameValue={nameValue} /> </div> </div> </> )} </div> </div> </> ) }