Authorization and registration coding

Coding of registration and authorization is finished. Also other fixes
This commit is contained in:
RailTH
2024-05-16 00:11:43 +11:00
parent 5e521ab5db
commit 239e6c0420
19 changed files with 104 additions and 44 deletions

View File

@@ -1,4 +1,4 @@
# Generated by Django 4.1 on 2024-05-04 09:04
# Generated by Django 4.1 on 2024-05-14 07:21
import django.core.validators
from django.db import migrations, models
@@ -61,7 +61,7 @@ class Migration(migrations.Migration):
('id', models.AutoField(db_index=True, primary_key=True, serialize=False, unique=True, verbose_name='ID Отзыва')),
('commentary', models.TextField(max_length=300, verbose_name='Комментарий отзыва')),
('rate', models.PositiveIntegerField(validators=[django.core.validators.MinValueValidator(1), django.core.validators.MaxValueValidator(5)], verbose_name='Оценка')),
('icons', models.TextField(verbose_name='Изображение отзыва в BASE64')),
('icons', models.TextField(null=True, verbose_name='Изображение отзыва в BASE64')),
('date', models.DateTimeField(auto_now=True, verbose_name='Дата создания отзыва')),
('product', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='SusMarketBackend.product')),
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='SusMarketBackend.user')),

View File

@@ -1,7 +1,7 @@
{
"files": {
"main.css": "/static/css/main.b9cb408a.css",
"main.js": "/static/js/main.d5c997c3.js",
"main.css": "/static/css/main.f8545ce2.css",
"main.js": "/static/js/main.142d0adb.js",
"static/media/scam-image.png": "/static/media/scam-image.c6c14289dc251ba2d2b1.png",
"static/media/info-page__railth-avatar.png": "/static/media/info-page__railth-avatar.cbf11c43b5ef243b38c0.png",
"static/media/add.webp": "/static/media/add.cd69f1e2a8c91109db0f.webp",
@@ -13,11 +13,11 @@
"static/media/rating__star-icon.svg": "/static/media/rating__star-icon.73718a24d04eb67f5873.svg",
"static/media/rating__filled-star-icon.svg": "/static/media/rating__filled-star-icon.dc7d908d4d943b7f3b56.svg",
"index.html": "/index.html",
"main.b9cb408a.css.map": "/static/css/main.b9cb408a.css.map",
"main.d5c997c3.js.map": "/static/js/main.d5c997c3.js.map"
"main.f8545ce2.css.map": "/static/css/main.f8545ce2.css.map",
"main.142d0adb.js.map": "/static/js/main.142d0adb.js.map"
},
"entrypoints": [
"static/css/main.b9cb408a.css",
"static/js/main.d5c997c3.js"
"static/css/main.f8545ce2.css",
"static/js/main.142d0adb.js"
]
}

View File

