4 + промежуточная 5
This commit is contained in:
parent
056bab6b14
commit
a8937930eb
@ -30,7 +30,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="navbar-collapse collapse justify-content-end" id="navbarNav">
|
<div class="navbar-collapse collapse justify-content-end" id="navbarNav">
|
||||||
<div class="navbar-nav">
|
<div class="navbar-nav">
|
||||||
<a class="btn custom-btn" href="personalAccountLogin.html">Войти</a>
|
<a class="btn custom-btn" href="personalAccountLogin.html">Администратор</a>
|
||||||
<a class="btn btn-warning" href="basket.html">Корзина</a>
|
<a class="btn btn-warning" href="basket.html">Корзина</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -39,8 +39,10 @@
|
|||||||
</header>
|
</header>
|
||||||
<main class="container-fluid p-2">
|
<main class="container-fluid p-2">
|
||||||
<h1 class="text-warning text-center font-weight-bold">Панель администратора</h1>
|
<h1 class="text-warning text-center font-weight-bold">Панель администратора</h1>
|
||||||
<div class="btn-group" role="group">
|
<div class="text-center">
|
||||||
<a class="btn btn-warning" href="/page-edit.html">Добавить товар</a>
|
<div class="btn-group" role="group">
|
||||||
|
<a class="btn btn-warning" href="/page-edit.html">Добавить товар</a>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<h2 class="text-warning text-center font-weight-bold" style="padding-top: 10px;">Таблица данных</h2>
|
<h2 class="text-warning text-center font-weight-bold" style="padding-top: 10px;">Таблица данных</h2>
|
||||||
|
File diff suppressed because one or more lines are too long
@ -74,6 +74,7 @@
|
|||||||
class="fw-bold text-body"><u>Регистрация</u></a></p>
|
class="fw-bold text-body"><u>Регистрация</u></a></p>
|
||||||
|
|
||||||
<p class="text-center"><a class="fw-bold text-body" href="Administrator.html">Администратор</a></p>
|
<p class="text-center"><a class="fw-bold text-body" href="Administrator.html">Администратор</a></p>
|
||||||
|
<p class="text-center"><a class="fw-bold text-body" href="AdminDop.html">Администратор2</a></p>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
19
lab4/data.json
Normal file
19
lab4/data.json
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
{
|
||||||
|
"posts": [
|
||||||
|
{
|
||||||
|
"id": 1,
|
||||||
|
"title": "json-server",
|
||||||
|
"author": "typicode"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"comments": [
|
||||||
|
{
|
||||||
|
"id": 1,
|
||||||
|
"body": "some comment",
|
||||||
|
"postId": 1
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"profile": {
|
||||||
|
"name": "typicode"
|
||||||
|
}
|
||||||
|
}
|
1716
lab4/package-lock.json
generated
1716
lab4/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -1,33 +1,38 @@
|
|||||||
{
|
{
|
||||||
"name": "lab4",
|
"name": "lec4",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "0.0.0",
|
"version": "0.0.0",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
|
||||||
"build": "vite build",
|
|
||||||
"lint": "eslint . --ext js,jsx --report-unused-disable-directives --max-warnings 0",
|
"lint": "eslint . --ext js,jsx --report-unused-disable-directives --max-warnings 0",
|
||||||
"preview": "vite preview"
|
"rest": "json-server data.json",
|
||||||
|
"vite": "vite",
|
||||||
|
"dev": "npm-run-all --parallel rest vite",
|
||||||
|
"prod": "npm-run-all lint 'vite build' --parallel rest 'vite preview'"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"bootstrap": "^5.3.2",
|
|
||||||
"mdb-react-ui-kit": "^7.0.0",
|
|
||||||
"prop-types": "^15.8.1",
|
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
|
"react-dom": "^18.2.0",
|
||||||
|
"react-router-dom": "^6.18.0",
|
||||||
|
"react-hot-toast": "^2.4.1",
|
||||||
|
"axios": "^1.6.1",
|
||||||
|
"bootstrap": "^5.3.2",
|
||||||
"react-bootstrap": "^2.9.1",
|
"react-bootstrap": "^2.9.1",
|
||||||
"react-bootstrap-icons": "^1.10.3",
|
"react-bootstrap-icons": "^1.10.3",
|
||||||
"react-dom": "^18.2.0",
|
"prop-types": "^15.8.1"
|
||||||
"react-router-dom": "^6.18.0"
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/react": "^18.2.15",
|
"@types/react": "^18.2.15",
|
||||||
"@types/react-dom": "^18.2.7",
|
"@types/react-dom": "^18.2.15",
|
||||||
"@vitejs/plugin-react": "^4.0.3",
|
"@vitejs/plugin-react": "^4.0.3",
|
||||||
"eslint": "^8.45.0",
|
"eslint": "^8.45.0",
|
||||||
"eslint-config-airbnb-base": "^15.0.0",
|
"eslint-config-airbnb-base": "^15.0.0",
|
||||||
|
"eslint-plugin-import": "^2.29.0",
|
||||||
"eslint-plugin-react": "^7.32.2",
|
"eslint-plugin-react": "^7.32.2",
|
||||||
"eslint-plugin-react-hooks": "^4.6.0",
|
"eslint-plugin-react-hooks": "^4.6.0",
|
||||||
"eslint-plugin-react-refresh": "^0.4.3",
|
"eslint-plugin-react-refresh": "^0.4.3",
|
||||||
|
"json-server": "^0.17.4",
|
||||||
|
"npm-run-all": "^4.1.5",
|
||||||
"vite": "^4.4.5"
|
"vite": "^4.4.5"
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,5 +1,6 @@
|
|||||||
import { Container, Row, Col } from 'react-bootstrap';
|
import { Container, Row, Col } from 'react-bootstrap';
|
||||||
import BasketCard from '../components/card/BasketCard';
|
import BasketCard from '../components/card/BasketCard';
|
||||||
|
import { Link } from 'react-router-dom';
|
||||||
|
|
||||||
const Basket = () => {
|
const Basket = () => {
|
||||||
return (
|
return (
|
||||||
@ -24,7 +25,9 @@ const Basket = () => {
|
|||||||
Сумма ₽
|
Сумма ₽
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<a className="btn btn-warning" style={{ marginLeft: '25px', marginBottom: '10px' }} href="makingAnOrder">К оплате</a>
|
<Link to='/MakingAnOrder' className="btn btn-warning" style={{ marginLeft: '25px', marginBottom: '10px' }}>
|
||||||
|
К оплате
|
||||||
|
</Link>
|
||||||
</Container>
|
</Container>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -13,7 +13,7 @@ const Contacts = () => {
|
|||||||
<iframe
|
<iframe
|
||||||
src="https://yandex.ru/map-widget/v1/?um=constructor%3A0643c92cbdf3809080e5dfb2804b473ea00af31cfabe6fee08676c59d8675f01&source=constructor"
|
src="https://yandex.ru/map-widget/v1/?um=constructor%3A0643c92cbdf3809080e5dfb2804b473ea00af31cfabe6fee08676c59d8675f01&source=constructor"
|
||||||
className="img-fluid"
|
className="img-fluid"
|
||||||
style={{ width: '100%', height: '720px' }}
|
style={{ width: '100%', height: '500px' }}
|
||||||
title="Yandex Map"
|
title="Yandex Map"
|
||||||
></iframe>
|
></iframe>
|
||||||
</Col>
|
</Col>
|
||||||
|
@ -2,7 +2,7 @@ import { useState } from 'react';
|
|||||||
import { Container, Row, Col, Card, Form, Button } from 'react-bootstrap';
|
import { Container, Row, Col, Card, Form, Button } from 'react-bootstrap';
|
||||||
|
|
||||||
const MakingAnOrder = () => {
|
const MakingAnOrder = () => {
|
||||||
const [deliveryMethod, setDeliveryMethod] = useState('selfPickup');
|
const [deliveryMethod, setDeliveryMethod] = useState('selfPickup');
|
||||||
const [paymentMethod, setPaymentMethod] = useState('cash');
|
const [paymentMethod, setPaymentMethod] = useState('cash');
|
||||||
|
|
||||||
const handleDeliveryMethodChange = (e) => {
|
const handleDeliveryMethodChange = (e) => {
|
||||||
@ -35,7 +35,7 @@ const MakingAnOrder = () => {
|
|||||||
|
|
||||||
<Form noValidate validated={validated} onSubmit={handleSubmit}>
|
<Form noValidate validated={validated} onSubmit={handleSubmit}>
|
||||||
<Form.Group className="mb-4" controlId="name">
|
<Form.Group className="mb-4" controlId="name">
|
||||||
<Form.Label htmlFor="name">Ваше имя</Form.Label>
|
<Form.Label>Ваше имя</Form.Label>
|
||||||
<Form.Control type="text" required />
|
<Form.Control type="text" required />
|
||||||
<Form.Control.Feedback>Имя заполнено</Form.Control.Feedback>
|
<Form.Control.Feedback>Имя заполнено</Form.Control.Feedback>
|
||||||
<Form.Control.Feedback type="invalid">Имя не заполнено</Form.Control.Feedback>
|
<Form.Control.Feedback type="invalid">Имя не заполнено</Form.Control.Feedback>
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import { Container, Row, Col, Card, Form, Button } from 'react-bootstrap';
|
import { Container, Row, Col, Card, Form, Button } from 'react-bootstrap';
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
|
import { Link } from 'react-router-dom';
|
||||||
|
|
||||||
const PasswordRecovery = () => {
|
const PasswordRecovery = () => {
|
||||||
const [validated, setValidated] = useState(false);
|
const [validated, setValidated] = useState(false);
|
||||||
@ -39,15 +40,11 @@ const PasswordRecovery = () => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<p className="text-center text-muted mb-0">
|
<p className="text-center text-muted mb-0">
|
||||||
<a href="personalAccountLogin" className="fw-bold text-body">
|
<Link className="fw-bold text-body" to='/PersonalAccountLogin' style={{ color: 'black', textDecoration: 'none' }}><u>Войти</u></Link>
|
||||||
<u>Войти</u>
|
|
||||||
</a>
|
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p className="text-center text-muted mb-0">
|
<p className="text-center text-muted mb-0">
|
||||||
<a href="personalAccountRegister" className="fw-bold text-body">
|
<Link className="fw-bold text-body" to='/PersonalAccountRegister' style={{ color: 'black', textDecoration: 'none' }}><u>Регистрация</u></Link>
|
||||||
<u>Регистрация</u>
|
|
||||||
</a>
|
|
||||||
</p>
|
</p>
|
||||||
</Form>
|
</Form>
|
||||||
</Card.Body>
|
</Card.Body>
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import { Container, Row, Col, Card, Form, Button } from 'react-bootstrap';
|
import { Container, Row, Col, Card, Form, Button } from 'react-bootstrap';
|
||||||
|
import { Link } from 'react-router-dom';
|
||||||
|
|
||||||
const PersonalAccount = () => {
|
const PersonalAccount = () => {
|
||||||
const [validated, setValidated] = useState(false);
|
const [validated, setValidated] = useState(false);
|
||||||
@ -24,14 +25,14 @@ const PersonalAccount = () => {
|
|||||||
|
|
||||||
<Form noValidate validated={validated} onSubmit={handleSubmit}>
|
<Form noValidate validated={validated} onSubmit={handleSubmit}>
|
||||||
<Form.Group className="mb-4" controlId="name">
|
<Form.Group className="mb-4" controlId="name">
|
||||||
<Form.Label htmlFor="name">Ваше имя</Form.Label>
|
<Form.Label>Ваше имя</Form.Label>
|
||||||
<Form.Control type="text" required />
|
<Form.Control type="text" required />
|
||||||
<Form.Control.Feedback>Имя заполнено</Form.Control.Feedback>
|
<Form.Control.Feedback>Имя заполнено</Form.Control.Feedback>
|
||||||
<Form.Control.Feedback type="invalid">Имя не заполнено</Form.Control.Feedback>
|
<Form.Control.Feedback type="invalid">Имя не заполнено</Form.Control.Feedback>
|
||||||
</Form.Group>
|
</Form.Group>
|
||||||
|
|
||||||
<Form.Group className="mb-4" controlId="surname">
|
<Form.Group className="mb-4" controlId="surname">
|
||||||
<Form.Label htmlFor="surname">Ваша фамилия</Form.Label>
|
<Form.Label>Ваша фамилия</Form.Label>
|
||||||
<Form.Control type="text" required/>
|
<Form.Control type="text" required/>
|
||||||
<Form.Control.Feedback>Фамилия заполнена</Form.Control.Feedback>
|
<Form.Control.Feedback>Фамилия заполнена</Form.Control.Feedback>
|
||||||
<Form.Control.Feedback type="invalid">Фамилия не заполнена</Form.Control.Feedback>
|
<Form.Control.Feedback type="invalid">Фамилия не заполнена</Form.Control.Feedback>
|
||||||
@ -65,9 +66,9 @@ const PersonalAccount = () => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="d-flex justify-content-center mt-2">
|
<div className="d-flex justify-content-center mt-2">
|
||||||
<a className="btn btn-outline-danger" type="button" href="/">
|
<Link to='/' className="btn btn-outline-danger" type="button">
|
||||||
Выйти
|
Выйти
|
||||||
</a>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
</Form>
|
</Form>
|
||||||
</Card.Body>
|
</Card.Body>
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import { Container, Row, Col, Card, Form, Button } from 'react-bootstrap';
|
import { Container, Row, Col, Card, Form, Button } from 'react-bootstrap';
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
|
import { Link } from 'react-router-dom';
|
||||||
|
|
||||||
const PersonalAccountLogin = () => {
|
const PersonalAccountLogin = () => {
|
||||||
const [validated, setValidated] = useState(false);
|
const [validated, setValidated] = useState(false);
|
||||||
@ -43,28 +44,28 @@ const PersonalAccountLogin = () => {
|
|||||||
|
|
||||||
<p className="text-center text-muted mb-0">
|
<p className="text-center text-muted mb-0">
|
||||||
Забыли пароль?{' '}
|
Забыли пароль?{' '}
|
||||||
<a href="PasswordRecovery" className="fw-bold text-body">
|
<Link to='/PasswordRecovery' className="fw-bold text-body" style={{ color: 'black', textDecoration: 'none' }}>
|
||||||
<u>Восстановление пароля</u>
|
<u>Восстановление пароля</u>
|
||||||
</a>
|
</Link>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<div className="d-flex justify-content-center">
|
<div className="d-flex justify-content-center">
|
||||||
<Button variant="submit" className="btn-block btn-warning text-body mb-0" href="PersonalAccount">
|
<Button as={Link} to='/PersonalAccount' variant="submit" className="btn-block btn-warning text-body mb-0">
|
||||||
Вход
|
Вход
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<p className="text-center text-muted mb-0">
|
<p className="text-center text-muted mb-0">
|
||||||
У вас нет аккаунта?{' '}
|
У вас нет аккаунта?{' '}
|
||||||
<a href="personalAccountRegister" className="fw-bold text-body">
|
<Link to='/personalAccountRegister' className="fw-bold text-body" style={{ color: 'black', textDecoration: 'none' }}>
|
||||||
<u>Регистрация</u>
|
<u>Регистрация</u>
|
||||||
</a>
|
</Link>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p className="text-center">
|
<p className="text-center">
|
||||||
<a className="fw-bold text-body" href="Administrator">
|
<Link to='/Administrator' className="fw-bold text-body" style={{ color: 'black'}}>
|
||||||
Администратор
|
Администратор
|
||||||
</a>
|
</Link>
|
||||||
</p>
|
</p>
|
||||||
</Form>
|
</Form>
|
||||||
</Card.Body>
|
</Card.Body>
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import { Container, Row, Col, Card, Form, Button } from 'react-bootstrap';
|
import { Container, Row, Col, Card, Form, Button } from 'react-bootstrap';
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
|
import { Link } from 'react-router-dom';
|
||||||
|
|
||||||
const PersonalAccountRegister = () => {
|
const PersonalAccountRegister = () => {
|
||||||
const [validated, setValidated] = useState(false);
|
const [validated, setValidated] = useState(false);
|
||||||
@ -27,7 +28,7 @@ const PersonalAccountRegister = () => {
|
|||||||
<Form.Control type="text" required />
|
<Form.Control type="text" required />
|
||||||
<Form.Control.Feedback>Имя заполнено</Form.Control.Feedback>
|
<Form.Control.Feedback>Имя заполнено</Form.Control.Feedback>
|
||||||
<Form.Control.Feedback type="invalid">Имя не заполнено</Form.Control.Feedback>
|
<Form.Control.Feedback type="invalid">Имя не заполнено</Form.Control.Feedback>
|
||||||
<Form.Label htmlFor="name">Ваше имя</Form.Label>
|
<Form.Label>Ваше имя</Form.Label>
|
||||||
</Form.Group>
|
</Form.Group>
|
||||||
|
|
||||||
<Form.Group className="mb-4">
|
<Form.Group className="mb-4">
|
||||||
@ -63,16 +64,18 @@ const PersonalAccountRegister = () => {
|
|||||||
</Form.Group>
|
</Form.Group>
|
||||||
|
|
||||||
<div className="d-flex justify-content-center">
|
<div className="d-flex justify-content-center">
|
||||||
<Button variant="success" type="button" className="btn-block btn-warning text-body mb-0" href="PersonalAccount">
|
<Link to='/PersonalAccount' style={{color: 'black', textDecoration: 'none'}}>
|
||||||
Регистрация
|
<Button variant="success" type="button" className="btn-block btn-warning text-body mb-0">
|
||||||
</Button>
|
Регистрация
|
||||||
|
</Button>
|
||||||
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<p className="text-center text-muted mb-0">
|
<p className="text-center text-muted mb-0">
|
||||||
У вас уже есть учетная запись?{' '}
|
У вас уже есть учетная запись?{' '}
|
||||||
<a href="personalAccountLogin" className="fw-bold text-body">
|
<Link to='/PersonalAccountLogin' className="fw-bold text-body" style={{ color: 'black', textDecoration: 'none' }}>
|
||||||
<u>Войдите здесь</u>
|
<u>Войдите здесь</u>
|
||||||
</a>
|
</Link>
|
||||||
</p>
|
</p>
|
||||||
</Form>
|
</Form>
|
||||||
</Card.Body>
|
</Card.Body>
|
||||||
|
581
lab5/data.json
581
lab5/data.json
File diff suppressed because one or more lines are too long
26
lab5/package-lock.json
generated
26
lab5/package-lock.json
generated
@ -16,7 +16,7 @@
|
|||||||
"react-bootstrap-icons": "^1.10.3",
|
"react-bootstrap-icons": "^1.10.3",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
"react-hot-toast": "^2.4.1",
|
"react-hot-toast": "^2.4.1",
|
||||||
"react-router-dom": "^6.18.0"
|
"react-router-dom": "^6.20.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/react": "^18.2.15",
|
"@types/react": "^18.2.15",
|
||||||
@ -956,9 +956,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@remix-run/router": {
|
"node_modules/@remix-run/router": {
|
||||||
"version": "1.11.0",
|
"version": "1.13.0",
|
||||||
"resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.11.0.tgz",
|
"resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.13.0.tgz",
|
||||||
"integrity": "sha512-BHdhcWgeiudl91HvVa2wxqZjSHbheSgIiDvxrF1VjFzBzpTtuDPkOdOi3Iqvc08kXtFkLjhbS+ML9aM8mJS+wQ==",
|
"integrity": "sha512-5dMOnVnefRsl4uRnAdoWjtVTdh8e6aZqgM4puy9nmEADH72ck+uXwzpJLEKE9Q6F8ZljNewLgmTfkxUrBdv4WA==",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=14.0.0"
|
"node": ">=14.0.0"
|
||||||
}
|
}
|
||||||
@ -4802,11 +4802,11 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/react-router": {
|
"node_modules/react-router": {
|
||||||
"version": "6.18.0",
|
"version": "6.20.0",
|
||||||
"resolved": "https://registry.npmjs.org/react-router/-/react-router-6.18.0.tgz",
|
"resolved": "https://registry.npmjs.org/react-router/-/react-router-6.20.0.tgz",
|
||||||
"integrity": "sha512-vk2y7Dsy8wI02eRRaRmOs9g2o+aE72YCx5q9VasT1N9v+lrdB79tIqrjMfByHiY5+6aYkH2rUa5X839nwWGPDg==",
|
"integrity": "sha512-pVvzsSsgUxxtuNfTHC4IxjATs10UaAtvLGVSA1tbUE4GDaOSU1Esu2xF5nWLz7KPiMuW8BJWuPFdlGYJ7/rW0w==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@remix-run/router": "1.11.0"
|
"@remix-run/router": "1.13.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=14.0.0"
|
"node": ">=14.0.0"
|
||||||
@ -4816,12 +4816,12 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/react-router-dom": {
|
"node_modules/react-router-dom": {
|
||||||
"version": "6.18.0",
|
"version": "6.20.0",
|
||||||
"resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.18.0.tgz",
|
"resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.20.0.tgz",
|
||||||
"integrity": "sha512-Ubrue4+Ercc/BoDkFQfc6og5zRQ4A8YxSO3Knsne+eRbZ+IepAsK249XBH/XaFuOYOYr3L3r13CXTLvYt5JDjw==",
|
"integrity": "sha512-CbcKjEyiSVpA6UtCHOIYLUYn/UJfwzp55va4yEfpk7JBN3GPqWfHrdLkAvNCcpXr8QoihcDMuk0dzWZxtlB/mQ==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@remix-run/router": "1.11.0",
|
"@remix-run/router": "1.13.0",
|
||||||
"react-router": "6.18.0"
|
"react-router": "6.20.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=14.0.0"
|
"node": ">=14.0.0"
|
||||||
|
@ -12,6 +12,7 @@ const LinesForm = ({ id }) => {
|
|||||||
validated,
|
validated,
|
||||||
handleSubmit,
|
handleSubmit,
|
||||||
handleChange,
|
handleChange,
|
||||||
|
handleStockChange,
|
||||||
} = useLinesItemForm(id);
|
} = useLinesItemForm(id);
|
||||||
|
|
||||||
const onBack = () => {
|
const onBack = () => {
|
||||||
@ -27,7 +28,7 @@ const LinesForm = ({ id }) => {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Form className='m-0 p-2' noValidate validated={validated} onSubmit={onSubmit}>
|
<Form className='m-0 p-2' noValidate validated={validated} onSubmit={onSubmit}>
|
||||||
<LinesItemForm item={item} handleChange={handleChange} />
|
<LinesItemForm item={item} handleChange={handleChange} handleStockChange={handleStockChange} />
|
||||||
<Form.Group className='row justify-content-center m-0 mt-3'>
|
<Form.Group className='row justify-content-center m-0 mt-3'>
|
||||||
<Button className='col-5 col-lg-2 m-0 me-2' variant='secondary' onClick={() => onBack()}>
|
<Button className='col-5 col-lg-2 m-0 me-2' variant='secondary' onClick={() => onBack()}>
|
||||||
Назад
|
Назад
|
||||||
|
@ -3,23 +3,23 @@ import imgPlaceholder from '../../../Images/200.png';
|
|||||||
import Input from '../../input/Input.jsx';
|
import Input from '../../input/Input.jsx';
|
||||||
import Select from '../../input/Select.jsx';
|
import Select from '../../input/Select.jsx';
|
||||||
import useTypes from '../../types/hooks/TypesHook';
|
import useTypes from '../../types/hooks/TypesHook';
|
||||||
|
import useStocks from '../../types/hooks/StockHook';
|
||||||
import './LinesItemForm.css';
|
import './LinesItemForm.css';
|
||||||
|
|
||||||
const LinesItemForm = ({ item, handleChange }) => {
|
const LinesItemForm = ({ item, handleChange, handleStockChange }) => {
|
||||||
const { types } = useTypes();
|
const { types } = useTypes();
|
||||||
|
const { stocks } = useStocks();
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className='text-center'>
|
<div className='text-center'>
|
||||||
<img id='image-preview' className='rounded' alt='placeholder'
|
<img id='image-preview' className='rounded' alt='placeholder'
|
||||||
src={item.image || imgPlaceholder} />
|
src={item.image || imgPlaceholder} />
|
||||||
</div>
|
</div>
|
||||||
<Select values={types} name='typeId' label='Товары' value={item.typeId} onChange={handleChange}
|
<Select values={types} name='typeId' label='Товары' value={item.typeId.toString()} onChange={handleChange}
|
||||||
required />
|
required />
|
||||||
<Input name='price' label='Цена' value={item.price} onChange={handleChange}
|
<Input name='price' label='Цена' value={item.price} onChange={handleChange}
|
||||||
type='number' min='1000.0' step='0.50' required />
|
type='number' min='1' step='1' required />
|
||||||
<Input name='stock' label='Акция' value={item.stock} onChange={handleChange}
|
<Select values={stocks} name='stock' label='Акция' value={item.stock} onChange={handleStockChange} />
|
||||||
type='number' min='0' step='1' />
|
|
||||||
<Input name='count' label='Количество' value={item.count} onChange={handleChange}
|
<Input name='count' label='Количество' value={item.count} onChange={handleChange}
|
||||||
type='number' min='1' step='1' required />
|
type='number' min='1' step='1' required />
|
||||||
<Input name='image' label='Изображение' onChange={handleChange}
|
<Input name='image' label='Изображение' onChange={handleChange}
|
||||||
@ -30,7 +30,9 @@ const LinesItemForm = ({ item, handleChange }) => {
|
|||||||
|
|
||||||
LinesItemForm.propTypes = {
|
LinesItemForm.propTypes = {
|
||||||
item: PropTypes.object,
|
item: PropTypes.object,
|
||||||
|
|
||||||
handleChange: PropTypes.func,
|
handleChange: PropTypes.func,
|
||||||
|
handleStockChange: PropTypes.func,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default LinesItemForm;
|
export default LinesItemForm;
|
||||||
|
48
lab5/src/components/lines/form/StocksForm.jsx
Normal file
48
lab5/src/components/lines/form/StocksForm.jsx
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import { Button, Form } from 'react-bootstrap';
|
||||||
|
import { useNavigate } from 'react-router-dom';
|
||||||
|
import useStocksItemForm from '../hooks/StocksItemFormHook.js';
|
||||||
|
import StocksItemForm from './StocksItemForm.jsx';
|
||||||
|
|
||||||
|
const StocksForm = ({ id }) => {
|
||||||
|
const navigate = useNavigate();
|
||||||
|
|
||||||
|
const {
|
||||||
|
stocks,
|
||||||
|
validated,
|
||||||
|
handleSubmit,
|
||||||
|
handleChange,
|
||||||
|
} = useStocksItemForm(id);
|
||||||
|
|
||||||
|
const onBack = () => {
|
||||||
|
navigate(-1);
|
||||||
|
};
|
||||||
|
|
||||||
|
const onSubmit = async (event) => {
|
||||||
|
if (await handleSubmit(event)) {
|
||||||
|
onBack();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Form className='m-0 p-2' noValidate validated={validated} onSubmit={onSubmit}>
|
||||||
|
<StocksItemForm item={stocks} handleChange={handleChange} />
|
||||||
|
<Form.Group className='row justify-content-center m-0 mt-3'>
|
||||||
|
<Button className='col-5 col-lg-2 m-0 me-2' variant='secondary' onClick={() => onBack()}>
|
||||||
|
Назад
|
||||||
|
</Button>
|
||||||
|
<Button className='col-5 col-lg-2 m-0 ms-2' type='submit' variant='primary'>
|
||||||
|
Сохранить
|
||||||
|
</Button>
|
||||||
|
</Form.Group>
|
||||||
|
</Form>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
StocksForm.propTypes = {
|
||||||
|
id: PropTypes.string,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default StocksForm;
|
19
lab5/src/components/lines/form/StocksItemForm.jsx
Normal file
19
lab5/src/components/lines/form/StocksItemForm.jsx
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import Input from '../../input/Input.jsx';
|
||||||
|
|
||||||
|
const StocksItemForm = ({ item, handleChange }) => {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<h1 className="text-warning text-center font-weight-bold">Добавление акции</h1>
|
||||||
|
<Input name='name' label='Наименование акции ' value={item.name} onChange={handleChange} required />
|
||||||
|
<Input name='value' label='Значение акции' value={item.value} max='100' onChange={handleChange} required />
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
StocksItemForm.propTypes = {
|
||||||
|
item: PropTypes.object,
|
||||||
|
handleChange: PropTypes.func,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default StocksItemForm;
|
@ -1,11 +1,24 @@
|
|||||||
import { useState } from 'react';
|
import { useState, useEffect } from 'react';
|
||||||
import toast from 'react-hot-toast';
|
import toast from 'react-hot-toast';
|
||||||
import getBase64FromFile from '../../utils/Base64';
|
import getBase64FromFile from '../../utils/Base64';
|
||||||
import LinesApiService from '../service/LinesApiService';
|
import LinesApiService from '../service/LinesApiService';
|
||||||
|
import StocksApiService from '../service/StocksApiService';
|
||||||
import useLinesItem from './LinesItemHook';
|
import useLinesItem from './LinesItemHook';
|
||||||
|
|
||||||
const useLinesItemForm = (id, linesChangeHandle) => {
|
const useLinesItemForm = (id, linesChangeHandle) => {
|
||||||
const { item, setItem } = useLinesItem(id);
|
const { item, setItem } = useLinesItem(id);
|
||||||
|
const [stockData, setStockData] = useState(null);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (item.stock) {
|
||||||
|
StocksApiService.getById(item.stock)
|
||||||
|
.then(response => setStockData(response))
|
||||||
|
.catch(error => {
|
||||||
|
console.error('Ошибка при получении данных акции:', error);
|
||||||
|
setStockData(null);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, [item.stock]);
|
||||||
|
|
||||||
const [validated, setValidated] = useState(false);
|
const [validated, setValidated] = useState(false);
|
||||||
|
|
||||||
@ -16,10 +29,11 @@ const useLinesItemForm = (id, linesChangeHandle) => {
|
|||||||
const getLineObject = (formData) => {
|
const getLineObject = (formData) => {
|
||||||
const typeId = parseInt(formData.typeId, 10);
|
const typeId = parseInt(formData.typeId, 10);
|
||||||
const price = parseFloat(formData.price).toFixed(2);
|
const price = parseFloat(formData.price).toFixed(2);
|
||||||
const stock = formData.stock !== '' ? parseInt(formData.stock, 10) : null;
|
const stock = stockData.value;
|
||||||
const count = parseInt(formData.count, 10);
|
const count = parseInt(formData.count, 10);
|
||||||
let sum;
|
let sum;
|
||||||
if (stock !== null) {
|
|
||||||
|
if (stockData !== null) {
|
||||||
sum = parseFloat((price * ((100 - stock) / 100)) * count).toFixed(2);
|
sum = parseFloat((price * ((100 - stock) / 100)) * count).toFixed(2);
|
||||||
} else {
|
} else {
|
||||||
sum = parseFloat(price * count).toFixed(2);
|
sum = parseFloat(price * count).toFixed(2);
|
||||||
@ -29,7 +43,7 @@ const useLinesItemForm = (id, linesChangeHandle) => {
|
|||||||
return {
|
return {
|
||||||
typeId: typeId.toString(),
|
typeId: typeId.toString(),
|
||||||
price: price.toString(),
|
price: price.toString(),
|
||||||
stock: stock !== null ? stock.toString() : '',
|
stock: stock,
|
||||||
count: count.toString(),
|
count: count.toString(),
|
||||||
sum: sum.toString(),
|
sum: sum.toString(),
|
||||||
image,
|
image,
|
||||||
@ -45,11 +59,22 @@ const useLinesItemForm = (id, linesChangeHandle) => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleStockChange = (event) => {
|
||||||
|
setItem({
|
||||||
|
...item,
|
||||||
|
stock: event.target.value,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
const handleChange = (event) => {
|
const handleChange = (event) => {
|
||||||
if (event.target.type === 'file') {
|
if (event.target.type === 'file') {
|
||||||
handleImageChange(event);
|
handleImageChange(event);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (event.target.name === 'stock') {
|
||||||
|
handleStockChange(event);
|
||||||
|
return;
|
||||||
|
}
|
||||||
const inputName = event.target.name;
|
const inputName = event.target.name;
|
||||||
const inputValue = event.target.type === 'checkbox' ? event.target.checked : event.target.value;
|
const inputValue = event.target.type === 'checkbox' ? event.target.checked : event.target.value;
|
||||||
setItem({
|
setItem({
|
||||||
@ -82,6 +107,7 @@ const useLinesItemForm = (id, linesChangeHandle) => {
|
|||||||
validated,
|
validated,
|
||||||
handleSubmit,
|
handleSubmit,
|
||||||
handleChange,
|
handleChange,
|
||||||
|
handleStockChange,
|
||||||
resetValidity,
|
resetValidity,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -5,9 +5,9 @@ const useLinesItem = (id) => {
|
|||||||
const emptyItem = {
|
const emptyItem = {
|
||||||
id: '',
|
id: '',
|
||||||
typeId: '',
|
typeId: '',
|
||||||
price: '0',
|
price: '',
|
||||||
stock: '',
|
stock: '',
|
||||||
count: '0',
|
count: '',
|
||||||
image: '',
|
image: '',
|
||||||
};
|
};
|
||||||
const [item, setItem] = useState({ ...emptyItem });
|
const [item, setItem] = useState({ ...emptyItem });
|
||||||
|
34
lab5/src/components/lines/hooks/StocksDeleteModalHook.js
Normal file
34
lab5/src/components/lines/hooks/StocksDeleteModalHook.js
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
import { useState } from 'react';
|
||||||
|
import toast from 'react-hot-toast';
|
||||||
|
import useModal from '../../modal/ModalHook';
|
||||||
|
import StocksApiService from '../service/StocksApiService';
|
||||||
|
|
||||||
|
const useStocksDeleteModal = (linesChangeHandle) => {
|
||||||
|
const { isModalShow, showModal, hideModal } = useModal();
|
||||||
|
const [currentId, setCurrentId] = useState(0);
|
||||||
|
|
||||||
|
const showModalDialogStock = (id) => {
|
||||||
|
showModal();
|
||||||
|
setCurrentId(id);
|
||||||
|
};
|
||||||
|
|
||||||
|
const onCloseStock = () => {
|
||||||
|
hideModal();
|
||||||
|
};
|
||||||
|
|
||||||
|
const onDeleteStock = async () => {
|
||||||
|
await StocksApiService.delete(currentId);
|
||||||
|
linesChangeHandle();
|
||||||
|
toast.success('Акция успешно удалена', { id: 'StocksTable' });
|
||||||
|
onCloseStock();
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
isDeleteModalShowStock: isModalShow,
|
||||||
|
showDeleteModalStock: showModalDialogStock,
|
||||||
|
handleDeleteConfirmStock: onDeleteStock,
|
||||||
|
handleDeleteCancelStock: onCloseStock,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export default useStocksDeleteModal;
|
25
lab5/src/components/lines/hooks/StocksHook.js
Normal file
25
lab5/src/components/lines/hooks/StocksHook.js
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
import { useEffect, useState } from 'react';
|
||||||
|
import StocksApiService from '../service/StocksApiService';
|
||||||
|
|
||||||
|
const useStocks = () => {
|
||||||
|
const [stocksRefresh, setStocksRefresh] = useState(false);
|
||||||
|
const [stocks, setStocks] = useState([]);
|
||||||
|
const handleStocksChange = () => setStocksRefresh(!stocksRefresh);
|
||||||
|
|
||||||
|
const getStocks = async () => {
|
||||||
|
let expand = '?_expand=';
|
||||||
|
const data = await StocksApiService.getAll(expand);
|
||||||
|
setStocks(data ?? []);
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
getStocks();
|
||||||
|
}, [stocksRefresh]);
|
||||||
|
|
||||||
|
return {
|
||||||
|
stocks,
|
||||||
|
handleStocksChange,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export default useStocks;
|
62
lab5/src/components/lines/hooks/StocksItemFormHook.js
Normal file
62
lab5/src/components/lines/hooks/StocksItemFormHook.js
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
import { useState } from 'react';
|
||||||
|
import toast from 'react-hot-toast';
|
||||||
|
import StocksApiService from '../service/StocksApiService';
|
||||||
|
import useStocksItem from './StocksItemHook.js';
|
||||||
|
|
||||||
|
const useStocksItemForm = (id, linesChangeHandle) => {
|
||||||
|
const { stocks, setStock } = useStocksItem(id);
|
||||||
|
const [validated, setValidated] = useState(null);
|
||||||
|
|
||||||
|
const resetValidity = () => {
|
||||||
|
setValidated(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
const getStockObject = (formData) => {
|
||||||
|
const name = formData.name;
|
||||||
|
const value = parseInt(formData.value, 10);
|
||||||
|
return {
|
||||||
|
name: name.toString(),
|
||||||
|
value: value.toString(),
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleChange = (event) => {
|
||||||
|
const inputName = event.target.name;
|
||||||
|
const inputValue = event.target.type === 'checkbox' ? event.target.checked : event.target.value;
|
||||||
|
setStock({
|
||||||
|
...stocks,
|
||||||
|
[inputName]: inputValue,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSubmit = async (event) => {
|
||||||
|
const form = event.currentTarget;
|
||||||
|
event.preventDefault();
|
||||||
|
event.stopPropagation();
|
||||||
|
const body = getStockObject(stocks);
|
||||||
|
|
||||||
|
if (form.checkValidity()) {
|
||||||
|
if (id === undefined) {
|
||||||
|
await StocksApiService.create(body);
|
||||||
|
} else {
|
||||||
|
await StocksApiService.update(id, body);
|
||||||
|
}
|
||||||
|
if (linesChangeHandle) linesChangeHandle();
|
||||||
|
toast.success('Акция успешно сохранена', { id: 'StocksTable' });
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
setValidated(true);
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
stocks,
|
||||||
|
validated,
|
||||||
|
handleSubmit,
|
||||||
|
handleChange,
|
||||||
|
resetValidity,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export default useStocksItemForm;
|
32
lab5/src/components/lines/hooks/StocksItemHook.js
Normal file
32
lab5/src/components/lines/hooks/StocksItemHook.js
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
import { useEffect, useState } from 'react';
|
||||||
|
import TypesApiService from '../service/StocksApiService';
|
||||||
|
|
||||||
|
const useStocksItem = (id) => {
|
||||||
|
const emptyStocks = {
|
||||||
|
id: '',
|
||||||
|
name: '',
|
||||||
|
stock: '',
|
||||||
|
};
|
||||||
|
const [stocks, setStock] = useState({ ...emptyStocks });
|
||||||
|
|
||||||
|
const getStock = async (stockId = undefined) => {
|
||||||
|
if (stockId && stockId > 0) {
|
||||||
|
const data = await TypesApiService.get(stockId);
|
||||||
|
setStock(data);
|
||||||
|
} else {
|
||||||
|
setStock({ ...emptyStocks });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
getStock(id);
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
}, [id]);
|
||||||
|
|
||||||
|
return {
|
||||||
|
stocks,
|
||||||
|
setStock,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export default useStocksItem;
|
11
lab5/src/components/lines/service/StocksApiService.js
Normal file
11
lab5/src/components/lines/service/StocksApiService.js
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
import ApiService from '../../api/ApiService';
|
||||||
|
|
||||||
|
class StocksApiService extends ApiService {
|
||||||
|
async getById(id) {
|
||||||
|
return this.get(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const TypesApiService = new StocksApiService('stocks');
|
||||||
|
|
||||||
|
export default TypesApiService;
|
@ -3,15 +3,27 @@ import { Link, useNavigate } from 'react-router-dom';
|
|||||||
import Select from '../../input/Select.jsx';
|
import Select from '../../input/Select.jsx';
|
||||||
import ModalConfirm from '../../modal/ModalConfirm.jsx';
|
import ModalConfirm from '../../modal/ModalConfirm.jsx';
|
||||||
import useLinesDeleteModal from '../hooks/LinesDeleteModalHook';
|
import useLinesDeleteModal from '../hooks/LinesDeleteModalHook';
|
||||||
|
import useStocksDeleteModal from '../hooks/StocksDeleteModalHook';
|
||||||
import useTypeFilter from '../hooks/LinesFilterHook';
|
import useTypeFilter from '../hooks/LinesFilterHook';
|
||||||
import useLines from '../hooks/LinesHook';
|
import useLines from '../hooks/LinesHook';
|
||||||
import LinesTable from './LinesTable.jsx';
|
import LinesTable from './LinesTable.jsx';
|
||||||
import LinesTableRow from './LinesTableRow.jsx';
|
import LinesTableRow from './LinesTableRow.jsx';
|
||||||
|
import StocksTable from './StocksTable.jsx';
|
||||||
|
import StocksTableRow from './StocksTableRow.jsx';
|
||||||
|
import useStocks from '../hooks/StocksHook.js';
|
||||||
|
|
||||||
const Lines = () => {
|
const Lines = () => {
|
||||||
const { types, currentFilter, handleFilterChange } = useTypeFilter();
|
const { types, currentFilter, handleFilterChange } = useTypeFilter();
|
||||||
const { lines, handleLinesChange } = useLines(currentFilter);
|
const { lines, handleLinesChange } = useLines(currentFilter);
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
const { stocks, handleStocksChange } = useStocks();
|
||||||
|
|
||||||
|
const {
|
||||||
|
isDeleteModalShowStock,
|
||||||
|
showDeleteModalStock,
|
||||||
|
handleDeleteConfirmStock,
|
||||||
|
handleDeleteCancelStock,
|
||||||
|
} = useStocksDeleteModal(handleStocksChange);
|
||||||
|
|
||||||
const {
|
const {
|
||||||
isDeleteModalShow,
|
isDeleteModalShow,
|
||||||
@ -28,6 +40,14 @@ const Lines = () => {
|
|||||||
showDeleteModal(id);
|
showDeleteModal(id);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const showEditStocksPage = (id) => {
|
||||||
|
navigate(`/PageEditStocks/${id}`);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleDeleteStock = (id) => {
|
||||||
|
showDeleteModalStock(id);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<h1 className="text-warning text-center font-weight-bold">Панель администратора</h1>
|
<h1 className="text-warning text-center font-weight-bold">Панель администратора</h1>
|
||||||
@ -36,6 +56,9 @@ const Lines = () => {
|
|||||||
<Button as={Link} to='/pageEdit' variant='warning'>
|
<Button as={Link} to='/pageEdit' variant='warning'>
|
||||||
Добавить товар
|
Добавить товар
|
||||||
</Button>
|
</Button>
|
||||||
|
<Button as={Link} to='/PageEditStocks' variant='warning'>
|
||||||
|
Добавить акцию
|
||||||
|
</Button>
|
||||||
</ButtonGroup>
|
</ButtonGroup>
|
||||||
</div>
|
</div>
|
||||||
<Select className='mt-2' values={types} label='Фильтр по товарам'
|
<Select className='mt-2' values={types} label='Фильтр по товарам'
|
||||||
@ -51,9 +74,25 @@ const Lines = () => {
|
|||||||
/>)
|
/>)
|
||||||
}
|
}
|
||||||
</LinesTable>
|
</LinesTable>
|
||||||
|
|
||||||
|
<h2 className="text-warning text-center font-weight-bold mt-2">Таблица акций</h2>
|
||||||
|
<StocksTable>
|
||||||
|
{
|
||||||
|
stocks.map((stock, index) =>
|
||||||
|
<StocksTableRow key={stock.id}
|
||||||
|
index={index} stock={stock}
|
||||||
|
onDelete={() => handleDeleteStock(stock.id)}
|
||||||
|
onEdit={() => showEditStocksPage(stock.id)}
|
||||||
|
/>)
|
||||||
|
}
|
||||||
|
</StocksTable>
|
||||||
|
|
||||||
<ModalConfirm show={isDeleteModalShow}
|
<ModalConfirm show={isDeleteModalShow}
|
||||||
onConfirm={handleDeleteConfirm} onClose={handleDeleteCancel}
|
onConfirm={handleDeleteConfirm} onClose={handleDeleteCancel}
|
||||||
title='Удаление' message='Удалить элемент?' />
|
title='Удаление' message='Удалить элемент?' />
|
||||||
|
<ModalConfirm show={isDeleteModalShowStock}
|
||||||
|
onConfirm={handleDeleteConfirmStock} onClose={handleDeleteCancelStock}
|
||||||
|
title='Удаление' message='Удалить акцию?' />
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
27
lab5/src/components/lines/table/StocksTable.jsx
Normal file
27
lab5/src/components/lines/table/StocksTable.jsx
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import { Table } from 'react-bootstrap';
|
||||||
|
|
||||||
|
const StocksTable = ({ children }) => {
|
||||||
|
return (
|
||||||
|
<Table className='mt-2' striped responsive>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th scope="col">№</th>
|
||||||
|
<th scope="col" className="w-25">Имя акции</th>
|
||||||
|
<th scope="col" className="w-75">Значение акции</th>
|
||||||
|
<th scope="col"></th>
|
||||||
|
<th scope="col"></th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{children}
|
||||||
|
</tbody >
|
||||||
|
</Table>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
StocksTable.propTypes = {
|
||||||
|
children: PropTypes.node,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default StocksTable;
|
30
lab5/src/components/lines/table/StocksTableRow.jsx
Normal file
30
lab5/src/components/lines/table/StocksTableRow.jsx
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import { PencilSquare, Trash3 } from 'react-bootstrap-icons';
|
||||||
|
|
||||||
|
const StocksTableRow = ({
|
||||||
|
index, stock, onDelete, onEdit
|
||||||
|
}) => {
|
||||||
|
const handleAnchorClick = (event, action) => {
|
||||||
|
event.preventDefault();
|
||||||
|
action();
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<tr>
|
||||||
|
<th scope="row">{index + 1}</th>
|
||||||
|
<td>{stock.name}</td>
|
||||||
|
<td>{stock.value}</td>
|
||||||
|
<td><a href="#" onClick={(event) => handleAnchorClick(event, onEdit)}><PencilSquare /></a></td>
|
||||||
|
<td><a href="#" onClick={(event) => handleAnchorClick(event, onDelete)}><Trash3 /></a></td>
|
||||||
|
</tr>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
StocksTableRow.propTypes = {
|
||||||
|
index: PropTypes.number,
|
||||||
|
stock: PropTypes.object,
|
||||||
|
onDelete: PropTypes.func,
|
||||||
|
onEdit: PropTypes.func,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default StocksTableRow;
|
21
lab5/src/components/types/hooks/StockHook.js
Normal file
21
lab5/src/components/types/hooks/StockHook.js
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
import { useEffect, useState } from 'react';
|
||||||
|
import StocksApiService from '../../lines/service/StocksApiService';
|
||||||
|
|
||||||
|
const useStocks = () => {
|
||||||
|
const [stocks, setStocks] = useState([]);
|
||||||
|
|
||||||
|
const getStocks = async () => {
|
||||||
|
const data = await StocksApiService.getAll();
|
||||||
|
setStocks(data ?? []);
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
getStocks();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return {
|
||||||
|
stocks,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export default useStocks;
|
@ -16,6 +16,7 @@ import Administrator from './pages/Administrator.jsx';
|
|||||||
import Basket from './pages/Basket.jsx';
|
import Basket from './pages/Basket.jsx';
|
||||||
import MakingAnOrder from './pages/MakingAnOrder.jsx';
|
import MakingAnOrder from './pages/MakingAnOrder.jsx';
|
||||||
import PageEdit from './pages/PageEdit.jsx';
|
import PageEdit from './pages/PageEdit.jsx';
|
||||||
|
import PageEditStocks from './pages/PageEditStocs.jsx';
|
||||||
|
|
||||||
const routes = [
|
const routes = [
|
||||||
{
|
{
|
||||||
@ -66,6 +67,10 @@ const routes = [
|
|||||||
path: '/PageEdit/:id?',
|
path: '/PageEdit/:id?',
|
||||||
element: <PageEdit/>,
|
element: <PageEdit/>,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: '/PageEditStocks/:id?',
|
||||||
|
element: <PageEditStocks/>,
|
||||||
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
const router = createBrowserRouter([
|
const router = createBrowserRouter([
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import { Container, Row, Col } from 'react-bootstrap';
|
import { Container, Row, Col } from 'react-bootstrap';
|
||||||
import BasketCard from '../components/card/BasketCard';
|
import BasketCard from '../components/card/BasketCard';
|
||||||
|
import { Link } from 'react-router-dom';
|
||||||
|
|
||||||
const Basket = () => {
|
const Basket = () => {
|
||||||
return (
|
return (
|
||||||
@ -24,7 +25,9 @@ const Basket = () => {
|
|||||||
Сумма ₽
|
Сумма ₽
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<a className="btn btn-warning" style={{ marginLeft: '25px', marginBottom: '10px' }} href="makingAnOrder">К оплате</a>
|
<Link to='/MakingAnOrder' className="btn btn-warning" style={{ marginLeft: '25px', marginBottom: '10px' }}>
|
||||||
|
К оплате
|
||||||
|
</Link>
|
||||||
</Container>
|
</Container>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -13,7 +13,7 @@ const Contacts = () => {
|
|||||||
<iframe
|
<iframe
|
||||||
src="https://yandex.ru/map-widget/v1/?um=constructor%3A0643c92cbdf3809080e5dfb2804b473ea00af31cfabe6fee08676c59d8675f01&source=constructor"
|
src="https://yandex.ru/map-widget/v1/?um=constructor%3A0643c92cbdf3809080e5dfb2804b473ea00af31cfabe6fee08676c59d8675f01&source=constructor"
|
||||||
className="img-fluid"
|
className="img-fluid"
|
||||||
style={{ width: '100%', height: '720px' }}
|
style={{ width: '100%', height: '500px' }}
|
||||||
title="Yandex Map"
|
title="Yandex Map"
|
||||||
></iframe>
|
></iframe>
|
||||||
</Col>
|
</Col>
|
||||||
|
@ -2,7 +2,7 @@ import { useState } from 'react';
|
|||||||
import { Container, Row, Col, Card, Form, Button } from 'react-bootstrap';
|
import { Container, Row, Col, Card, Form, Button } from 'react-bootstrap';
|
||||||
|
|
||||||
const MakingAnOrder = () => {
|
const MakingAnOrder = () => {
|
||||||
const [deliveryMethod, setDeliveryMethod] = useState('selfPickup');
|
const [deliveryMethod, setDeliveryMethod] = useState('selfPickup');
|
||||||
const [paymentMethod, setPaymentMethod] = useState('cash');
|
const [paymentMethod, setPaymentMethod] = useState('cash');
|
||||||
|
|
||||||
const handleDeliveryMethodChange = (e) => {
|
const handleDeliveryMethodChange = (e) => {
|
||||||
@ -35,7 +35,7 @@ const MakingAnOrder = () => {
|
|||||||
|
|
||||||
<Form noValidate validated={validated} onSubmit={handleSubmit}>
|
<Form noValidate validated={validated} onSubmit={handleSubmit}>
|
||||||
<Form.Group className="mb-4" controlId="name">
|
<Form.Group className="mb-4" controlId="name">
|
||||||
<Form.Label htmlFor="name">Ваше имя</Form.Label>
|
<Form.Label>Ваше имя</Form.Label>
|
||||||
<Form.Control type="text" required />
|
<Form.Control type="text" required />
|
||||||
<Form.Control.Feedback>Имя заполнено</Form.Control.Feedback>
|
<Form.Control.Feedback>Имя заполнено</Form.Control.Feedback>
|
||||||
<Form.Control.Feedback type="invalid">Имя не заполнено</Form.Control.Feedback>
|
<Form.Control.Feedback type="invalid">Имя не заполнено</Form.Control.Feedback>
|
||||||
|
@ -1,174 +1,7 @@
|
|||||||
//import { useState } from 'react';
|
|
||||||
//import { Container, Col, Row, Form, Button } from 'react-bootstrap';
|
|
||||||
|
|
||||||
import { useParams } from 'react-router-dom';
|
import { useParams } from 'react-router-dom';
|
||||||
import LinesForm from '../components/lines/form/LinesForm.jsx';
|
import LinesForm from '../components/lines/form/LinesForm.jsx';
|
||||||
|
|
||||||
const PageEdit = () => {
|
const PageEdit = () => {
|
||||||
/*const [validated, setValidated] = useState(false);
|
|
||||||
|
|
||||||
const handleSubmit = (event) => {
|
|
||||||
const form = event.currentTarget;
|
|
||||||
if (form.checkValidity() === false) {
|
|
||||||
event.preventDefault();
|
|
||||||
event.stopPropagation();
|
|
||||||
}
|
|
||||||
|
|
||||||
setValidated(true);
|
|
||||||
};
|
|
||||||
|
|
||||||
const [selectedItem, setSelectedItem] = useState('');
|
|
||||||
const [price, setPrice] = useState(0.00);
|
|
||||||
const [stock, setStock] = useState(0);
|
|
||||||
const [count, setCount] = useState(0);
|
|
||||||
const [imagePreview, setImagePreview] = useState('https://via.placeholder.com/200');
|
|
||||||
|
|
||||||
const handleItemChange = (e) => {
|
|
||||||
setSelectedItem(e.target.value);
|
|
||||||
};
|
|
||||||
|
|
||||||
const handlePriceChange = (e) => {
|
|
||||||
setPrice(parseFloat(e.target.value));
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleStockChange = (e) => {
|
|
||||||
setStock(parseInt(e.target.value, 10));
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleCountChange = (e) => {
|
|
||||||
setCount(parseInt(e.target.value, 10));
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleImageChange = (e) => {
|
|
||||||
const file = e.target.files[0];
|
|
||||||
|
|
||||||
if (file) {
|
|
||||||
const reader = new FileReader();
|
|
||||||
|
|
||||||
reader.onloadend = () => {
|
|
||||||
const img = new Image();
|
|
||||||
img.src = reader.result;
|
|
||||||
|
|
||||||
img.onload = () => {
|
|
||||||
const canvas = document.createElement('canvas');
|
|
||||||
const ctx = canvas.getContext('2d');
|
|
||||||
|
|
||||||
const maxWidth = 200;
|
|
||||||
const maxHeight = 200;
|
|
||||||
let width = img.width;
|
|
||||||
let height = img.height;
|
|
||||||
|
|
||||||
if (width > height) {
|
|
||||||
if (width > maxWidth) {
|
|
||||||
height *= maxWidth / width;
|
|
||||||
width = maxWidth;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (height > maxHeight) {
|
|
||||||
width *= maxHeight / height;
|
|
||||||
height = maxHeight;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
canvas.width = width;
|
|
||||||
canvas.height = height;
|
|
||||||
|
|
||||||
ctx.drawImage(img, 0, 0, width, height);
|
|
||||||
|
|
||||||
setImagePreview(canvas.toDataURL('image/png'));
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
reader.readAsDataURL(file);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Container fluid className="p-2">
|
|
||||||
<h1 className="text-warning text-center font-weight-bold">Добавление товара</h1>
|
|
||||||
<Row className="text-center">
|
|
||||||
<Col>
|
|
||||||
<img id="image-preview" src={imagePreview} className="rounded rounded-circle" alt="placeholder" />
|
|
||||||
</Col>
|
|
||||||
</Row>
|
|
||||||
<Form
|
|
||||||
id="items-form"
|
|
||||||
className="needs-validation"
|
|
||||||
noValidate
|
|
||||||
validated={validated}
|
|
||||||
onSubmit={handleSubmit}
|
|
||||||
>
|
|
||||||
<Form.Group controlId="item" className="mb-2">
|
|
||||||
<Form.Label>Товары</Form.Label>
|
|
||||||
<Form.Control
|
|
||||||
as="select"
|
|
||||||
name="selected"
|
|
||||||
onChange={handleItemChange}
|
|
||||||
value={selectedItem}
|
|
||||||
required
|
|
||||||
>
|
|
||||||
</Form.Control>
|
|
||||||
<Form.Control.Feedback type="invalid">Пожалуйста, выберите товар.</Form.Control.Feedback>
|
|
||||||
</Form.Group>
|
|
||||||
<Form.Group controlId="price" className="mb-2">
|
|
||||||
<Form.Label>Цена</Form.Label>
|
|
||||||
<Form.Control
|
|
||||||
type="number"
|
|
||||||
name="price"
|
|
||||||
value={price}
|
|
||||||
min="1000.00"
|
|
||||||
step="0.50"
|
|
||||||
onChange={handlePriceChange}
|
|
||||||
required
|
|
||||||
/>
|
|
||||||
<Form.Control.Feedback type="invalid">Пожалуйста, введите цену.</Form.Control.Feedback>
|
|
||||||
</Form.Group>
|
|
||||||
<Form.Group controlId="stock" className="mb-2">
|
|
||||||
<Form.Label>Акция</Form.Label>
|
|
||||||
<Form.Control
|
|
||||||
type="number"
|
|
||||||
name="price"
|
|
||||||
value={stock}
|
|
||||||
min="0"
|
|
||||||
step="1"
|
|
||||||
onChange={handleStockChange}
|
|
||||||
required
|
|
||||||
/>
|
|
||||||
<Form.Control.Feedback type="invalid">Пожалуйста, введите акцию.</Form.Control.Feedback>
|
|
||||||
</Form.Group>
|
|
||||||
<Form.Group controlId="count" className="mb-2">
|
|
||||||
<Form.Label>Количество</Form.Label>
|
|
||||||
<Form.Control
|
|
||||||
type="number"
|
|
||||||
name="count"
|
|
||||||
value={count}
|
|
||||||
min="1"
|
|
||||||
step="1"
|
|
||||||
onChange={handleCountChange}
|
|
||||||
required
|
|
||||||
/>
|
|
||||||
<Form.Control.Feedback type="invalid">Пожалуйста, введите количество.</Form.Control.Feedback>
|
|
||||||
</Form.Group>
|
|
||||||
<Form.Group controlId="image" className="mb-2">
|
|
||||||
<Form.Label>Изображение</Form.Label>
|
|
||||||
<Form.Control
|
|
||||||
type="file"
|
|
||||||
name="image"
|
|
||||||
accept="image/*"
|
|
||||||
onChange={handleImageChange}
|
|
||||||
/>
|
|
||||||
<Form.Control.Feedback type="invalid">Пожалуйста, выберите изображение.</Form.Control.Feedback>
|
|
||||||
</Form.Group>
|
|
||||||
<Row className="mb-2">
|
|
||||||
<Col>
|
|
||||||
<Button href="Administrator" className="btn btn-secondary">Назад</Button>
|
|
||||||
<Button type="submit" className="btn btn-primary">Сохранить</Button>
|
|
||||||
</Col>
|
|
||||||
</Row>
|
|
||||||
</Form>
|
|
||||||
</Container>
|
|
||||||
);*/
|
|
||||||
|
|
||||||
const { id } = useParams();
|
const { id } = useParams();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
12
lab5/src/pages/PageEditStocs.jsx
Normal file
12
lab5/src/pages/PageEditStocs.jsx
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
import { useParams } from 'react-router-dom';
|
||||||
|
import StocksForm from '../components/lines/form/StocksForm';
|
||||||
|
|
||||||
|
const PageEditStocks = () => {
|
||||||
|
const { id } = useParams();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<StocksForm id={id} />
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default PageEditStocks;
|
@ -1,5 +1,6 @@
|
|||||||
import { Container, Row, Col, Card, Form, Button } from 'react-bootstrap';
|
import { Container, Row, Col, Card, Form, Button } from 'react-bootstrap';
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
|
import { Link } from 'react-router-dom';
|
||||||
|
|
||||||
const PasswordRecovery = () => {
|
const PasswordRecovery = () => {
|
||||||
const [validated, setValidated] = useState(false);
|
const [validated, setValidated] = useState(false);
|
||||||
@ -39,15 +40,11 @@ const PasswordRecovery = () => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<p className="text-center text-muted mb-0">
|
<p className="text-center text-muted mb-0">
|
||||||
<a href="personalAccountLogin" className="fw-bold text-body">
|
<Link className="fw-bold text-body" to='/PersonalAccountLogin' style={{ color: 'black', textDecoration: 'none' }}><u>Войти</u></Link>
|
||||||
<u>Войти</u>
|
|
||||||
</a>
|
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p className="text-center text-muted mb-0">
|
<p className="text-center text-muted mb-0">
|
||||||
<a href="personalAccountRegister" className="fw-bold text-body">
|
<Link className="fw-bold text-body" to='/PersonalAccountRegister' style={{ color: 'black', textDecoration: 'none' }}><u>Регистрация</u></Link>
|
||||||
<u>Регистрация</u>
|
|
||||||
</a>
|
|
||||||
</p>
|
</p>
|
||||||
</Form>
|
</Form>
|
||||||
</Card.Body>
|
</Card.Body>
|
||||||
|
@ -1,36 +1,18 @@
|
|||||||
/* eslint-disable linebreak-style */
|
|
||||||
/* eslint-disable object-curly-newline */
|
|
||||||
/* eslint-disable linebreak-style */
|
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import { Container, Row, Col, Card, Form, Button } from 'react-bootstrap';
|
import { Container, Row, Col, Card, Form, Button } from 'react-bootstrap';
|
||||||
|
import { Link } from 'react-router-dom';
|
||||||
|
|
||||||
const PersonalAccount = () => {
|
const PersonalAccount = () => {
|
||||||
const [validated, setValidated] = useState(false);
|
const [validated, setValidated] = useState(false);
|
||||||
const [formData, setFormData] = useState({
|
|
||||||
lastname: '',
|
|
||||||
firstname: '',
|
|
||||||
email: '',
|
|
||||||
date: '',
|
|
||||||
tel: '',
|
|
||||||
});
|
|
||||||
|
|
||||||
const handleSubmit = (event) => {
|
const handleSubmit = (event) => {
|
||||||
const form = event.currentTarget;
|
const form = event.currentTarget;
|
||||||
event.preventDefault();
|
if (form.checkValidity() === false) {
|
||||||
event.stopPropagation();
|
event.preventDefault();
|
||||||
if (form.checkValidity() !== false) {
|
event.stopPropagation();
|
||||||
console.log(formData);
|
|
||||||
}
|
}
|
||||||
setValidated(true);
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleChange = (event) => {
|
setValidated(true);
|
||||||
const inputName = event.target.name;
|
|
||||||
const inputValue = event.target.type === 'checkbox' ? event.target.checked : event.target.value;
|
|
||||||
setFormData({
|
|
||||||
...formData,
|
|
||||||
[inputName]: inputValue,
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -39,61 +21,56 @@ const PersonalAccount = () => {
|
|||||||
<Col xs={12} md={9} lg={7} xl={6}>
|
<Col xs={12} md={9} lg={7} xl={6}>
|
||||||
<Card style={{ borderRadius: '15px', borderColor: 'gold' }}>
|
<Card style={{ borderRadius: '15px', borderColor: 'gold' }}>
|
||||||
<Card.Body className="p-5">
|
<Card.Body className="p-5">
|
||||||
<h2 className="text-uppercase text-center mb-5">Личный кабинет</h2>
|
<h2 className="text-uppercase text-center mb-5">Личный кабинет</h2>
|
||||||
|
|
||||||
<Form noValidate validated={validated} onSubmit={handleSubmit}>
|
<Form noValidate validated={validated} onSubmit={handleSubmit}>
|
||||||
<Form.Group className='mb-2' controlId='firstname'>
|
<Form.Group className="mb-4" controlId="name">
|
||||||
<Form.Label>Имя</Form.Label>
|
<Form.Label>Ваше имя</Form.Label>
|
||||||
<Form.Control type='text' name='firstname' required
|
<Form.Control type="text" required />
|
||||||
value={formData.firstname} onChange={handleChange} />
|
<Form.Control.Feedback>Имя заполнено</Form.Control.Feedback>
|
||||||
<Form.Control.Feedback>Имя заполнено</Form.Control.Feedback>
|
<Form.Control.Feedback type="invalid">Имя не заполнено</Form.Control.Feedback>
|
||||||
<Form.Control.Feedback type='invalid'>Имя не заполнено</Form.Control.Feedback>
|
</Form.Group>
|
||||||
</Form.Group>
|
|
||||||
|
|
||||||
<Form.Group className='mb-4' controlId='lastname'>
|
<Form.Group className="mb-4" controlId="surname">
|
||||||
<Form.Label>Фамилия</Form.Label>
|
<Form.Label>Ваша фамилия</Form.Label>
|
||||||
<Form.Control type='text' name='lastname' required
|
<Form.Control type="text" required/>
|
||||||
value={formData.lastname} onChange={handleChange} />
|
<Form.Control.Feedback>Фамилия заполнена</Form.Control.Feedback>
|
||||||
<Form.Control.Feedback>Фамилия заполнена</Form.Control.Feedback>
|
<Form.Control.Feedback type="invalid">Фамилия не заполнена</Form.Control.Feedback>
|
||||||
<Form.Control.Feedback type='invalid'>Фамилия не заполнена</Form.Control.Feedback>
|
</Form.Group>
|
||||||
</Form.Group>
|
|
||||||
|
|
||||||
<Form.Group className='mb-4' controlId='email'>
|
<Form.Group className="mb-4">
|
||||||
<Form.Label>Ваш адрес электронной почты</Form.Label>
|
<Form.Label htmlFor="form3Example3cg">Ваш адрес электронной почты</Form.Label>
|
||||||
<Form.Control type='email' name='email' placeholder='name@example.ru' required
|
<Form.Control type="email" id="form3Example3cg" required />
|
||||||
value={formData.email} onChange={handleChange} />
|
<Form.Control.Feedback>Email заполнен</Form.Control.Feedback>
|
||||||
<Form.Control.Feedback>E-mail заполнен</Form.Control.Feedback>
|
<Form.Control.Feedback type="invalid">Email не заполнен</Form.Control.Feedback>
|
||||||
<Form.Control.Feedback type='invalid'>E-mail не заполнен</Form.Control.Feedback>
|
</Form.Group>
|
||||||
</Form.Group>
|
|
||||||
|
|
||||||
<Form.Group className="mb-4">
|
<Form.Group className="mb-4">
|
||||||
<Form.Label htmlFor="form3Example4cg">Дата рождения</Form.Label>
|
<Form.Label htmlFor="form3Example4cg">Дата рождения</Form.Label>
|
||||||
<Form.Control type="date" id="form3Example4cg" required
|
<Form.Control type="date" id="form3Example4cg" required />
|
||||||
value={formData.date} onChange={handleChange} />
|
<Form.Control.Feedback>Дата рождения заполнена</Form.Control.Feedback>
|
||||||
<Form.Control.Feedback>Дата рождения заполнена</Form.Control.Feedback>
|
<Form.Control.Feedback type="invalid">Дата рождения не заполнена</Form.Control.Feedback>
|
||||||
<Form.Control.Feedback type="invalid">Дата рождения не заполнена</Form.Control.Feedback>
|
</Form.Group>
|
||||||
</Form.Group>
|
|
||||||
|
|
||||||
<Form.Group className="mb-2">
|
<Form.Group className="mb-2">
|
||||||
<Form.Label htmlFor="form3Example5cg">Номер телефона</Form.Label>
|
<Form.Label htmlFor="form3Example5cg">Номер телефона</Form.Label>
|
||||||
<Form.Control type="tel" id="form3Example5cg" required
|
<Form.Control type="tel" id="form3Example5cg" required />
|
||||||
value={formData.tel} onChange={handleChange} />
|
<Form.Control.Feedback>Номер телефона заполнен</Form.Control.Feedback>
|
||||||
<Form.Control.Feedback>Номер телефона заполнен</Form.Control.Feedback>
|
<Form.Control.Feedback type="invalid">Номер телефона не заполнен</Form.Control.Feedback>
|
||||||
<Form.Control.Feedback type="invalid">Номер телефона не заполнен</Form.Control.Feedback>
|
</Form.Group>
|
||||||
</Form.Group>
|
|
||||||
|
|
||||||
<div className="d-flex justify-content-center">
|
<div className="d-flex justify-content-center">
|
||||||
<Button variant="warning" type="submit" id="saveButton">
|
<Button variant="warning" type="submit" id="saveButton">
|
||||||
Сохранить
|
Сохранить
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="d-flex justify-content-center mt-2">
|
<div className="d-flex justify-content-center mt-2">
|
||||||
<a className="btn btn-outline-danger" type="button" href="/">
|
<Link to='/' className="btn btn-outline-danger" type="button">
|
||||||
Выйти
|
Выйти
|
||||||
</a>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
</Form>
|
</Form>
|
||||||
</Card.Body>
|
</Card.Body>
|
||||||
</Card>
|
</Card>
|
||||||
</Col>
|
</Col>
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import { Container, Row, Col, Card, Form, Button } from 'react-bootstrap';
|
import { Container, Row, Col, Card, Form, Button } from 'react-bootstrap';
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
|
import { Link } from 'react-router-dom';
|
||||||
|
|
||||||
const PersonalAccountLogin = () => {
|
const PersonalAccountLogin = () => {
|
||||||
const [validated, setValidated] = useState(false);
|
const [validated, setValidated] = useState(false);
|
||||||
@ -43,28 +44,28 @@ const PersonalAccountLogin = () => {
|
|||||||
|
|
||||||
<p className="text-center text-muted mb-0">
|
<p className="text-center text-muted mb-0">
|
||||||
Забыли пароль?{' '}
|
Забыли пароль?{' '}
|
||||||
<a href="PasswordRecovery" className="fw-bold text-body">
|
<Link to='/PasswordRecovery' className="fw-bold text-body" style={{ color: 'black', textDecoration: 'none' }}>
|
||||||
<u>Восстановление пароля</u>
|
<u>Восстановление пароля</u>
|
||||||
</a>
|
</Link>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<div className="d-flex justify-content-center">
|
<div className="d-flex justify-content-center">
|
||||||
<Button variant="submit" className="btn-block btn-warning text-body mb-0" href="PersonalAccount">
|
<Button as={Link} to='/PersonalAccount' variant="submit" className="btn-block btn-warning text-body mb-0">
|
||||||
Вход
|
Вход
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<p className="text-center text-muted mb-0">
|
<p className="text-center text-muted mb-0">
|
||||||
У вас нет аккаунта?{' '}
|
У вас нет аккаунта?{' '}
|
||||||
<a href="personalAccountRegister" className="fw-bold text-body">
|
<Link to='/personalAccountRegister' className="fw-bold text-body" style={{ color: 'black', textDecoration: 'none' }}>
|
||||||
<u>Регистрация</u>
|
<u>Регистрация</u>
|
||||||
</a>
|
</Link>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p className="text-center">
|
<p className="text-center">
|
||||||
<a className="fw-bold text-body" href="Administrator">
|
<Link to='/Administrator' className="fw-bold text-body" style={{ color: 'black'}}>
|
||||||
Администратор
|
Администратор
|
||||||
</a>
|
</Link>
|
||||||
</p>
|
</p>
|
||||||
</Form>
|
</Form>
|
||||||
</Card.Body>
|
</Card.Body>
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import { Container, Row, Col, Card, Form, Button } from 'react-bootstrap';
|
import { Container, Row, Col, Card, Form, Button } from 'react-bootstrap';
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
|
import { Link } from 'react-router-dom';
|
||||||
|
|
||||||
const PersonalAccountRegister = () => {
|
const PersonalAccountRegister = () => {
|
||||||
const [validated, setValidated] = useState(false);
|
const [validated, setValidated] = useState(false);
|
||||||
@ -27,7 +28,7 @@ const PersonalAccountRegister = () => {
|
|||||||
<Form.Control type="text" required />
|
<Form.Control type="text" required />
|
||||||
<Form.Control.Feedback>Имя заполнено</Form.Control.Feedback>
|
<Form.Control.Feedback>Имя заполнено</Form.Control.Feedback>
|
||||||
<Form.Control.Feedback type="invalid">Имя не заполнено</Form.Control.Feedback>
|
<Form.Control.Feedback type="invalid">Имя не заполнено</Form.Control.Feedback>
|
||||||
<Form.Label htmlFor="name">Ваше имя</Form.Label>
|
<Form.Label>Ваше имя</Form.Label>
|
||||||
</Form.Group>
|
</Form.Group>
|
||||||
|
|
||||||
<Form.Group className="mb-4">
|
<Form.Group className="mb-4">
|
||||||
@ -63,16 +64,18 @@ const PersonalAccountRegister = () => {
|
|||||||
</Form.Group>
|
</Form.Group>
|
||||||
|
|
||||||
<div className="d-flex justify-content-center">
|
<div className="d-flex justify-content-center">
|
||||||
<Button variant="success" type="button" className="btn-block btn-warning text-body mb-0" href="PersonalAccount">
|
<Link to='/PersonalAccount' style={{color: 'black', textDecoration: 'none'}}>
|
||||||
Регистрация
|
<Button variant="success" type="button" className="btn-block btn-warning text-body mb-0">
|
||||||
</Button>
|
Регистрация
|
||||||
|
</Button>
|
||||||
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<p className="text-center text-muted mb-0">
|
<p className="text-center text-muted mb-0">
|
||||||
У вас уже есть учетная запись?{' '}
|
У вас уже есть учетная запись?{' '}
|
||||||
<a href="personalAccountLogin" className="fw-bold text-body">
|
<Link to='/PersonalAccountLogin' className="fw-bold text-body" style={{ color: 'black', textDecoration: 'none' }}>
|
||||||
<u>Войдите здесь</u>
|
<u>Войдите здесь</u>
|
||||||
</a>
|
</Link>
|
||||||
</p>
|
</p>
|
||||||
</Form>
|
</Form>
|
||||||
</Card.Body>
|
</Card.Body>
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
/* eslint-disable import/no-extraneous-dependencies */
|
|
||||||
import react from '@vitejs/plugin-react';
|
import react from '@vitejs/plugin-react';
|
||||||
import { defineConfig } from 'vite';
|
import { defineConfig } from 'vite';
|
||||||
|
|
||||||
|
BIN
Отчёты/~$тчёт 5.docx
Normal file
BIN
Отчёты/~$тчёт 5.docx
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue
Block a user