summaryrefslogtreecommitdiff
path: root/src/components/header/authdialog
diff options
context:
space:
mode:
Diffstat (limited to 'src/components/header/authdialog')
-rw-r--r--src/components/header/authdialog/LoginForm.tsx23
-rw-r--r--src/components/header/authdialog/RegisterForm.tsx115
-rw-r--r--src/components/header/authdialog/ResetForm.tsx23
-rw-r--r--src/components/header/authdialog/register.ts69
4 files changed, 230 insertions, 0 deletions
diff --git a/src/components/header/authdialog/LoginForm.tsx b/src/components/header/authdialog/LoginForm.tsx
new file mode 100644
index 0000000..c5b606c
--- /dev/null
+++ b/src/components/header/authdialog/LoginForm.tsx
@@ -0,0 +1,23 @@
+import { Button } from '@/components/ui/button';
+import GoogleIcon from '../../../../public/icons/google.svg';
+import { InputField } from '@/components/ui/inputfield';
+import { Input } from '@/components/ui/input';
+export default function LoginForm() {
+ return (
+ <>
+ <div className="gap-5 flex flex-col h-[148px] w-[310px]">
+ <Button className="w-full bg-white hover:bg-white hover:text-black">
+ <GoogleIcon />
+ <span className="text-black text-sm">
+ Войти через Google
+ </span>
+ </Button>
+ <div className="gap-[10px] flex-col flex h-[88px]">
+ <InputField placeholder="Никнейм или почта" />
+ <InputField placeholder="Пароль" />
+ </div>
+ </div>
+ <Button className="w-full gap-[10px]">Войти</Button>
+ </>
+ );
+}
diff --git a/src/components/header/authdialog/RegisterForm.tsx b/src/components/header/authdialog/RegisterForm.tsx
new file mode 100644
index 0000000..20a7c14
--- /dev/null
+++ b/src/components/header/authdialog/RegisterForm.tsx
@@ -0,0 +1,115 @@
+'use client';
+import { useState } from 'react';
+import { Button } from '@/components/ui/button';
+import GoogleIcon from '../../../../public/icons/google.svg';
+import { InputField } from '@/components/ui/inputfield';
+import { validate, registerUser } from './register';
+import { useAuthContext } from '@/lib/contexts/Auth.context';
+
+export default function RegisterForm() {
+ const [errors, setErrors] = useState<any>({});
+ const [loading, setLoading] = useState(false);
+ const { setUser } = useAuthContext();
+ const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
+ e.preventDefault();
+ setLoading(true);
+ setErrors({});
+
+ const formData = new FormData(e.currentTarget);
+ const username = formData.get('username')?.toString() || '';
+ const email = formData.get('email')?.toString() || '';
+ const password = formData.get('password')?.toString() || '';
+ const passwordConfirm =
+ formData.get('passwordConfirm')?.toString() || '';
+
+ const validationErrors = validate(
+ username,
+ email,
+ password,
+ passwordConfirm,
+ );
+
+ if (Object.keys(validationErrors).length > 0) {
+ setErrors(validationErrors);
+ setLoading(false);
+ return;
+ }
+
+ const { data, error } = await registerUser(username, email, password);
+
+ if (error) {
+ setErrors(error);
+ } else if (data) {
+ setUser({
+ id: data.id,
+ username: data.username,
+ });
+ }
+
+ setLoading(false);
+ };
+
+ return (
+ <form
+ onSubmit={handleSubmit}
+ className="flex flex-col gap-5 min-w-[310px] w-fit"
+ >
+ <Button className="w-full bg-white hover:bg-white hover:text-black">
+ <GoogleIcon />
+ <span className="text-black">Войти через Google</span>
+ </Button>
+
+ <div className="flex flex-col gap-2.5">
+ <div className="flex flex-col ">
+ <InputField placeholder="Никнейм" name="username" />
+ {errors.username && (
+ <p className="text-red pl-5 text-[12px] leading-[16px] mt-[5px]">
+ {errors.username}
+ </p>
+ )}
+ </div>
+
+ <div className="flex flex-col">
+ <InputField placeholder="E-mail" name="email" />
+ {errors.email && (
+ <p className="text-red pl-5 text-[12px] leading-[16px] mt-[5px]">
+ {errors.email}
+ </p>
+ )}
+ </div>
+
+ <div className="flex flex-col ">
+ <InputField
+ placeholder="Пароль"
+ type="password"
+ name="password"
+ />
+ {errors.password && (
+ <p className="text-red pl-5 text-[12px] leading-[16px] mt-[5px]">
+ {errors.password}
+ </p>
+ )}
+ </div>
+
+ <div className="flex flex-col ">
+ <InputField
+ placeholder="Повторите пароль"
+ type="password"
+ name="passwordConfirm"
+ />
+ {errors.passwordConfirm && (
+ <p className="text-red pl-5 text-[12px] leading-[16px] mt-[5px]">
+ {errors.passwordConfirm}
+ </p>
+ )}
+ </div>
+ </div>
+
+ {errors.general && <p className="text-red ">{errors.general}</p>}
+
+ <Button type="submit" className="w-full" disabled={loading}>
+ {loading ? 'Регистрация...' : 'Зарегистрироваться'}
+ </Button>
+ </form>
+ );
+}
diff --git a/src/components/header/authdialog/ResetForm.tsx b/src/components/header/authdialog/ResetForm.tsx
new file mode 100644
index 0000000..42ca1b2
--- /dev/null
+++ b/src/components/header/authdialog/ResetForm.tsx
@@ -0,0 +1,23 @@
+import { Button } from '@/components/ui/button';
+import GoogleIcon from '../../../../public/icons/google.svg';
+import { InputField } from '@/components/ui/inputfield';
+import { Input } from '@/components/ui/input';
+export default function ResetForm() {
+ return (
+ <>
+ <div className="flex gap-5 flex-col">
+ <div className="flex flex-col w-[310px] gap-5">
+ <span className="">ВОССТАНОВЛЕНИЕ ПАРОЛЯ</span>
+ <div className=" gap-2.5 flex flex-col">
+ <span className="text-sm">
+ Введите никнейм или почту, с помощью которых входите
+ в аккаунт.
+ </span>
+ <InputField placeholder="Никнейм или почта"></InputField>
+ </div>
+ </div>
+ <Button className="w-full">Восстановить</Button>
+ </div>
+ </>
+ );
+}
diff --git a/src/components/header/authdialog/register.ts b/src/components/header/authdialog/register.ts
new file mode 100644
index 0000000..bcbc21b
--- /dev/null
+++ b/src/components/header/authdialog/register.ts
@@ -0,0 +1,69 @@
+export const validate = (
+ username: string,
+ email: string,
+ password: string,
+ passwordConfirm: string,
+) => {
+ const newErrors: any = {};
+
+ if (!username) {
+ newErrors.username = 'Введите никнейм';
+ } else if (username.length < 3) {
+ newErrors.username = 'Минимум 3 символа.';
+ } else if (username.length > 32) {
+ newErrors.username = 'Максимум 32 символа';
+ }
+
+ if (!email) {
+ newErrors.email = 'Введите email.';
+ } else {
+ const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
+ if (!emailRegex.test(email)) newErrors.email = 'Некорректный email';
+ if (email.length > 254) newErrors.email = 'Слишком длинный email.';
+ }
+
+ if (!password) {
+ newErrors.password = 'Введите пароль.';
+ } else if (password.length < 8) {
+ newErrors.password = 'Необходимо минимум 8 символов.';
+ } else {
+ const hasLetter = /[A-Za-z]/.test(password);
+ const hasNumber = /\d/.test(password);
+ const hasSymbol = /[^\w\s]/.test(password);
+
+ if (!(hasLetter && hasNumber && hasSymbol)) {
+ newErrors.password = 'Попробуйте сочетание букв, цифр и символов.';
+ }
+ }
+
+ if (password !== passwordConfirm) {
+ newErrors.passwordConfirm = 'пароли не совпадают.';
+ }
+
+ return newErrors;
+};
+
+export const registerUser = async (
+ username: string,
+ email: string,
+ password: string,
+) => {
+ try {
+ const res = await fetch('http://localhost:8000/api/auth/register', {
+ method: 'POST',
+ headers: { 'Content-Type': 'application/json' },
+ body: JSON.stringify({ username, email, password }),
+ });
+
+ const data = await res.json();
+
+ if (!res.ok) {
+ const { field, message } = data.detail;
+ return { error: { [field]: message } };
+ }
+
+ return { data };
+ } catch (err: any) {
+ return { error: { general: err.message } };
+ }
+};