@@ -1 +1 @@
<!doctype html><html lang="en"><head><meta charset="utf-8"/><meta name="viewport" content="width=device-width,initial-scale=1"/><title>SusMarket</title><link rel="manifest" href="/manifest.json"/><script defer="defer" src="/static/js/main.d5c997c3.js"></script><link href="/static/css/main.b9cb408a.css" rel="stylesheet"></head><body><div id="root"></div></body></html>
<!doctype html><html lang="en"><head><meta charset="utf-8"/><meta name="viewport" content="width=device-width,initial-scale=1"/><title>SusMarket</title><link rel="manifest" href="/manifest.json"/><script defer="defer" src="/static/js/main.142d0adb.js"></script><link href="/static/css/main.f8545ce2.css" rel="stylesheet"></head><body><div id="root"></div></body></html>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1,3 +1,5 @@
/*! js-cookie v3.0.5 | MIT */
/**
* @license React
* react-dom.production.min.js

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -16,6 +16,7 @@
"@types/react": "^18.2.51",
"@types/react-dom": "^18.2.18",
"framer-motion": "^11.0.3",
"js-cookie": "^3.0.5",
"node-sass": "^9.0.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
@@ -26,7 +27,8 @@
"web-vitals": "^2.1.4"
},
"devDependencies": {
"@babel/plugin-proposal-private-property-in-object": "^7.21.11"
"@babel/plugin-proposal-private-property-in-object": "^7.21.11",
"@types/js-cookie": "^3.0.6"
}
},
"node_modules/@aashutoshrathi/word-wrap": {
@@ -4487,6 +4489,12 @@
"node": ">=8"
}
},
"node_modules/@types/js-cookie": {
"version": "3.0.6",
"resolved": "https://registry.npmjs.org/@types/js-cookie/-/js-cookie-3.0.6.tgz",
"integrity": "sha512-wkw9yd1kEXOPnvEeEV1Go1MmxtBJL0RR79aOTAApecWFVu7w0NNXNqhcWgvw2YgZDYadliXkl14pa3WXw5jlCQ==",
"dev": true
},
"node_modules/@types/json-schema": {
"version": "7.0.15",
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
@@ -12575,6 +12583,14 @@
"resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.6.4.tgz",
"integrity": "sha512-pZe//GGmwJndub7ZghVHz7vjb2LgC1m8B07Au3eYqeqv9emhESByMXxaEgkUkEqJe87oBbSniGYoQNIBklc7IQ=="
},
"node_modules/js-cookie": {
"version": "3.0.5",
"resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-3.0.5.tgz",
"integrity": "sha512-cEiJEAEoIbWfCZYKWhVwFuvPX1gETRYPw6LlaTKoxD3s2AkXzkCjnp6h0V77ozyqj0jakteJ4YqDJT830+lVGw==",
"engines": {
"node": ">=14"
}
},
"node_modules/js-tokens": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",

View File

@@ -11,6 +11,7 @@
"@types/react": "^18.2.51",
"@types/react-dom": "^18.2.18",
"framer-motion": "^11.0.3",
"js-cookie": "^3.0.5",
"node-sass": "^9.0.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
@@ -45,6 +46,7 @@
]
},
"devDependencies": {
"@babel/plugin-proposal-private-property-in-object": "^7.21.11"
"@babel/plugin-proposal-private-property-in-object": "^7.21.11",
"@types/js-cookie": "^3.0.6"
}
}

View File

@@ -5,6 +5,8 @@ import Logotype from "../assets/img/amongasik.png";
import CatalogMenu from "./CatalogMenu";
import LoginMenu from "./LoginMenu";
import { Category } from "../utils/types";
import Cookies from "js-cookie";
import { useNavigate } from "react-router-dom";
interface HeaderProps {
togglePopupMap: () => void;
@@ -22,26 +24,25 @@ interface HeaderLoginMenuState {
export default function Header({ togglePopupMap, onSelectCategory, onSearchChange }: HeaderProps): JSX.Element {
const [stateCatalog, setStateCatalog] = useState<HeaderCatalogMenuState>({
isCatalogMenuVisible: false,
});
const [stateLogin, setStateLogin] = useState<HeaderLoginMenuState>({
isLoginMenuVisible: false,
});
const [isCatalogMenuVisible, setIsCatalogMenuVisible] = useState(false);
const [isLoginMenuVisible, setIsLoginMenuVisible] = useState(false);
const navigate = useNavigate();
const toggleCatalogMenu = () => {
setStateCatalog((prevState) => ({
...prevState,
isCatalogMenuVisible: !prevState.isCatalogMenuVisible,
}));
setIsCatalogMenuVisible(!isCatalogMenuVisible);
};
const toggleLoginMenu = () => {
setStateLogin((prevState) => ({
...prevState,
isLoginMenuVisible: !prevState.isLoginMenuVisible,
}));
setIsLoginMenuVisible(!isLoginMenuVisible);
};
const handleProfileClick = () => {
const userCookie = Cookies.get('user');
if (userCookie) {
navigate('/profile');
} else {
toggleLoginMenu();
}
};
const resetCategoryFilter = () => {
@@ -102,7 +103,7 @@ export default function Header({ togglePopupMap, onSelectCategory, onSearchChang
className="header__profile-a"
whileTap={{scale: 0.9}}
transition={{duration: 0.2, type: "spring"}}
onClick={toggleLoginMenu}
onClick={handleProfileClick}
>
{/* Код для svg */}
<motion.svg width="48.000000" height="48.000000" viewBox="0 0 48 48" fill="none"
@@ -162,8 +163,8 @@ export default function Header({ togglePopupMap, onSelectCategory, onSearchChang
{/* Код для svg */}
</motion.a>
</nav>
{stateCatalog.isCatalogMenuVisible && <CatalogMenu toggleCatalogMenu={toggleCatalogMenu} onSelectCategory={onSelectCategory}/>}
{stateLogin.isLoginMenuVisible && <LoginMenu toggleLoginMenu={toggleLoginMenu}/>}
{isCatalogMenuVisible && <CatalogMenu toggleCatalogMenu={toggleCatalogMenu} onSelectCategory={onSelectCategory}/>}
{isLoginMenuVisible && <LoginMenu toggleLoginMenu={toggleLoginMenu}/>}
</header>
)
}

