лаба 5, в процессе
This commit is contained in:
parent
77f57f9576
commit
8bf96a862c
File diff suppressed because one or more lines are too long
31
laba5/package-lock.json
generated
31
laba5/package-lock.json
generated
@ -15,6 +15,7 @@
|
|||||||
"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",
|
"react-dom": "^18.2.0",
|
||||||
|
"react-hook-form": "^7.49.3",
|
||||||
"react-hot-toast": "^2.4.1",
|
"react-hot-toast": "^2.4.1",
|
||||||
"react-router-dom": "^6.18.0"
|
"react-router-dom": "^6.18.0"
|
||||||
},
|
},
|
||||||
@ -2791,9 +2792,9 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/follow-redirects": {
|
"node_modules/follow-redirects": {
|
||||||
"version": "1.15.3",
|
"version": "1.15.4",
|
||||||
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.3.tgz",
|
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.4.tgz",
|
||||||
"integrity": "sha512-1VzOtuEM8pC9SFU1E+8KfTjZyMztRsgEfwQl44z8A25uy13jSzTj6dyK2Df52iV0vgHCfBwLhDWevLn95w5v6Q==",
|
"integrity": "sha512-Cr4D/5wlrb0z9dgERpUL3LrmPKVDsETIJhaCMeDfuFYcqa5bldGV6wBsAN6X/vxlXQtFBMrXdXxdL8CbDTGniw==",
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
"type": "individual",
|
"type": "individual",
|
||||||
@ -2880,7 +2881,7 @@
|
|||||||
},
|
},
|
||||||
"node_modules/function.prototype.name": {
|
"node_modules/function.prototype.name": {
|
||||||
"version": "1.1.6",
|
"version": "1.1.6",
|
||||||
"resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz",
|
"resolved": "https://registry.npmjs.org/function.prototype.name/-/page4.prototype.name-1.1.6.tgz",
|
||||||
"integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==",
|
"integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@ -4750,6 +4751,22 @@
|
|||||||
"react": "^18.2.0"
|
"react": "^18.2.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/react-hook-form": {
|
||||||
|
"version": "7.49.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.49.3.tgz",
|
||||||
|
"integrity": "sha512-foD6r3juidAT1cOZzpmD/gOKt7fRsDhXXZ0y28+Al1CHgX+AY1qIN9VSIIItXRq1dN68QrRwl1ORFlwjBaAqeQ==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18",
|
||||||
|
"pnpm": "8"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/react-hook-form"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": "^16.8.0 || ^17 || ^18"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/react-hot-toast": {
|
"node_modules/react-hot-toast": {
|
||||||
"version": "2.4.1",
|
"version": "2.4.1",
|
||||||
"resolved": "https://registry.npmjs.org/react-hot-toast/-/react-hot-toast-2.4.1.tgz",
|
"resolved": "https://registry.npmjs.org/react-hot-toast/-/react-hot-toast-2.4.1.tgz",
|
||||||
@ -5669,9 +5686,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/vite": {
|
"node_modules/vite": {
|
||||||
"version": "4.5.0",
|
"version": "4.5.1",
|
||||||
"resolved": "https://registry.npmjs.org/vite/-/vite-4.5.0.tgz",
|
"resolved": "https://registry.npmjs.org/vite/-/vite-4.5.1.tgz",
|
||||||
"integrity": "sha512-ulr8rNLA6rkyFAlVWw2q5YJ91v098AFQ2R0PRFwPzREXOUJQPtFUG0t+/ZikhaOCDqFoDhN6/v8Sq0o4araFAw==",
|
"integrity": "sha512-AXXFaAJ8yebyqzoNB9fu2pHoo/nWX+xZlaRwoeYUxEqBO+Zj4msE5G+BhGBll9lYEKv9Hfks52PAF2X7qDYXQA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"esbuild": "^0.18.10",
|
"esbuild": "^0.18.10",
|
||||||
|
@ -11,15 +11,16 @@
|
|||||||
"prod": "npm-run-all lint 'vite build' --parallel rest 'vite preview'"
|
"prod": "npm-run-all lint 'vite build' --parallel rest 'vite preview'"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"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",
|
"axios": "^1.6.1",
|
||||||
"bootstrap": "^5.3.2",
|
"bootstrap": "^5.3.2",
|
||||||
|
"prop-types": "^15.8.1",
|
||||||
|
"react": "^18.2.0",
|
||||||
"react-bootstrap": "^2.9.1",
|
"react-bootstrap": "^2.9.1",
|
||||||
"react-bootstrap-icons": "^1.10.3",
|
"react-bootstrap-icons": "^1.10.3",
|
||||||
"prop-types": "^15.8.1"
|
"react-dom": "^18.2.0",
|
||||||
|
"react-hook-form": "^7.49.3",
|
||||||
|
"react-hot-toast": "^2.4.1",
|
||||||
|
"react-router-dom": "^6.18.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/react": "^18.2.15",
|
"@types/react": "^18.2.15",
|
||||||
|
@ -5,10 +5,9 @@ import PropTypes from 'prop-types';
|
|||||||
import useCart from './cart/CartHook';
|
import useCart from './cart/CartHook';
|
||||||
import './Card.css';
|
import './Card.css';
|
||||||
import '../pages/Pages.css';
|
import '../pages/Pages.css';
|
||||||
import '../pages/Page3.css';
|
|
||||||
|
|
||||||
const CardOfRoom = ({
|
const CardOfRoom = ({
|
||||||
product, price, image, card,
|
product, price, image, card, size,
|
||||||
}) => {
|
}) => {
|
||||||
const { addToCart } = useCart();
|
const { addToCart } = useCart();
|
||||||
const handleAnchorClick = (event, action) => {
|
const handleAnchorClick = (event, action) => {
|
||||||
@ -16,13 +15,14 @@ const CardOfRoom = ({
|
|||||||
action();
|
action();
|
||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
<Card className='card_catalog'>
|
<Card className='card_catalog p-0'>
|
||||||
<Link to="/Page6" > <img src={image} className="card-img-top" alt="..." /></Link>
|
<Link to="" > <img src={image} className="card-img-top" alt="..." /></Link>
|
||||||
<div className="card-body">
|
<div className="card-body">
|
||||||
<p className="card-title card_name">{product}</p>
|
<p className="card-title card_name">{product}</p>
|
||||||
<div className="caption_basket_price">
|
<div className="caption_basket_price">
|
||||||
<p className="card-title card_price"> { `${parseInt(price, 10)} ₽` }</p>
|
<p className="card-title card_price"> { `${parseInt(price, 10)} ₽` }</p>
|
||||||
</div>
|
</div>
|
||||||
|
<p className="card_size"> Размер: {size} </p>
|
||||||
<div className="d-flex justify-content-center">
|
<div className="d-flex justify-content-center">
|
||||||
<Button type="submit" variant="outline-secondary" onClick={ (event) => handleAnchorClick(event, () => addToCart(card))}> Добавить в корзину</Button>
|
<Button type="submit" variant="outline-secondary" onClick={ (event) => handleAnchorClick(event, () => addToCart(card))}> Добавить в корзину</Button>
|
||||||
</div>
|
</div>
|
||||||
|
171
laba5/src/components/Register.js
Normal file
171
laba5/src/components/Register.js
Normal file
@ -0,0 +1,171 @@
|
|||||||
|
/* eslint-disable linebreak-style */
|
||||||
|
import { useRef, useState, useEffect } from 'react';
|
||||||
|
import axios from './api/axios';
|
||||||
|
|
||||||
|
const USER_REGEX = /^[A-z][A-z0-9-_]{3,23}$/;
|
||||||
|
const PWD_REGEX = /^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[!@#$%]).{8,24}$/;
|
||||||
|
const REGISTER_URL = '/register';
|
||||||
|
|
||||||
|
const Register = () => {
|
||||||
|
const userRef = useRef();
|
||||||
|
const errRef = useRef();
|
||||||
|
|
||||||
|
const [user, setUser] = useState('');
|
||||||
|
const [validName, setValidName] = useState(false);
|
||||||
|
const [userFocus, setUserFocus] = useState(false);
|
||||||
|
|
||||||
|
const [pwd, setPwd] = useState('');
|
||||||
|
const [validPwd, setValidPwd] = useState(false);
|
||||||
|
const [pwdFocus, setPwdFocus] = useState(false);
|
||||||
|
|
||||||
|
const [matchPwd, setMatchPwd] = useState('');
|
||||||
|
const [validMatch, setValidMatch] = useState(false);
|
||||||
|
const [matchFocus, setMatchFocus] = useState(false);
|
||||||
|
|
||||||
|
const [errMsg, setErrMsg] = useState('');
|
||||||
|
const [success, setSuccess] = useState(false);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
userRef.current.focus();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setValidName(USER_REGEX.test(user));
|
||||||
|
}, [user]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setValidPwd(PWD_REGEX.test(pwd));
|
||||||
|
setValidMatch(pwd === matchPwd);
|
||||||
|
}, [pwd, matchPwd]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setErrMsg('');
|
||||||
|
}, [user, pwd, matchPwd]);
|
||||||
|
|
||||||
|
const handleSubmit = async (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
// if button enabled with JS hack
|
||||||
|
const v1 = USER_REGEX.test(user);
|
||||||
|
const v2 = PWD_REGEX.test(pwd);
|
||||||
|
if (!v1 || !v2) {
|
||||||
|
setErrMsg('Invalid Entry');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
const response = await axios.post(
|
||||||
|
REGISTER_URL,
|
||||||
|
JSON.stringify({ user, pwd }),
|
||||||
|
{
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
withCredentials: true,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
console.log(response?.data);
|
||||||
|
console.log(response?.accessToken);
|
||||||
|
console.log(JSON.stringify(response));
|
||||||
|
setSuccess(true);
|
||||||
|
setUser('');
|
||||||
|
setPwd('');
|
||||||
|
setMatchPwd('');
|
||||||
|
} catch (err) {
|
||||||
|
if (!err?.response) {
|
||||||
|
setErrMsg('No Server Response');
|
||||||
|
} else if (err.response?.status === 409) {
|
||||||
|
setErrMsg('Username Taken');
|
||||||
|
} else {
|
||||||
|
setErrMsg('Registration Failed');
|
||||||
|
}
|
||||||
|
errRef.current.focus();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{success ? (
|
||||||
|
<section>
|
||||||
|
<h1>Success!</h1>
|
||||||
|
<p>
|
||||||
|
<a href="#">Sign In</a>
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
) : (
|
||||||
|
<section>
|
||||||
|
<p ref={errRef} className={errMsg ? 'errmsg' : 'offscreen'} aria-live="assertive">{errMsg}</p>
|
||||||
|
<h1>Register</h1>
|
||||||
|
<form onSubmit={handleSubmit}>
|
||||||
|
<label htmlFor="username">
|
||||||
|
Username:
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
id="username"
|
||||||
|
ref={userRef}
|
||||||
|
autoComplete="off"
|
||||||
|
onChange={(e) => setUser(e.target.value)}
|
||||||
|
value={user}
|
||||||
|
required
|
||||||
|
aria-invalid={validName ? 'false' : 'true'}
|
||||||
|
aria-describedby="uidnote"
|
||||||
|
onFocus={() => setUserFocus(true)}
|
||||||
|
onBlur={() => setUserFocus(false)}
|
||||||
|
/>
|
||||||
|
<p id="uidnote" className={userFocus && user && !validName ? 'instructions' : 'offscreen'}>
|
||||||
|
4 to 24 characters.<br />
|
||||||
|
Must begin with a letter.<br />
|
||||||
|
Letters, numbers, underscores, hyphens allowed.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<label htmlFor="password">
|
||||||
|
Password:
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
type="password"
|
||||||
|
id="password"
|
||||||
|
onChange={(e) => setPwd(e.target.value)}
|
||||||
|
value={pwd}
|
||||||
|
required
|
||||||
|
aria-invalid={validPwd ? 'false' : 'true'}
|
||||||
|
aria-describedby="pwdnote"
|
||||||
|
onFocus={() => setPwdFocus(true)}
|
||||||
|
onBlur={() => setPwdFocus(false)}
|
||||||
|
/>
|
||||||
|
<p id="pwdnote" className={pwdFocus && !validPwd ? 'instructions' : 'offscreen'}>
|
||||||
|
Allowed special characters: <span aria-label="exclamation mark">!</span>
|
||||||
|
<span aria-label="at symbol">@</span> <span aria-label="hashtag">#
|
||||||
|
</span> <span aria-label="dollar sign">$</span> <span aria-label="percent">%</span>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<label htmlFor="confirm_pwd">
|
||||||
|
Confirm Password:
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
type="password"
|
||||||
|
id="confirm_pwd"
|
||||||
|
onChange={(e) => setMatchPwd(e.target.value)}
|
||||||
|
value={matchPwd}
|
||||||
|
required
|
||||||
|
aria-invalid={validMatch ? 'false' : 'true'}
|
||||||
|
aria-describedby="confirmnote"
|
||||||
|
onFocus={() => setMatchFocus(true)}
|
||||||
|
onBlur={() => setMatchFocus(false)}
|
||||||
|
/>
|
||||||
|
<p id="confirmnote" className={matchFocus && !validMatch ? 'instructions' : 'offscreen'}>
|
||||||
|
Must match the first password input field.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<button disabled={!!(!validName || !validPwd
|
||||||
|
|| !validMatch)}>Sign Up</button>
|
||||||
|
</form>
|
||||||
|
<p>
|
||||||
|
Already registered?<br />
|
||||||
|
<span className="line">
|
||||||
|
<a href="#">Sign In</a>
|
||||||
|
</span>
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Register;
|
5
laba5/src/components/api/axios.js
Normal file
5
laba5/src/components/api/axios.js
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
import axios from 'axios';
|
||||||
|
|
||||||
|
export default axios.create({
|
||||||
|
baseURL: 'http://localhost:3500',
|
||||||
|
});
|
@ -3,53 +3,10 @@
|
|||||||
.cart{
|
.cart{
|
||||||
font-family: "Montserrat Alternates";
|
font-family: "Montserrat Alternates";
|
||||||
}
|
}
|
||||||
.cart .container-products {
|
|
||||||
background-color: rgba(210, 202, 188, 0.64);
|
|
||||||
position: relative;
|
|
||||||
margin-bottom: 3%;
|
|
||||||
border-radius: 10px;
|
|
||||||
}
|
|
||||||
.container-products .title-product,
|
|
||||||
.container-products .price,
|
|
||||||
.container-products .articuL,
|
|
||||||
.container-products a {
|
|
||||||
margin-left: 30%;
|
|
||||||
position: absolute;
|
|
||||||
padding: 3%;
|
|
||||||
}
|
|
||||||
.container-products .title-product {
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
}
|
|
||||||
.container-products .price {
|
|
||||||
top: 0;
|
|
||||||
right: 0;
|
|
||||||
}
|
|
||||||
.container-products .title-product,
|
|
||||||
.container-products .price {
|
|
||||||
font-weight: 700;
|
|
||||||
}
|
|
||||||
.container-products .articul {
|
|
||||||
bottom: 0;
|
|
||||||
left: 0;
|
|
||||||
padding-bottom: 3%;
|
|
||||||
}
|
|
||||||
.container-products a {
|
|
||||||
width: 20%;
|
|
||||||
bottom: 0;
|
|
||||||
right: 0;
|
|
||||||
margin-bottom: 3%;
|
|
||||||
}
|
|
||||||
.cart .card{
|
.cart .card{
|
||||||
background-color: rgba(191, 180, 161, 1);
|
|
||||||
margin-bottom: 30px;
|
margin-bottom: 30px;
|
||||||
}
|
border-width: 1px;
|
||||||
.cart u {
|
border-color: #533908;
|
||||||
padding-left: 4%;
|
|
||||||
text-align: left;
|
|
||||||
margin-left: 3%;
|
|
||||||
font-weight: 500;
|
|
||||||
padding-bottom: 10%;
|
|
||||||
}
|
}
|
||||||
.cart .btn{
|
.cart .btn{
|
||||||
font-weight: 100;
|
font-weight: 100;
|
||||||
@ -59,44 +16,6 @@
|
|||||||
background-color: #533908;
|
background-color: #533908;
|
||||||
border: #533908 3px solid;
|
border: #533908 3px solid;
|
||||||
}
|
}
|
||||||
.cart .card-text{
|
|
||||||
font-weight: 500;
|
|
||||||
padding: 5px;
|
|
||||||
font-size: 18px;
|
|
||||||
text-align: center;
|
|
||||||
color:#533908;
|
|
||||||
}
|
|
||||||
.cart .card-title{
|
|
||||||
font-weight: 600;
|
|
||||||
font-size: 23px;
|
|
||||||
color:#533908;
|
|
||||||
padding: 8px;
|
|
||||||
margin-bottom: 5%;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
.cart .price-text{
|
|
||||||
font-weight: 300;
|
|
||||||
padding: 5px;
|
|
||||||
font-size: 18px;
|
|
||||||
text-align: center;
|
|
||||||
color:#533908;
|
|
||||||
}
|
|
||||||
.cart .price-count{
|
|
||||||
font-weight: 500;
|
|
||||||
padding: 5px;
|
|
||||||
text-align: center;
|
|
||||||
color:#533908;
|
|
||||||
}
|
|
||||||
.cart .imageOfProduct{
|
|
||||||
padding: 10px;
|
|
||||||
width: 30%;
|
|
||||||
border-radius: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.cart-image {
|
.cart-image {
|
||||||
width: 12em;
|
width: 12em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.cart-item {
|
|
||||||
height: auto;
|
|
||||||
}
|
|
@ -22,7 +22,7 @@ const LinesItemForm = ({ item, handleChange }) => {
|
|||||||
type='number' min='1000.0' step='0.50' required />
|
type='number' min='1000.0' step='0.50' required />
|
||||||
<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='color' label='Цвет' value={item.color} onChange={handleChange} required />
|
<Input name='color' label='Цвет' value={item.color} onChange={handleChange} type='color' required />
|
||||||
<Input name='size' label='Размер' value={item.size} onChange={handleChange} required />
|
<Input name='size' label='Размер' value={item.size} onChange={handleChange} required />
|
||||||
<Input name='image' label='Изображение' onChange={handleChange}
|
<Input name='image' label='Изображение' onChange={handleChange}
|
||||||
type='file' accept='image/*' />
|
type='file' accept='image/*' />
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
/* eslint-disable no-undef */
|
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import toast from 'react-hot-toast';
|
import toast from 'react-hot-toast';
|
||||||
import getBase64FromFile from '../../utils/Base64';
|
import getBase64FromFile from '../../utils/Base64';
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import { Button, ButtonGroup } from 'react-bootstrap';
|
import { Button } from 'react-bootstrap';
|
||||||
import { useNavigate } from 'react-router-dom';
|
|
||||||
import useCart from '../../cart/CartHook';
|
import useCart from '../../cart/CartHook';
|
||||||
import Select from '../../input/Select.jsx';
|
import Select from '../../input/Select.jsx';
|
||||||
import ModalConfirm from '../../modal/ModalConfirm.jsx';
|
import ModalConfirm from '../../modal/ModalConfirm.jsx';
|
||||||
@ -34,22 +33,14 @@ const Lines = () => {
|
|||||||
handleFormClose,
|
handleFormClose,
|
||||||
} = useLinesFormModal(handleLinesChange);
|
} = useLinesFormModal(handleLinesChange);
|
||||||
|
|
||||||
const navigate = useNavigate();
|
|
||||||
|
|
||||||
const showEditPage = (id) => {
|
|
||||||
navigate(`/page-edit/${id}`);
|
|
||||||
};
|
|
||||||
|
|
||||||
const { addToCart } = useCart();
|
const { addToCart } = useCart();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<ButtonGroup>
|
<Button variant='secondary' className='mt-4 mx-4' onClick={() => showFormModal()}>
|
||||||
<Button variant='secondary' onClick={() => showFormModal()}>
|
Добавить товар
|
||||||
Добавить товар (диалог)
|
|
||||||
</Button>
|
</Button>
|
||||||
</ButtonGroup>
|
<Select className='mt-3 mx-4' values={types} label='Фильтр по товарам'
|
||||||
<Select className='mt-2' values={types} label='Фильтр по товарам'
|
|
||||||
value={currentFilter} onChange={handleFilterChange} />
|
value={currentFilter} onChange={handleFilterChange} />
|
||||||
<LinesTable>
|
<LinesTable>
|
||||||
{
|
{
|
||||||
@ -59,7 +50,6 @@ const Lines = () => {
|
|||||||
onAddCart={() => addToCart(line)}
|
onAddCart={() => addToCart(line)}
|
||||||
onDelete={() => showDeleteModal(line.id)}
|
onDelete={() => showDeleteModal(line.id)}
|
||||||
onEdit={() => showFormModal(line.id)}
|
onEdit={() => showFormModal(line.id)}
|
||||||
onEditInPage={() => showEditPage(line.id)}
|
|
||||||
/>)
|
/>)
|
||||||
}
|
}
|
||||||
</LinesTable>
|
</LinesTable>
|
||||||
|
@ -2,19 +2,25 @@ import PropTypes from 'prop-types';
|
|||||||
import { Row } from 'react-bootstrap';
|
import { Row } from 'react-bootstrap';
|
||||||
import CardOfRoom from '../../Card.jsx';
|
import CardOfRoom from '../../Card.jsx';
|
||||||
import useLines from '../hooks/LinesHook';
|
import useLines from '../hooks/LinesHook';
|
||||||
|
import Select from '../../input/Select.jsx';
|
||||||
|
import useTypeFilter from '../hooks/LinesFilterHook';
|
||||||
|
|
||||||
const LinesTableRow = () => {
|
const LinesTableRow = () => {
|
||||||
const { lines } = useLines();
|
const { types, currentFilter, handleFilterChange } = useTypeFilter();
|
||||||
|
const { lines } = useLines(currentFilter);
|
||||||
|
|
||||||
function allCards() {
|
function allCards() {
|
||||||
return lines.map((card) =>
|
return lines.map((card) =>
|
||||||
<CardOfRoom key={card.id}
|
<CardOfRoom key={card.id}
|
||||||
product={card.product}
|
product={card.product}
|
||||||
|
size = {card.size}
|
||||||
price={card.price} image={card.image} card={card} />);
|
price={card.price} image={card.image} card={card} />);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
<Select className='col-2 mt-0 mb-4 mx-4 ms-auto' values={types} label='Фильтр по товарам'
|
||||||
|
value={currentFilter} onChange={handleFilterChange} />
|
||||||
<Row xs={1} md={2} className="g-4 justify-content-center">
|
<Row xs={1} md={2} className="g-4 justify-content-center">
|
||||||
{allCards()}
|
{allCards()}
|
||||||
</Row>
|
</Row>
|
||||||
|
@ -8,9 +8,8 @@ import CartPage from './pages/CartPage.jsx';
|
|||||||
import ErrorPage from './pages/ErrorPage.jsx';
|
import ErrorPage from './pages/ErrorPage.jsx';
|
||||||
import Page1 from './pages/Page1.jsx';
|
import Page1 from './pages/Page1.jsx';
|
||||||
import Page2 from './pages/Page2.jsx';
|
import Page2 from './pages/Page2.jsx';
|
||||||
|
import Page3 from './pages/Page3.jsx';
|
||||||
import Page4 from './pages/Page4.jsx';
|
import Page4 from './pages/Page4.jsx';
|
||||||
import Page5 from './pages/Page5.jsx';
|
|
||||||
import Page6 from './pages/Page6.jsx';
|
|
||||||
import PageEdit from './pages/PageEdit.jsx';
|
import PageEdit from './pages/PageEdit.jsx';
|
||||||
|
|
||||||
const routes = [
|
const routes = [
|
||||||
@ -24,18 +23,14 @@ const routes = [
|
|||||||
element: <Page2 />, // Страница каталога
|
element: <Page2 />, // Страница каталога
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/page4',
|
path: '/page3',
|
||||||
element: <Page4 />,
|
element: <Page3 />,
|
||||||
title: 'Аккаунт',
|
title: 'Аккаунт',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/page5',
|
path: '/page4',
|
||||||
element: <Page5 />,
|
element: <Page4 />,
|
||||||
title: 'Табличка', // Таблица с товарами
|
title: 'Таблица товаров', // Таблица с товарами
|
||||||
},
|
|
||||||
{
|
|
||||||
path: '/page6',
|
|
||||||
element: <Page6 />, // Страница товара
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/page-edit/:id?',
|
path: '/page-edit/:id?',
|
||||||
|
59
laba5/src/pages/Page3.jsx
Normal file
59
laba5/src/pages/Page3.jsx
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
import { Link } from 'react-router-dom';
|
||||||
|
import {
|
||||||
|
Container, Col, Row, Form, Button,
|
||||||
|
} from 'react-bootstrap';
|
||||||
|
// import Register from '../components/Register';
|
||||||
|
import './Page3.css';
|
||||||
|
|
||||||
|
const Page3 = () => {
|
||||||
|
return (
|
||||||
|
// <Register />
|
||||||
|
<>
|
||||||
|
<div className="accountPage">
|
||||||
|
<Container>
|
||||||
|
<Row>
|
||||||
|
<Col className="mx-auto">
|
||||||
|
<Form.Text className='text-center'>
|
||||||
|
<h1>АВТОРИЗАЦИЯ</h1>
|
||||||
|
</Form.Text>
|
||||||
|
<Form method="post" >
|
||||||
|
<Form.Group>
|
||||||
|
<Form.Label htmlFor="login">Логин</Form.Label>
|
||||||
|
<Form.Control type="text" className="form-control"id="exampleInputLogin" />
|
||||||
|
</Form.Group>
|
||||||
|
<Form.Group>
|
||||||
|
<Form.Label htmlFor="password">Пароль</Form.Label>
|
||||||
|
<Form.Control type="password" className="form-control"
|
||||||
|
id="exampleInputPassword" />
|
||||||
|
</Form.Group>
|
||||||
|
<Button className='my-3' type="submit" variant="secondary"
|
||||||
|
as={Link} to="/page4">Войти</Button>
|
||||||
|
</Form>
|
||||||
|
</Col>
|
||||||
|
<Col className="mx-auto">
|
||||||
|
<Form.Text className='text-center'>
|
||||||
|
<h1>РЕГИСТРАЦИЯ</h1>
|
||||||
|
</Form.Text>
|
||||||
|
<Form method="post" >
|
||||||
|
<Form.Group>
|
||||||
|
<Form.Label htmlFor="login">Логин</Form.Label>
|
||||||
|
<Form.Control type="text" className="form-control"
|
||||||
|
id="exampleInputLogin" />
|
||||||
|
</Form.Group>
|
||||||
|
<Form.Group>
|
||||||
|
<Form.Label htmlFor="password">Пароль</Form.Label>
|
||||||
|
<Form.Control type="password" className="form-control"
|
||||||
|
id="exampleInputPassword" />
|
||||||
|
</Form.Group>
|
||||||
|
<Button className='my-3' type="submit" variant="outline-secondary">
|
||||||
|
Зарегистрироваться</Button>
|
||||||
|
</Form>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
</Container>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Page3;
|
@ -1,55 +1,8 @@
|
|||||||
import { Link } from 'react-router-dom';
|
import Lines from '../components/lines/table/Lines.jsx';
|
||||||
import {
|
|
||||||
Container, Col, Row, Form, Button,
|
|
||||||
} from 'react-bootstrap';
|
|
||||||
import './Page4.css';
|
|
||||||
|
|
||||||
const Page4 = () => {
|
const Page4 = () => {
|
||||||
return (
|
return (
|
||||||
<>
|
<Lines />
|
||||||
<div className="accountPage">
|
|
||||||
<Container>
|
|
||||||
<Row>
|
|
||||||
<Col className="mx-auto">
|
|
||||||
<Form.Text className='text-center'>
|
|
||||||
<h1>АВТОРИЗАЦИЯ</h1>
|
|
||||||
</Form.Text>
|
|
||||||
<Form method="post">
|
|
||||||
<Form.Group>
|
|
||||||
<Form.Label htmlFor="email">E-mail</Form.Label>
|
|
||||||
<Form.Control type="email" name="email" required />
|
|
||||||
</Form.Group>
|
|
||||||
<Form.Group>
|
|
||||||
<Form.Label htmlFor="password">Пароль</Form.Label>
|
|
||||||
<Form.Control type="password" name="password" required />
|
|
||||||
</Form.Group>
|
|
||||||
<Button className='my-3' type="submit" variant="secondary" as={Link} to="/page5">Войти</Button>
|
|
||||||
</Form>
|
|
||||||
</Col>
|
|
||||||
<Col className="mx-auto">
|
|
||||||
<Form.Text className='text-center'>
|
|
||||||
<h1>РЕГИСТРАЦИЯ</h1>
|
|
||||||
</Form.Text>
|
|
||||||
<Form method="post">
|
|
||||||
<Form.Group>
|
|
||||||
<Form.Label htmlFor="email">E-mail</Form.Label>
|
|
||||||
<Form.Control type="email" name="email" required />
|
|
||||||
</Form.Group>
|
|
||||||
<Form.Group>
|
|
||||||
<Form.Label htmlFor="password">Пароль</Form.Label>
|
|
||||||
<Form.Control type="password" name="password" required />
|
|
||||||
</Form.Group>
|
|
||||||
<Form.Group>
|
|
||||||
<Form.Label htmlFor="password">Повторите пароль</Form.Label>
|
|
||||||
<Form.Control type="password" name="password" required />
|
|
||||||
</Form.Group>
|
|
||||||
<Button className='my-3' type="submit" variant="outline-secondary">Зарегистрироваться</Button>
|
|
||||||
</Form>
|
|
||||||
</Col>
|
|
||||||
</Row>
|
|
||||||
</Container>
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,9 +0,0 @@
|
|||||||
import Lines from '../components/lines/table/Lines.jsx';
|
|
||||||
|
|
||||||
const Page5 = () => {
|
|
||||||
return (
|
|
||||||
<Lines />
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default Page5;
|
|
Loading…
Reference in New Issue
Block a user