add login, register layout
This commit is contained in:
@@ -39,3 +39,31 @@ export async function testConnect() {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
export async function authenticate(
|
||||
prevState: string | undefined,
|
||||
formData: FormData,
|
||||
) {
|
||||
try {
|
||||
console.log(formData);
|
||||
} catch (error) {
|
||||
if (error) {
|
||||
return 'Something went wrong.';
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
export async function registration(
|
||||
prevState: string | undefined,
|
||||
formData: FormData,
|
||||
) {
|
||||
try {
|
||||
console.log(formData);
|
||||
} catch (error) {
|
||||
if (error) {
|
||||
return 'Something went wrong.';
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
+39
-2
@@ -1,4 +1,8 @@
|
||||
import { Metadata } from 'next';
|
||||
import styles from '@/app/styles/login.module.scss'
|
||||
import LogoIcon from '@/app/ui/logo-icon';
|
||||
import Link from 'next/link';
|
||||
import LoginForm from '@/app/ui/login-form';
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: 'Login',
|
||||
@@ -6,8 +10,41 @@ export const metadata: Metadata = {
|
||||
|
||||
export default function Home() {
|
||||
return (
|
||||
<div>
|
||||
plz login
|
||||
<div className={`${styles['login-container-wrapper']}`}>
|
||||
<div className={`${styles['login-container']}`}>
|
||||
<div className={`${styles['logo']}`}>
|
||||
<LogoIcon />
|
||||
<h1>NO COPY</h1>
|
||||
<p>Защита авторских прав</p>
|
||||
</div>
|
||||
<LoginForm />
|
||||
<div className="divider">
|
||||
<span>или войти через</span>
|
||||
</div>
|
||||
<div className={`${styles['register-link']}`}>
|
||||
<p>Нет аккаунта? <Link href="register">Зарегистрироваться</Link></p>
|
||||
</div>
|
||||
<div className={`${styles['features']}`}>
|
||||
<div className={`${styles['feature']}`}>
|
||||
<svg className={`${styles['feature-icon']}`} viewBox="0 0 24 24" fill="currentColor">
|
||||
<path d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"></path>
|
||||
</svg>
|
||||
Защита контента скрытыми водяными знаками
|
||||
</div>
|
||||
<div className={`${styles['feature']}`}>
|
||||
<svg className={`${styles['feature-icon']}`} viewBox="0 0 24 24" fill="currentColor">
|
||||
<path d="M13 10V3L4 14h7v7l9-11h-7z"></path>
|
||||
</svg>
|
||||
Мониторинг нарушений в реальном времени
|
||||
</div>
|
||||
<div className={`${styles['feature']}`}>
|
||||
<svg className={`${styles['feature-icon']}`} viewBox="0 0 24 24" fill="currentColor">
|
||||
<path d="M12 1L3 5v6c0 5.55 3.84 9.74 9 11 5.16-1.26 9-5.45 9-11V5l-9-4z"></path>
|
||||
</svg>
|
||||
Надежное хранение и безопасность данных
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
import LogoIcon from '@/app/ui/logo-icon';
|
||||
import styles from '@/app/styles/login.module.scss'
|
||||
import Link from 'next/link';
|
||||
import RegisterForm from '@/app/ui/register-form';
|
||||
|
||||
export default function Home() {
|
||||
return (
|
||||
<div className={`${styles['login-container-wrapper']}`}>
|
||||
<div className={`${styles['login-container']}`}>
|
||||
<div className={`${styles['logo']}`}>
|
||||
<LogoIcon />
|
||||
<h1>NO COPY</h1>
|
||||
<p>Создать аккаунт</p>
|
||||
</div>
|
||||
<div className={`${styles['subscription-info']}`}>
|
||||
<h4>🎉 Бесплатный старт</h4>
|
||||
<p>При регистрации вы получаете подписку "ДЕМО" с возможностью маркировки до 3 файлов в месяц и 10 МБ хранилища.</p>
|
||||
</div>
|
||||
<RegisterForm />
|
||||
<div className="divider">
|
||||
<span>или зарегистрироваться через</span>
|
||||
</div>
|
||||
<div className={`${styles['register-link']}`}>
|
||||
<p>Уже есть аккаунт? <Link href="login">Войти</Link></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -25,3 +25,27 @@
|
||||
box-shadow: 0 8px 25px rgba(99, 102, 241, 0.3);
|
||||
}
|
||||
}
|
||||
|
||||
.divider {
|
||||
text-align: center;
|
||||
margin: 20px 0;
|
||||
position: relative;
|
||||
color: #9ca3af;
|
||||
font-size: 14px;
|
||||
|
||||
&::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 1px;
|
||||
background: #e5e7eb;
|
||||
}
|
||||
|
||||
span {
|
||||
background: white;
|
||||
padding: 0 15px;
|
||||
position: relative;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,175 @@
|
||||
.login-container-wrapper {
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.login-container {
|
||||
background: white;
|
||||
border-radius: 20px;
|
||||
padding: 40px;
|
||||
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.1);
|
||||
width: 100%;
|
||||
max-width: 500px;
|
||||
}
|
||||
|
||||
.logo {
|
||||
text-align: center;
|
||||
margin-bottom: 30px;
|
||||
|
||||
h1 {
|
||||
font-size: 28px;
|
||||
font-weight: 700;
|
||||
color: #1f2937;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
p {
|
||||
color: #6b7280;
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
|
||||
.form-group {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.form-row {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 15px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.form-label {
|
||||
display: block;
|
||||
margin-bottom: 8px;
|
||||
font-weight: 500;
|
||||
color: #374151;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.form-label.required::after {
|
||||
content: ' *';
|
||||
color: #dc2626;
|
||||
}
|
||||
|
||||
.form-input {
|
||||
width: 100%;
|
||||
padding: 12px 16px;
|
||||
border: 2px solid #e5e7eb;
|
||||
border-radius: 10px;
|
||||
font-size: 16px;
|
||||
transition: all 0.3s;
|
||||
background: #f9fafb;
|
||||
}
|
||||
|
||||
.form-options {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.form-checkbox {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
input {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
margin-right: 10px;
|
||||
accent-color: #6366f1;
|
||||
}
|
||||
|
||||
label {
|
||||
font-size: 14px;
|
||||
color: #6b7280;
|
||||
cursor: pointer;
|
||||
|
||||
a {
|
||||
color: #6366f1;
|
||||
text-decoration: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.forgot-password {
|
||||
font-size: 14px;
|
||||
color: #6366f1;
|
||||
text-decoration: none;
|
||||
font-weight: 500;
|
||||
transition: color 0.3s;
|
||||
}
|
||||
|
||||
.btn {
|
||||
width: 100%;
|
||||
padding: 14px;
|
||||
background: linear-gradient(135deg, #6366f1, #8b5cf6);
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 10px;
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.register-link {
|
||||
text-align: center;
|
||||
margin-top: 20px;
|
||||
|
||||
a {
|
||||
color: #6366f1;
|
||||
text-decoration: none;
|
||||
font-weight: 500;
|
||||
transition: color 0.3s;
|
||||
}
|
||||
}
|
||||
|
||||
.features {
|
||||
margin-top: 30px;
|
||||
padding-top: 20px;
|
||||
border-top: 1px solid #e5e7eb;
|
||||
}
|
||||
|
||||
.feature {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 10px;
|
||||
font-size: 13px;
|
||||
color: #6b7280;
|
||||
}
|
||||
|
||||
.feature-icon {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
margin-right: 8px;
|
||||
color: #10b981;
|
||||
}
|
||||
|
||||
.subscription-info {
|
||||
background: #f0f9ff;
|
||||
border: 1px solid #bae6fd;
|
||||
border-radius: 10px;
|
||||
padding: 15px;
|
||||
margin-bottom: 20px;
|
||||
|
||||
h4 {
|
||||
color: #0369a1;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
p {
|
||||
color: #0c4a6e;
|
||||
font-size: 13px;
|
||||
line-height: 1.4;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
'use client'
|
||||
|
||||
import styles from '@/app/styles/login.module.scss'
|
||||
import { useActionState } from 'react';
|
||||
import { authenticate } from '@/app/api/action';
|
||||
|
||||
export default function LoginForm() {
|
||||
const [errorMessage, formAction, isPending] = useActionState(
|
||||
authenticate,
|
||||
undefined,
|
||||
);
|
||||
|
||||
return (
|
||||
<form action={formAction}>
|
||||
<div className={`${styles['form-group']}`}>
|
||||
<label className={`${styles['form-label']}`}>Email адрес</label>
|
||||
<input type="readOnly" id="email" name="email" className={`${styles['form-input']}`} placeholder="Введите ваш email" />
|
||||
</div>
|
||||
<div className={`${styles['form-group']}`}>
|
||||
<label className={`${styles['form-label']}`}>Пароль</label>
|
||||
<input type="password" id="password" name="password" className={`${styles['form-input']}`} placeholder="Введите пароль" />
|
||||
</div>
|
||||
{errorMessage && (
|
||||
<p className="text-sm text-red-500">{errorMessage}</p>
|
||||
)}
|
||||
<div className={`${styles['form-options']}`}>
|
||||
<div className={`${styles['form-checkbox']}`}>
|
||||
<input type="checkbox" id="remember" name="remember" />
|
||||
<label>Запомнить меня</label>
|
||||
</div>
|
||||
<a href="forgot-password" className={`${styles['forgot-password']}`} >Забыли пароль?</a>
|
||||
</div>
|
||||
<button type="submit" className={`${styles['btn']}`}>Войти в систему</button>
|
||||
</form>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
import style from "./ui.module.scss"
|
||||
|
||||
export default function LogoIcon() {
|
||||
return (
|
||||
<div className={`${style['logo-icon']}`}>
|
||||
<svg viewBox="0 0 24 24">
|
||||
<path d="M12 2L2 7v10c0 5.55 3.84 9.74 9 11 5.16-1.26 9-5.45 9-11V7l-10-5z"></path>
|
||||
</svg>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
'use client'
|
||||
|
||||
import styles from '@/app/styles/login.module.scss';
|
||||
import { useActionState } from 'react';
|
||||
import { registration } from '@/app/api/action';
|
||||
|
||||
export default function RegisterForm() {
|
||||
const [errorMessage, formAction, isPending] = useActionState(
|
||||
registration,
|
||||
undefined,
|
||||
);
|
||||
|
||||
return (
|
||||
<form action={formAction}>
|
||||
<div className={`${styles['form-group']}`}>
|
||||
<label
|
||||
className={`${styles['form-label']} ${styles['required']}`}
|
||||
>
|
||||
Полное имя
|
||||
</label>
|
||||
<input type="readOnly" id="full_name" name="full_name" className={`${styles['form-input']}`} placeholder="Иванов Иван Иванович" />
|
||||
</div>
|
||||
<div className={`${styles['form-row']}`}>
|
||||
<div className={`${styles['form-group']}`}>
|
||||
<label className={`${styles['form-label']} ${styles['required']}`}>Email адрес</label>
|
||||
<input type="password" id="email" name="email" className={`${styles['form-input']}`} placeholder="ivan@example.com" />
|
||||
</div>
|
||||
<div className={`${styles['form-group']}`}>
|
||||
<label className={`${styles['form-label']}`}>Телефон</label>
|
||||
<input type="phone" id="phone" name="phone" className={`${styles['form-input']}`} placeholder="+7 (999) 123-45-67" />
|
||||
</div>
|
||||
</div>
|
||||
<div className={`${styles['form-group']}`}>
|
||||
<label
|
||||
className={`${styles['form-label']}`}
|
||||
>
|
||||
Компания
|
||||
</label>
|
||||
<input type="readOnly" id="company" name="company" className={`${styles['form-input']}`} placeholder="ООО «Ваша компания»" />
|
||||
</div>
|
||||
<div className={`${styles['form-row']}`}>
|
||||
<div className={`${styles['form-group']}`}>
|
||||
<label className={`${styles['form-label']} ${styles['required']}`}>Пароль</label>
|
||||
<input type="password" id="password" name="password" className={`${styles['form-input']}`} placeholder="Минимум 6 символов" />
|
||||
</div>
|
||||
<div className={`${styles['form-group']}`}>
|
||||
<label className={`${styles['form-label']} ${styles['required']}`}>Подтвердите пароль</label>
|
||||
<input type="password" id="confirm_password" name="confirm_password" className={`${styles['form-input']}`} placeholder="Повторите пароль" />
|
||||
</div>
|
||||
</div>
|
||||
{errorMessage && (
|
||||
<p className="text-sm text-red-500">{errorMessage}</p>
|
||||
)}
|
||||
<div className={`${styles['form-checkbox']}`} style={{ marginBottom: "20px" }}>
|
||||
<input type="checkbox" id="remember" name="remember" />
|
||||
<label>Я соглашаюсь с <a href="forgot-password" >условиями использования и политикой конфиденциальности</a></label>
|
||||
</div>
|
||||
<button type="submit" className={`${styles['btn']}`}>Создать аккаунт</button>
|
||||
</form>
|
||||
)
|
||||
}
|
||||
@@ -84,3 +84,20 @@
|
||||
margin-right: 15px;
|
||||
}
|
||||
}
|
||||
|
||||
.logo-icon {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
background: linear-gradient(135deg, #6366f1, #8b5cf6);
|
||||
border-radius: 15px;
|
||||
margin-bottom: 15px;
|
||||
|
||||
svg {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
fill: white;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user