Add sign in layout
This commit is contained in:
parent
c5c462f420
commit
769ea33a46
36
package-lock.json
generated
36
package-lock.json
generated
@ -8,6 +8,7 @@
|
|||||||
"name": "procurment",
|
"name": "procurment",
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@hookform/resolvers": "^3.9.0",
|
||||||
"autoprefixer": "^10.4.20",
|
"autoprefixer": "^10.4.20",
|
||||||
"axios": "^1.7.4",
|
"axios": "^1.7.4",
|
||||||
"clsx": "^2.1.1",
|
"clsx": "^2.1.1",
|
||||||
@ -16,7 +17,9 @@
|
|||||||
"next-intl": "^3.17.2",
|
"next-intl": "^3.17.2",
|
||||||
"react": "^18",
|
"react": "^18",
|
||||||
"react-dom": "^18",
|
"react-dom": "^18",
|
||||||
"tailwind-merge": "^2.5.2"
|
"react-hook-form": "^7.52.2",
|
||||||
|
"tailwind-merge": "^2.5.2",
|
||||||
|
"zod": "^3.23.8"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/node": "^20",
|
"@types/node": "^20",
|
||||||
@ -160,6 +163,14 @@
|
|||||||
"tslib": "^2.4.0"
|
"tslib": "^2.4.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@hookform/resolvers": {
|
||||||
|
"version": "3.9.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@hookform/resolvers/-/resolvers-3.9.0.tgz",
|
||||||
|
"integrity": "sha512-bU0Gr4EepJ/EQsH/IwEzYLsT/PEj5C0ynLQ4m+GSHS+xKH4TfSelhluTgOaoc4kA5s7eCsQbM4wvZLzELmWzUg==",
|
||||||
|
"peerDependencies": {
|
||||||
|
"react-hook-form": "^7.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@humanwhocodes/config-array": {
|
"node_modules/@humanwhocodes/config-array": {
|
||||||
"version": "0.11.14",
|
"version": "0.11.14",
|
||||||
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz",
|
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz",
|
||||||
@ -4198,6 +4209,21 @@
|
|||||||
"react": "^18.3.1"
|
"react": "^18.3.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/react-hook-form": {
|
||||||
|
"version": "7.52.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.52.2.tgz",
|
||||||
|
"integrity": "sha512-pqfPEbERnxxiNMPd0bzmt1tuaPcVccywFDpyk2uV5xCIBphHV5T8SVnX9/o3kplPE1zzKt77+YIoq+EMwJp56A==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/react-hook-form"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": "^16.8.0 || ^17 || ^18 || ^19"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/react-is": {
|
"node_modules/react-is": {
|
||||||
"version": "16.13.1",
|
"version": "16.13.1",
|
||||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
|
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
|
||||||
@ -5378,6 +5404,14 @@
|
|||||||
"funding": {
|
"funding": {
|
||||||
"url": "https://github.com/sponsors/sindresorhus"
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"node_modules/zod": {
|
||||||
|
"version": "3.23.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/zod/-/zod-3.23.8.tgz",
|
||||||
|
"integrity": "sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==",
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/colinhacks"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
"lint": "next lint"
|
"lint": "next lint"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@hookform/resolvers": "^3.9.0",
|
||||||
"autoprefixer": "^10.4.20",
|
"autoprefixer": "^10.4.20",
|
||||||
"axios": "^1.7.4",
|
"axios": "^1.7.4",
|
||||||
"clsx": "^2.1.1",
|
"clsx": "^2.1.1",
|
||||||
@ -17,7 +18,9 @@
|
|||||||
"next-intl": "^3.17.2",
|
"next-intl": "^3.17.2",
|
||||||
"react": "^18",
|
"react": "^18",
|
||||||
"react-dom": "^18",
|
"react-dom": "^18",
|
||||||
"tailwind-merge": "^2.5.2"
|
"react-hook-form": "^7.52.2",
|
||||||
|
"tailwind-merge": "^2.5.2",
|
||||||
|
"zod": "^3.23.8"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/node": "^20",
|
"@types/node": "^20",
|
||||||
|
14
src/app/[locale]/sign-in/icons/sign-in_icon.svg
Normal file
14
src/app/[locale]/sign-in/icons/sign-in_icon.svg
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
<svg width="24.000000" height="24.000000" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||||
|
<desc>
|
||||||
|
Created with Pixso.
|
||||||
|
</desc>
|
||||||
|
<defs>
|
||||||
|
<clipPath id="clip51_17162">
|
||||||
|
<rect id="log-in-04" width="24.000000" height="24.000000" fill="white" fill-opacity="0"/>
|
||||||
|
</clipPath>
|
||||||
|
</defs>
|
||||||
|
<rect id="log-in-04" width="24.000000" height="24.000000" fill="#FFFFFF" fill-opacity="0"/>
|
||||||
|
<g clip-path="url(#clip51_17162)">
|
||||||
|
<path id="Icon" d="M12 8L16 12L12 16M3 12L16 12M3.33789 7C5.06641 4.01074 8.29883 2 12 2C17.5225 2 22 6.47754 22 12C22 17.5225 17.5225 22 12 22C8.29883 22 5.06641 19.9893 3.33789 17" stroke="#000000" stroke-opacity="1.000000" stroke-width="2.000000" stroke-linejoin="round"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 768 B |
38
src/app/[locale]/sign-in/page.tsx
Normal file
38
src/app/[locale]/sign-in/page.tsx
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
import Image from "next/image";
|
||||||
|
import sign_in_icon from "./icons/sign-in_icon.svg";
|
||||||
|
import { Link } from "@/shared/config/navigation";
|
||||||
|
import { Container } from "@/shared/ui";
|
||||||
|
import SignInForm from "@/widgets/forms/SignInForm";
|
||||||
|
|
||||||
|
const SignIn = () => {
|
||||||
|
return (
|
||||||
|
<Container>
|
||||||
|
<div className="h-full min-h-[800px] w-full flex justify-center">
|
||||||
|
<div className="flex flex-col items-center gap-6">
|
||||||
|
<div className="w-[48px] h-[48px] flex items-center justify-center rounded-sm border">
|
||||||
|
<Image src={sign_in_icon} alt="Sign In Icon" />
|
||||||
|
</div>
|
||||||
|
<div className="mb-2 flex flex-col items-center gap-2 text-center">
|
||||||
|
<h2 className="text-[24px] font-bold leading-8 text-gray-900">
|
||||||
|
Войдите в аккаунт
|
||||||
|
</h2>
|
||||||
|
<p className="text-gray-500">Пожалуйста, введите свои данные</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<SignInForm />
|
||||||
|
<p className="text-[14px] font-semibold leading-5 text-gray-500">
|
||||||
|
Еще нет аккаунта?{" "}
|
||||||
|
<Link
|
||||||
|
className="text-[14px] font-semibold leading-5 text-light-blue"
|
||||||
|
href="/sign-up"
|
||||||
|
>
|
||||||
|
Зарегистрируйтесь
|
||||||
|
</Link>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Container>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default SignIn;
|
@ -9,7 +9,7 @@ import { useState } from "react";
|
|||||||
interface IAuthInputProps extends React.InputHTMLAttributes<HTMLInputElement> {
|
interface IAuthInputProps extends React.InputHTMLAttributes<HTMLInputElement> {
|
||||||
isPassword?: boolean;
|
isPassword?: boolean;
|
||||||
label: string;
|
label: string;
|
||||||
error: string;
|
error?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const AuthInput: React.FC<IAuthInputProps> = ({
|
const AuthInput: React.FC<IAuthInputProps> = ({
|
||||||
|
73
src/widgets/forms/SignInForm.tsx
Normal file
73
src/widgets/forms/SignInForm.tsx
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
"use client";
|
||||||
|
import React, { FC, useState } from "react";
|
||||||
|
import { z } from "zod";
|
||||||
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
|
import AuthInput from "@/features/AuthInput";
|
||||||
|
import Loader from "@/shared/ui/Loader/Loader";
|
||||||
|
import Link from "next/link";
|
||||||
|
import { useForm } from "react-hook-form";
|
||||||
|
|
||||||
|
// interface SignInProps {
|
||||||
|
// isLoading: boolean;
|
||||||
|
// onSubmitFunc: () => void;
|
||||||
|
// noAccountError: Error | null;
|
||||||
|
// }
|
||||||
|
const SignInForm = ({}) => {
|
||||||
|
const signInFormScheme = z.object({
|
||||||
|
email: z.string().email("Неверный формат email"),
|
||||||
|
password: z.string().min(8, "Пароль должен содержать минимум 8 символов"),
|
||||||
|
});
|
||||||
|
|
||||||
|
type FormFields = z.infer<typeof signInFormScheme>;
|
||||||
|
|
||||||
|
const {
|
||||||
|
register,
|
||||||
|
handleSubmit,
|
||||||
|
formState: { errors },
|
||||||
|
} = useForm<FormFields>({
|
||||||
|
resolver: zodResolver(signInFormScheme),
|
||||||
|
});
|
||||||
|
|
||||||
|
const onSubmit = (data: FormFields) => {};
|
||||||
|
return (
|
||||||
|
<form className="mb-2 w-[360px] flex flex-col">
|
||||||
|
<div className="flex flex-col gap-5">
|
||||||
|
<AuthInput
|
||||||
|
type="email"
|
||||||
|
label="Email"
|
||||||
|
placeholder="Введите email"
|
||||||
|
error={errors.email?.message}
|
||||||
|
{...register("email", { required: true })}
|
||||||
|
/>
|
||||||
|
<AuthInput
|
||||||
|
isPassword
|
||||||
|
label="Пароль"
|
||||||
|
placeholder="Введите пароль"
|
||||||
|
error={errors.password?.message}
|
||||||
|
{...register("password", { required: true })}
|
||||||
|
/>
|
||||||
|
{errors.root && (
|
||||||
|
<div className="text-red-500">{errors.root.message}</div>
|
||||||
|
)}
|
||||||
|
<button
|
||||||
|
type="submit"
|
||||||
|
className="p-4 h-[50px] w-full font-bold leading-6 text-white bg-light-blue rounded-md"
|
||||||
|
// disabled={isLoading}
|
||||||
|
>
|
||||||
|
{/* {isLoading ? <Loader /> : "Войти"} */}
|
||||||
|
Войти
|
||||||
|
</button>
|
||||||
|
<div className="text-blue font-semibold pt-2 cursor-pointer">
|
||||||
|
<Link
|
||||||
|
href="/forgot-password-email"
|
||||||
|
className="text-blue font-semibold pt-2 cursor-pointer "
|
||||||
|
>
|
||||||
|
Забыли пароль?
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default SignInForm;
|
11
src/widgets/forms/icons/eye-off.svg
Normal file
11
src/widgets/forms/icons/eye-off.svg
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<g clip-path="url(#clip0_661_14568)">
|
||||||
|
<path d="M17.94 17.94C16.2306 19.243 14.1491 19.9649 12 20C5 20 1 12 1 12C2.24389 9.68192 3.96914 7.65663 6.06 6.06003M9.9 4.24002C10.5883 4.0789 11.2931 3.99836 12 4.00003C19 4.00003 23 12 23 12C22.393 13.1356 21.6691 14.2048 20.84 15.19M14.12 14.12C13.8454 14.4148 13.5141 14.6512 13.1462 14.8151C12.7782 14.9791 12.3809 15.0673 11.9781 15.0744C11.5753 15.0815 11.1752 15.0074 10.8016 14.8565C10.4281 14.7056 10.0887 14.4811 9.80385 14.1962C9.51897 13.9113 9.29439 13.572 9.14351 13.1984C8.99262 12.8249 8.91853 12.4247 8.92563 12.0219C8.93274 11.6191 9.02091 11.2219 9.18488 10.8539C9.34884 10.4859 9.58525 10.1547 9.88 9.88003" stroke="#979797" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
<path d="M1 1L23 23" stroke="#979797" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
</g>
|
||||||
|
<defs>
|
||||||
|
<clipPath id="clip0_661_14568">
|
||||||
|
<rect width="24" height="24" fill="white"/>
|
||||||
|
</clipPath>
|
||||||
|
</defs>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 1.0 KiB |
4
src/widgets/forms/icons/eye.svg
Normal file
4
src/widgets/forms/icons/eye.svg
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M1 12C1 12 5 4 12 4C19 4 23 12 23 12C23 12 19 20 12 20C5 20 1 12 1 12Z" stroke="#979797" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
<path d="M12 15C13.6569 15 15 13.6569 15 12C15 10.3431 13.6569 9 12 9C10.3431 9 9 10.3431 9 12C9 13.6569 10.3431 15 12 15Z" stroke="#979797" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 474 B |
Loading…
Reference in New Issue
Block a user