View File

@@ -1,5 +1,8 @@
import React, { useState } from "react";
import { motion } from "framer-motion";
import axios from "axios";
import { useNavigate } from "react-router-dom";
import Cookies from "js-cookie";
interface LoginMenuProps {
toggleLoginMenu: () => void;
@@ -7,15 +10,49 @@ interface LoginMenuProps {
export default function LoginMenu({ toggleLoginMenu }: LoginMenuProps): JSX.Element {
const [isLoginMode, setIsLoginMode] = useState(true);
const [login, setLogin] = useState('');
const [password, setPassword] = useState('');
const navigate = useNavigate();
const toggleMode = () => {
setIsLoginMode(!isLoginMode);
}
const handleAuth = async (isRegistering: boolean) => {
try {
let response;
if (isRegistering) {
// Регистрация пользователя
const params = new URLSearchParams({
login: login,
password: password
});
response = await axios.get(`http://127.0.0.1:8000/api/post/user?${params.toString()}`);
} else {
// Вход в систему
response = await axios.get(`http://127.0.0.1:8000/api/get/user?login=${encodeURIComponent(login)}&password=${encodeURIComponent(password)}`);
}
if (response.status === 200) {
// Создание cookie файла
Cookies.set('user', login, { expires: 1 }); // Cookie на 1 день
// Перенаправление на страницу профиля
navigate('/profile');
toggleLoginMenu(); // Закрытие меню входа
}
} catch (error) {
console.error('Ошибка при авторизации:', error);
}
}
const handleSubmit = async (event: React.FormEvent<HTMLFormElement>) => {
event.preventDefault();
await handleAuth(!isLoginMode);
}
return(
<>
<div className="background-blackout" onClick={toggleLoginMenu}></div>
<form className="popup-login">
<form className="popup-login" onSubmit={handleSubmit}>
<div className="popup-login__top-container">
<div className="top-container__headings-text">
<h5 className="popup-menu__heading">
@@ -27,8 +64,8 @@ export default function LoginMenu({ toggleLoginMenu }: LoginMenuProps): JSX.Elem
</div>
</div>
<div className="popup-login__inputs-container">
<input type="text" name="userName" id="userName" className="popup-login__name-input" placeholder="Логин"/>
<input type="password" name="userPassword" id="userPassword" className="popup-login__password-input" placeholder="Пароль"/>
<input type="text" name="userName" id="userName" className="popup-login__name-input" placeholder="Логин" value={login} onChange={(e) => setLogin(e.target.value)}/>
<input type="password" name="userPassword" id="userPassword" className="popup-login__password-input" placeholder="Пароль" value={password} onChange={(e) => setPassword(e.target.value)}/>
</div>
<div className="popup-login__bottom-container">
<p className="popup-login__prompt-url" onClick={toggleMode}>
@@ -36,6 +73,7 @@ export default function LoginMenu({ toggleLoginMenu }: LoginMenuProps): JSX.Elem
<u>{isLoginMode ? 'Зарегистрироваться' : 'Войти'}</u>
</p>
<motion.button
type="submit"
className="popup-login__login-button"
whileTap={{scale: 0.98}}
transition={{duration: 0.2, type: "spring"}}

View File

@@ -1,12 +1,15 @@
import React from "react";
import ProfileAvatar from '../assets/icons/profile-avatar.svg';
import '../ProfileStyle.scss';
import Cookies from "js-cookie";
export default function ProfileInfo() {
const userLogin = Cookies.get('user');
return(
<div className="profile-page__info-div">
<img src={ProfileAvatar} alt="" className="info-div__img"/>
<span>Роман Константинов</span>
<span>{userLogin || 'Гость'}</span>
</div>
)
}

View File

@@ -2,7 +2,7 @@ import React from "react";
import { Link } from "react-router-dom";
import '../ProfileStyle.scss';
import ProfileInfo from "./ProfileInfo";
import ProductCard from "./ProductCard";
// import ProductCard from "./ProductCard";
export default function ProfilePurchases() {
return(

View File

@@ -157,13 +157,11 @@ body {
position: fixed;
z-index: 999;
width: 340px;
height: 495px;
left: 218px;
top: 108px;
display: flex;
gap: 30px;
flex-direction: column;
justify-content: space-between;
align-items: flex-start;
box-sizing: border-box;
border-radius: 20px;
background-color: $background-color;