Лаба 4
26
4_laba_IP_project/.eslintrc.cjs
Normal file
@ -0,0 +1,26 @@
|
||||
module.exports = {
|
||||
root: true,
|
||||
env: {browser: true, es2020: true},
|
||||
extends: [
|
||||
'airbnb-base',
|
||||
'plugin:react/recommended',
|
||||
'plugin:react/jsx-runtime',
|
||||
'plugin:react-hooks/recommended',
|
||||
],
|
||||
ignorePatterns: ['dist', '.eslintrc.cjs'],
|
||||
parserOptions: {ecmaVersion: 12, sourceType: 'module'},
|
||||
settings: {react: {version: '18.2'}},
|
||||
plugins: ['react-refresh'],
|
||||
rules: {
|
||||
'react-refresh/only-export-components': [
|
||||
'warn',
|
||||
{allowConstantExport: true},
|
||||
],
|
||||
'indent': 'off',
|
||||
'no-console': 'off',
|
||||
'arrow-body-style': 'off',
|
||||
'implicit-arrow-linebreak': 'off',
|
||||
'linebreak-style': 'off',
|
||||
'import/no-extraneous-dependencies': 'off'
|
||||
},
|
||||
}
|
24
4_laba_IP_project/.gitignore
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
pnpm-debug.log*
|
||||
lerna-debug.log*
|
||||
|
||||
node_modules
|
||||
dist
|
||||
dist-ssr
|
||||
*.local
|
||||
|
||||
# Editor directories and files
|
||||
.vscode/*
|
||||
!.vscode/extensions.json
|
||||
.idea
|
||||
.DS_Store
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.sw?
|
10
4_laba_IP_project/README.md
Normal file
@ -0,0 +1,10 @@
|
||||
# React + Vite
|
||||
|
||||
This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.
|
||||
|
||||
Currently, two official plugins are available:
|
||||
|
||||
- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md)
|
||||
uses [Babel](https://babeljs.io/) for Fast Refresh
|
||||
- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react-swc) uses [SWC](https://swc.rs/) for Fast
|
||||
Refresh
|
13
4_laba_IP_project/index.html
Normal file
@ -0,0 +1,13 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8"/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
||||
<title>Ульяновский Кондитер</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root" class="h-100 d-flex flex-column"></div>
|
||||
<script type="module" src="/src/main.jsx"></script>
|
||||
</body>
|
||||
</html>
|
4344
4_laba_IP_project/package-lock.json
generated
Normal file
32
4_laba_IP_project/package.json
Normal file
@ -0,0 +1,32 @@
|
||||
{
|
||||
"name": "lec4",
|
||||
"private": true,
|
||||
"version": "0.0.0",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "vite build",
|
||||
"lint": "eslint . --ext js,jsx --report-unused-disable-directives --max-warnings 0",
|
||||
"preview": "vite preview"
|
||||
},
|
||||
"dependencies": {
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-router-dom": "^6.18.0",
|
||||
"bootstrap": "^5.3.2",
|
||||
"react-bootstrap": "^2.9.1",
|
||||
"react-bootstrap-icons": "^1.10.3",
|
||||
"prop-types": "^15.8.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/react": "^18.2.15",
|
||||
"@types/react-dom": "^18.2.7",
|
||||
"@vitejs/plugin-react": "^4.0.3",
|
||||
"eslint": "^8.45.0",
|
||||
"eslint-config-airbnb-base": "^15.0.0",
|
||||
"eslint-plugin-react": "^7.32.2",
|
||||
"eslint-plugin-react-hooks": "^4.6.0",
|
||||
"eslint-plugin-react-refresh": "^0.4.3",
|
||||
"vite": "^4.4.5"
|
||||
}
|
||||
}
|
18
4_laba_IP_project/public/vite.svg
Normal file
@ -0,0 +1,18 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img"
|
||||
class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257">
|
||||
<defs>
|
||||
<linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%">
|
||||
<stop offset="0%" stop-color="#41D1FF"></stop>
|
||||
<stop offset="100%" stop-color="#BD34FE"></stop>
|
||||
</linearGradient>
|
||||
<linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%">
|
||||
<stop offset="0%" stop-color="#FFEA83"></stop>
|
||||
<stop offset="8.333%" stop-color="#FFDD35"></stop>
|
||||
<stop offset="100%" stop-color="#FFA800"></stop>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<path fill="url(#IconifyId1813088fe1fbc01fb466)"
|
||||
d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path>
|
||||
<path fill="url(#IconifyId1813088fe1fbc01fb467)"
|
||||
d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path>
|
||||
</svg>
|
After Width: | Height: | Size: 1.6 KiB |
44
4_laba_IP_project/src/App.css
Normal file
@ -0,0 +1,44 @@
|
||||
/*#root {*/
|
||||
/* max-width: 1280px;*/
|
||||
/* margin: 0 auto;*/
|
||||
/* padding: 2rem;*/
|
||||
/* text-align: center;*/
|
||||
/*}*/
|
||||
|
||||
.logo {
|
||||
height: 6em;
|
||||
padding: 1.5em;
|
||||
will-change: filter;
|
||||
transition: filter 300ms;
|
||||
}
|
||||
|
||||
.logo:hover {
|
||||
filter: drop-shadow(0 0 2em #646cffaa);
|
||||
}
|
||||
|
||||
.logo.react:hover {
|
||||
filter: drop-shadow(0 0 2em #61dafbaa);
|
||||
}
|
||||
|
||||
@keyframes logo-spin {
|
||||
from {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
to {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: no-preference) {
|
||||
a:nth-of-type(2) .logo {
|
||||
animation: logo-spin infinite 20s linear;
|
||||
}
|
||||
}
|
||||
|
||||
.card {
|
||||
padding: 2em;
|
||||
}
|
||||
|
||||
.read-the-docs {
|
||||
color: #888;
|
||||
}
|
28
4_laba_IP_project/src/App.jsx
Normal file
@ -0,0 +1,28 @@
|
||||
import {useState} from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import {Container} from 'react-bootstrap';
|
||||
import {Outlet} from 'react-router-dom';
|
||||
import './App.css';
|
||||
import LeftBar from './components/LeftBar/LeftBar.jsx';
|
||||
import Header from './components/Header/Header.jsx';
|
||||
|
||||
const App = ({routes}) => {
|
||||
const [show, setShow] = useState(false);
|
||||
const handleClose = () => setShow(false);
|
||||
const toggleShow = () => {
|
||||
setShow((s) => !s);
|
||||
};
|
||||
return (
|
||||
<>
|
||||
<Container className='p-2' as="main" fluid>
|
||||
<Outlet/>
|
||||
</Container>
|
||||
<Header toggleShow={toggleShow}/>
|
||||
<LeftBar show={show} handleClose={handleClose} routes={routes}/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
App.propTypes = {
|
||||
routes: PropTypes.array,
|
||||
};
|
||||
export default App;
|
BIN
4_laba_IP_project/src/assets/acc_icon.png
Normal file
After Width: | Height: | Size: 6.3 KiB |
BIN
4_laba_IP_project/src/assets/arrow_icon.png
Normal file
After Width: | Height: | Size: 2.7 KiB |
BIN
4_laba_IP_project/src/assets/back_arrow_icon.png
Normal file
After Width: | Height: | Size: 2.8 KiB |
BIN
4_laba_IP_project/src/assets/logo.png
Normal file
After Width: | Height: | Size: 37 KiB |
BIN
4_laba_IP_project/src/assets/object_1.png
Normal file
After Width: | Height: | Size: 209 KiB |
BIN
4_laba_IP_project/src/assets/object_2.png
Normal file
After Width: | Height: | Size: 163 KiB |
BIN
4_laba_IP_project/src/assets/object_3.png
Normal file
After Width: | Height: | Size: 202 KiB |
BIN
4_laba_IP_project/src/assets/open_sidebar.png
Normal file
After Width: | Height: | Size: 3.0 KiB |
BIN
4_laba_IP_project/src/assets/search_icon.png
Normal file
After Width: | Height: | Size: 14 KiB |
BIN
4_laba_IP_project/src/assets/shop_icon.png
Normal file
After Width: | Height: | Size: 13 KiB |
BIN
4_laba_IP_project/src/assets/vk_icon.png
Normal file
After Width: | Height: | Size: 18 KiB |
BIN
4_laba_IP_project/src/assets/whatsapp_icon.png
Normal file
After Width: | Height: | Size: 20 KiB |
6
4_laba_IP_project/src/components/BackArrow/BackArrow.css
Normal file
@ -0,0 +1,6 @@
|
||||
.back_arrow { /*стрелка назад*/
|
||||
height: 4vh;
|
||||
position: absolute;
|
||||
top: 7vh;
|
||||
left: 3vw;
|
||||
}
|
15
4_laba_IP_project/src/components/BackArrow/BackArrow.jsx
Normal file
@ -0,0 +1,15 @@
|
||||
import './BackArrow.css';
|
||||
import backarrow from '../../assets/back_arrow_icon.png';
|
||||
|
||||
const BackArrow = () => {
|
||||
const goBack = () => {
|
||||
window.history.back();
|
||||
};
|
||||
return (
|
||||
<div id="BackArrow" onClick={goBack}>
|
||||
<img className="back_arrow " src={backarrow} alt="back_arrow"/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default BackArrow;
|
33
4_laba_IP_project/src/components/Header/Header.css
Normal file
@ -0,0 +1,33 @@
|
||||
.top_pannel { /*отступ слева в top_pannel*/
|
||||
margin-left: 20vw;
|
||||
}
|
||||
|
||||
.icon-container { /* сдвиг top_pannel*/
|
||||
margin-right: 5vw;
|
||||
}
|
||||
|
||||
.text_containter { /* сдвиг top_pannel*/
|
||||
margin-left: 5vw;
|
||||
}
|
||||
|
||||
header nav a:hover { /* подчеркивание текста top_pannel*/
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.arrow_and_cities { /*чтобы все было на одном уровне, стрелка и город top_pannel*/
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.btn_open {
|
||||
background-image: url('../../assets/open_sidebar.png');
|
||||
background-color: transparent;
|
||||
background-size: cover;
|
||||
position: fixed;
|
||||
margin-top: 0vh;
|
||||
margin-left: 3vh;
|
||||
border: none;
|
||||
height: 4vh;
|
||||
width: 3vw;
|
||||
}
|
||||
|
51
4_laba_IP_project/src/components/Header/Header.jsx
Normal file
@ -0,0 +1,51 @@
|
||||
import {Link} from 'react-router-dom';
|
||||
import Button from 'react-bootstrap/Button';
|
||||
import './Header.css';
|
||||
import arrowicon from '../../assets/arrow_icon.png';
|
||||
import accicon from '../../assets/acc_icon.png';
|
||||
import shopicon from '../../assets/shop_icon.png';
|
||||
import searchicon from '../../assets/search_icon.png';
|
||||
|
||||
const header = ({toggleShow, name}) => {
|
||||
return (
|
||||
<header>
|
||||
<nav className="navbar navbar-expand-md navbar-white fixed-top">
|
||||
<div className="btn_open_sidebar">
|
||||
<Button variant="primary" onClick={() => toggleShow()} className="btn_open me-2">
|
||||
{name}
|
||||
</Button>
|
||||
</div>
|
||||
<div className="container-fluid top_pannel">
|
||||
<div className="navbar-collapse collapse justify-content-start" id="navbarNav">
|
||||
|
||||
<div className="navbar-nav text_containter">
|
||||
<div className="arrow_and_cities">
|
||||
<img className="icon_top" src={arrowicon} alt="arrow_icon"/>
|
||||
<a className="nav-link"
|
||||
style={{color: 'black'}}>Ульяновск</a> {/* Используем объект стилей для атрибута style */}
|
||||
</div>
|
||||
<a className="nav-link adress" style={{marginLeft: '40px', color: 'black'}}>Адреса
|
||||
магазинов</a> {/* Используем объект стилей для атрибута style */}
|
||||
</div>
|
||||
</div>
|
||||
<div className="navbar-collapse collapse justify-content-end"
|
||||
id="navbarNav1"> {/* Перемещаем закрывающий тег внутрь предыдущего тега */}
|
||||
<div className="navbar-nav icon-container">
|
||||
<Link to="/Page2">
|
||||
<img className="icon_top" src={accicon} alt="acc_icon"/>
|
||||
</Link>
|
||||
<Link to="/Page3">
|
||||
<img className="icon_top" src={shopicon} alt="shop_icon"/>
|
||||
</Link>
|
||||
<Link to="/Page2">
|
||||
<img className="icon_top" src={searchicon} alt="search_icon"/>
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
</header>
|
||||
);
|
||||
};
|
||||
|
||||
export default header;
|
51
4_laba_IP_project/src/components/LeftBar/LeftBar.css
Normal file
@ -0,0 +1,51 @@
|
||||
.logo_sidebar { /*размеры лого sidebar*/
|
||||
width: 17vh;
|
||||
}
|
||||
|
||||
.list_font { /*текст sidebar*/
|
||||
line-height: 3;
|
||||
font-size: 2.4vh;
|
||||
color: #5d5d5d;
|
||||
}
|
||||
|
||||
.offcanvas-start.show { /*ширина sidebar*/
|
||||
width: 25vw;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.offcanvas-header { /*настройки header sidebar*/
|
||||
margin-top: 8vh;
|
||||
height: 15%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
margin-bottom: auto;
|
||||
}
|
||||
|
||||
.offcanvas-body { /*настройки body sidebar*/
|
||||
position: relative;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
margin-top: auto;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.social_network img { /*иконки соц сетей*/
|
||||
margin-top: 1vh;
|
||||
height: 3.5vh;
|
||||
margin-right: 1vw;
|
||||
}
|
||||
|
||||
.list_sidebar { /* список sidebar*/
|
||||
top: 10vh;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
|
||||
.btn_open_sidebar {
|
||||
/*position: absolute;*/
|
||||
top: 10px;
|
||||
left: 10px;
|
||||
z-index: 1000;
|
||||
background-color: #a60000;
|
||||
}
|
88
4_laba_IP_project/src/components/LeftBar/LeftBar.jsx
Normal file
@ -0,0 +1,88 @@
|
||||
import {Link} from 'react-router-dom';
|
||||
import Offcanvas from 'react-bootstrap/Offcanvas';
|
||||
import PropTypes from 'prop-types';
|
||||
import './LeftBar.css';
|
||||
import logo from '../../assets/logo.png';
|
||||
import Whatsappicon from '../../assets/whatsapp_icon.png';
|
||||
import vkicon from '../../assets/vk_icon.png';
|
||||
|
||||
const options = [
|
||||
{
|
||||
name: 'Enable body scrolling',
|
||||
scroll: true,
|
||||
backdrop: false,
|
||||
},
|
||||
];
|
||||
|
||||
function OffCanvasExample({
|
||||
name,
|
||||
show,
|
||||
handleClose,
|
||||
...props
|
||||
}) {
|
||||
return (
|
||||
<>
|
||||
<Offcanvas show={show} onHide={handleClose} {...props}>
|
||||
<Offcanvas.Header closeButton>
|
||||
<Link to="/Page1">
|
||||
<img className="logo_sidebar" src={logo} alt="shop_icon"/>
|
||||
</Link>
|
||||
</Offcanvas.Header>
|
||||
<Offcanvas.Body>
|
||||
|
||||
<div className="list_sidebar">
|
||||
<div className="list_font">
|
||||
<ul>
|
||||
<li>Клубника в шоколаде</li>
|
||||
<li>Бананы в шоколаде</li>
|
||||
<li>Конфеты</li>
|
||||
<li>Шоколад</li>
|
||||
<li>Медианты</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div className="bottom_sidebar">
|
||||
<div className='h0'>8 800 700 34 21
|
||||
<div className="take_order" style={{color: '#25e000'}}>Сделать заказ</div>
|
||||
</div>
|
||||
<div className="social_network">
|
||||
<img className="vk" src={vkicon} alt="vk"/>
|
||||
<img className="whatsapp" src={Whatsappicon} alt="whatsapp"/>
|
||||
</div>
|
||||
</div>
|
||||
</Offcanvas.Body>
|
||||
</Offcanvas>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
OffCanvasExample.propTypes = {
|
||||
name: PropTypes.string.isRequired,
|
||||
show: PropTypes.bool.isRequired,
|
||||
handleClose: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
function LeftBar({
|
||||
name,
|
||||
show,
|
||||
handleClose,
|
||||
}) {
|
||||
return (
|
||||
<>
|
||||
{options.map((props, idx) => (
|
||||
<OffCanvasExample
|
||||
name={name}
|
||||
show={show}
|
||||
handleClose={handleClose}
|
||||
key={idx} {...props} />
|
||||
))}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
LeftBar.propTypes = {
|
||||
name: PropTypes.string.isRequired,
|
||||
show: PropTypes.bool.isRequired,
|
||||
handleClose: PropTypes.func.isRequired,
|
||||
};
|
||||
export default LeftBar;
|
12
4_laba_IP_project/src/components/Navigation/Navigation.css
Normal file
@ -0,0 +1,12 @@
|
||||
.my-navbar {
|
||||
background-color: #a60000 !important;
|
||||
}
|
||||
|
||||
.my-navbar .link a:hover {
|
||||
text-decoration: underline !important;
|
||||
}
|
||||
|
||||
.my-navbar .logo {
|
||||
width: 26px;
|
||||
height: 26px;
|
||||
}
|
46
4_laba_IP_project/src/components/Navigation/Navigation.jsx
Normal file
@ -0,0 +1,46 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import {Container, Nav, Navbar} from 'react-bootstrap';
|
||||
import {Cart2} from 'react-bootstrap-icons';
|
||||
import {Link, useLocation} from 'react-router-dom';
|
||||
import './Navigation.css';
|
||||
|
||||
const Navigation = ({routes}) => {
|
||||
const location = useLocation();
|
||||
const indexPageLink = routes.filter((route) => route.index === false).shift();
|
||||
const show = routes.filter((route) => route.path === location.pathname).shift();
|
||||
const pages = routes.filter((route) => Object.prototype.hasOwnProperty.call(route, 'title'));
|
||||
|
||||
if (show.hideNavigation) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<header>
|
||||
<Navbar expand='md' bg='dark' data-bs-theme='dark' className='my-navbar'>
|
||||
<Container fluid>
|
||||
<Navbar.Brand as={Link} to={indexPageLink?.path ?? '/'}>
|
||||
<Cart2 className='d-inline-block align-top me-1 logo'/>
|
||||
My shop
|
||||
</Navbar.Brand>
|
||||
<Navbar.Toggle aria-controls='main-navbar' hic/>
|
||||
<Navbar.Collapse id='main-navbar'>
|
||||
<Nav className='me-auto link' activeKey={location.pathname}>
|
||||
{
|
||||
pages.map((page) =>
|
||||
<Nav.Link as={Link} key={page.path} eventKey={page.path} to={page.path ?? '/'}>
|
||||
{page.title}
|
||||
</Nav.Link>)
|
||||
}
|
||||
</Nav>
|
||||
</Navbar.Collapse>
|
||||
</Container>
|
||||
</Navbar>
|
||||
</header>
|
||||
);
|
||||
};
|
||||
|
||||
Navigation.propTypes = {
|
||||
routes: PropTypes.array,
|
||||
};
|
||||
|
||||
export default Navigation;
|
337
4_laba_IP_project/src/index.css
Normal file
@ -0,0 +1,337 @@
|
||||
|
||||
h1 { /*форматирование текста*/
|
||||
font-size: 4.5vw;
|
||||
font-family: "Segoe UI Light";
|
||||
font-weight: lighter;
|
||||
}
|
||||
|
||||
.main_pannel { /*основная панель main_pannel*/
|
||||
margin-left: 28vw;
|
||||
margin-top: 5vw;
|
||||
font-weight: lighter;
|
||||
max-width: 70%;
|
||||
}
|
||||
|
||||
.table { /*таблица */
|
||||
margin-top: 5vh;
|
||||
margin-left: 0vw;
|
||||
width: 60vw;
|
||||
}
|
||||
|
||||
body {
|
||||
overflow-x: hidden; /* скрыть горизонтальную прокрутку на всей странице */
|
||||
}
|
||||
|
||||
.objects { /*объекты в таблицe main_pannel*/
|
||||
width: 17vw;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.caption { /*описание к объекту в таблице main_pannel*/
|
||||
font-weight: lighter;
|
||||
text-align: center;
|
||||
font-size: 1.8vw;
|
||||
/*margin-top: 1vw;*/
|
||||
}
|
||||
|
||||
.caption_2 { /*описание к объекту в цене main_pannel*/
|
||||
font-weight: lighter;
|
||||
text-align: center;
|
||||
font-size: 2.8vw;
|
||||
color: #5d5d5d;
|
||||
/*margin-top: 0.3vw;*/
|
||||
}
|
||||
|
||||
.caption_count {
|
||||
font-weight: lighter;
|
||||
text-align: center;
|
||||
font-size: 1.2vw;
|
||||
margin-top: 0.5vw;
|
||||
|
||||
}
|
||||
|
||||
.icon_top { /*top_pannel*/
|
||||
margin-left: 2vw;
|
||||
width: 1.1vw;
|
||||
margin-top: 1vh;
|
||||
}
|
||||
|
||||
.nav-link { /* текста top_pannel*/
|
||||
font-size: calc(0.6vw + 0.6vh);
|
||||
margin-top: 1vh;
|
||||
}
|
||||
|
||||
header nav { /*заливка панели белым top_pannel*/
|
||||
background-color: #ffffff
|
||||
}
|
||||
|
||||
|
||||
header nav a:hover { /* подчеркивание текста top_pannel*/
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
|
||||
.bottom_sidebar { /*bottom sidebar*/
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-bottom: 0vh;
|
||||
flex-direction: column;
|
||||
margin-top: 60vh;
|
||||
}
|
||||
|
||||
|
||||
.h0 {
|
||||
font-size: 2vh;
|
||||
}
|
||||
|
||||
|
||||
.btn:hover {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.btn-close {
|
||||
position: absolute;
|
||||
top: 5vh;
|
||||
right: 5vh;
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
.width_input_mail { /*ширина панели для вводы почты*/
|
||||
width: 30%;
|
||||
}
|
||||
|
||||
|
||||
h2 {
|
||||
font-weight: lighter;
|
||||
font-size: 4vh;
|
||||
}
|
||||
|
||||
.h2_light {
|
||||
font-weight: lighter;
|
||||
font-size: 2vh;
|
||||
}
|
||||
|
||||
.login_pannel { /*2 страница, расположение объектов*/
|
||||
height: 90vh; /* на весь экран */
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
gap: 2vh; /* Добавляет отступы между элементами */
|
||||
}
|
||||
|
||||
.add_object {
|
||||
height: 90vh; /* на весь экран */
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
gap: 1vh; /* Добавляет отступы между элементами */
|
||||
}
|
||||
|
||||
.width_add_object {
|
||||
width: 25%;
|
||||
text-align: left;
|
||||
|
||||
}
|
||||
|
||||
.add_object-button {
|
||||
background-color: #118500;
|
||||
border-color: #118500;
|
||||
}
|
||||
|
||||
.view_object {
|
||||
margin-top: 6vh;
|
||||
margin-left: 0vw;
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr; /* Делит контейнер на две равные колонки */
|
||||
gap: 6vh; /* Добавляет промежуток между клеточками */
|
||||
}
|
||||
|
||||
.left-cell {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 6vh;
|
||||
margin-top: 6vh;
|
||||
/*margin-left: 15vw;*/
|
||||
}
|
||||
|
||||
.right-cell {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 6vh;
|
||||
margin-top: 6vh;
|
||||
}
|
||||
|
||||
.main_pannel2 {
|
||||
height: 100vh; /* на весь экран */
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
padding-left: 25vw;
|
||||
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-weight: lighter;
|
||||
font-size: 3em;
|
||||
}
|
||||
|
||||
.nav-pills .nav-link {
|
||||
color: rgba(166, 166, 166, 0.7);
|
||||
}
|
||||
|
||||
.nav-pills .nav-link:hover {
|
||||
color: black;
|
||||
}
|
||||
|
||||
.nav-pills .nav-link:focus,
|
||||
.nav-pills .nav-link.active,
|
||||
.nav-pills .nav-link:visited {
|
||||
background-color: rgba(0, 255, 49, 0.28);
|
||||
color: #000000;
|
||||
}
|
||||
|
||||
.objects_basket {
|
||||
height: 20vh;
|
||||
}
|
||||
|
||||
.caption_basket {
|
||||
text-align: left;
|
||||
font-weight: lighter;
|
||||
font-size: 2.5vh;
|
||||
background-color: #25e000;
|
||||
}
|
||||
|
||||
.caption_basket_price {
|
||||
font-weight: lighter;
|
||||
font-size: 4vh;
|
||||
background-color: red;
|
||||
}
|
||||
|
||||
.add_object-button:hover {
|
||||
background-color: rgba(0, 255, 49, 0.28);
|
||||
color: black;
|
||||
border-color: #118500;
|
||||
}
|
||||
|
||||
.col {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
#image-preview {
|
||||
width: 200px;
|
||||
margin-bottom: 1.4vh;
|
||||
}
|
||||
|
||||
.clear-float:nth-child(3n+1) {
|
||||
clear: left;
|
||||
}
|
||||
|
||||
.fa-pencil, .fa-trash {
|
||||
color: darkgray; /* Change to the desired color */
|
||||
text-decoration: none; /* Убрать подчеркивание у кнопок */
|
||||
}
|
||||
|
||||
.caption { /*описание к объекту в таблице main_pannel*/
|
||||
font-weight: lighter;
|
||||
text-align: center;
|
||||
font-size: 1.2vw;
|
||||
margin-top: 1vw;
|
||||
}
|
||||
|
||||
.caption_2 { /*описание к объекту в цене main_pannel*/
|
||||
font-weight: lighter;
|
||||
text-align: center;
|
||||
font-size: 2vw;
|
||||
color: #5d5d5d;
|
||||
margin-top: 0.3vw;
|
||||
}
|
||||
|
||||
.caption_link {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
@media (max-width: 1300px) {
|
||||
.main_pannel {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.table { /*таблица */
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
width: 60vw;
|
||||
}
|
||||
|
||||
h1 {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.offcanvas-start.show {
|
||||
border: 1px solid black;
|
||||
}
|
||||
|
||||
.btn-close {
|
||||
visibility: visible;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 800px) {
|
||||
.col-4 {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.objects { /*объекты в таблицe main_pannel*/
|
||||
width: 52vw;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.caption { /*описание к объекту в таблице main_pannel*/
|
||||
font-size: 3.2vw;
|
||||
}
|
||||
|
||||
.caption_2 { /*описание к объекту в цене main_pannel*/
|
||||
font-size: 4vw;
|
||||
}
|
||||
|
||||
.list_font { /*текст sidebar*/
|
||||
font-size: 2vh;
|
||||
|
||||
}
|
||||
|
||||
.offcanvas-start.show { /*ширина sidebar*/
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.top_pannel {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
.width_input_mail {
|
||||
width: 90%;
|
||||
}
|
||||
|
||||
.form-control {
|
||||
width: 90%;
|
||||
}
|
||||
|
||||
.width_add_object {
|
||||
width: 90%;
|
||||
}
|
||||
|
||||
.input-group { /*подгон ширины под отсльаные*/
|
||||
padding-right: 9vw;
|
||||
}
|
||||
|
||||
.view_object {
|
||||
padding-top: 1vh;
|
||||
}
|
||||
}
|
||||
|
14
4_laba_IP_project/src/jsconfig.json
Normal file
@ -0,0 +1,14 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "Node",
|
||||
"target": "ES2020",
|
||||
"jsx": "preserve",
|
||||
"strictNullChecks": true,
|
||||
"strictFunctionTypes": true
|
||||
},
|
||||
"exclude": [
|
||||
"node_modules",
|
||||
"**/node_modules/*"
|
||||
]
|
||||
}
|
51
4_laba_IP_project/src/main.jsx
Normal file
@ -0,0 +1,51 @@
|
||||
import 'bootstrap/dist/css/bootstrap.min.css';
|
||||
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom/client';
|
||||
import {createBrowserRouter, RouterProvider} from 'react-router-dom';
|
||||
import App from './App.jsx';
|
||||
import './index.css';
|
||||
import ErrorPage from './pages/ErrorPage.jsx';
|
||||
import Page1 from './pages/Page1.jsx';
|
||||
import Page2 from './pages/Page2.jsx';
|
||||
import Page3 from './pages/Page3.jsx';
|
||||
import Page4 from './pages/Page4.jsx';
|
||||
|
||||
const routes = [
|
||||
{
|
||||
index: true,
|
||||
path: '/Page1',
|
||||
element: <Page1/>,
|
||||
title: 'Главная страница',
|
||||
},
|
||||
{
|
||||
path: '/Page2',
|
||||
element: <Page2/>,
|
||||
title: 'Вторая страница',
|
||||
hideNavigation: true,
|
||||
},
|
||||
{
|
||||
path: '/Page3',
|
||||
element: <Page3/>,
|
||||
title: 'Третья страница',
|
||||
},
|
||||
{
|
||||
path: '/Page4',
|
||||
element: <Page4/>,
|
||||
title: 'Четвертая страница',
|
||||
},
|
||||
];
|
||||
|
||||
const router = createBrowserRouter([
|
||||
{
|
||||
path: '/',
|
||||
element: <App routes={routes}/>,
|
||||
children: routes,
|
||||
errorElement: <ErrorPage/>,
|
||||
},
|
||||
]);
|
||||
ReactDOM.createRoot(document.getElementById('root')).render(
|
||||
<React.StrictMode>
|
||||
<RouterProvider router={router}/>
|
||||
</React.StrictMode>,
|
||||
);
|
19
4_laba_IP_project/src/pages/ErrorPage.jsx
Normal file
@ -0,0 +1,19 @@
|
||||
import {Alert, Button, Container} from 'react-bootstrap';
|
||||
import {useNavigate} from 'react-router-dom';
|
||||
|
||||
const ErrorPage = () => {
|
||||
const navigate = useNavigate();
|
||||
|
||||
return (
|
||||
<Container fluid className="p-2 row justify-content-center">
|
||||
<Container className='col-md-6'>
|
||||
<Alert variant="danger">
|
||||
Страница не найдена
|
||||
</Alert>
|
||||
<Button className="w-25 mt-2" variant="primary" onClick={() => navigate(-1)}>Назад</Button>
|
||||
</Container>
|
||||
</Container>
|
||||
);
|
||||
};
|
||||
|
||||
export default ErrorPage;
|
78
4_laba_IP_project/src/pages/Page1.jsx
Normal file
@ -0,0 +1,78 @@
|
||||
import {Link} from 'react-router-dom';
|
||||
import Object1 from '../assets/object_1.png';
|
||||
import Object2 from '../assets/object_2.png';
|
||||
import Object3 from '../assets/object_3.png';
|
||||
|
||||
const Page1 = () => {
|
||||
return (
|
||||
<>
|
||||
<main className="container main_pannel">
|
||||
<h1>Клубника в шоколаде</h1>
|
||||
<div className="container table">
|
||||
<div className="row">
|
||||
<div className="col-4">
|
||||
<Link to="/Page4" className="caption_link">
|
||||
<img className="objects" src={Object1} alt="object"/>
|
||||
<div className="caption"> Букет из клубники 108. <br/>Набор из клубники в шоколаде в
|
||||
коробке
|
||||
</div>
|
||||
<div className="caption_2"> 400₽</div>
|
||||
</Link>
|
||||
</div>
|
||||
<div className="col-4">
|
||||
<Link to="/Page4" className="caption_link">
|
||||
<img className="objects" src={Object2} alt="object"/>
|
||||
<div className="caption"> Букет из клубники 108. <br/>Набор из клубники в шоколаде в
|
||||
коробке
|
||||
</div>
|
||||
<div className="caption_2"> 400₽</div>
|
||||
</Link>
|
||||
|
||||
</div>
|
||||
<div className="col-4">
|
||||
<Link to="/Page4" className="caption_link">
|
||||
<img className="objects" src={Object3} alt="object"/>
|
||||
<div className="caption"> Букет из клубники 108. <br/>Набор из клубники в шоколаде в
|
||||
коробке
|
||||
</div>
|
||||
<div className="caption_2"> 400₽</div>
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
<div className="row">
|
||||
<div className="col-4">
|
||||
<Link to="/Page4" className="caption_link">
|
||||
<img className="objects" src={Object1} alt="object"/>
|
||||
<div className="caption"> Букет из клубники 108. <br/>Набор из клубники в шоколаде в
|
||||
коробке
|
||||
</div>
|
||||
<div className="caption_2"> 400₽</div>
|
||||
</Link>
|
||||
</div>
|
||||
<div className="col-4">
|
||||
<Link to="/Page4" className="caption_link">
|
||||
<img className="objects" src={Object2} alt="object"/>
|
||||
<div className="caption"> Букет из клубники 108. <br/>Набор из клубники в шоколаде в
|
||||
коробке
|
||||
</div>
|
||||
<div className="caption_2"> 400₽</div>
|
||||
</Link>
|
||||
|
||||
</div>
|
||||
<div className="col-4">
|
||||
<Link to="/Page4" className="caption_link">
|
||||
<img className="objects" src={Object3} alt="object"/>
|
||||
<div className="caption"> Букет из клубники 108. <br/>Набор из клубники в шоколаде в
|
||||
коробке
|
||||
</div>
|
||||
<div className="caption_2"> 400₽</div>
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default Page1;
|
35
4_laba_IP_project/src/pages/Page2.jsx
Normal file
@ -0,0 +1,35 @@
|
||||
import {Link} from 'react-router-dom';
|
||||
import BackArrow from '../components/BackArrow/BackArrow.jsx';
|
||||
import logo from '../assets/logo.png';
|
||||
|
||||
const Page2 = () => {
|
||||
return (
|
||||
<>
|
||||
<BackArrow/>
|
||||
<>
|
||||
<main className="container-fluid p-2">
|
||||
<div className="text-center login_pannel">
|
||||
|
||||
<img className="logo_sidebar" src={logo} alt="logo"/>
|
||||
<h2>Войдите или зарегистрируйтесь</h2>
|
||||
<div className="input-group flex-nowrap width_input_mail">
|
||||
<span className="input-group-text" id="addon-wrapping">@</span>
|
||||
<input type="text" className="form-control" placeholder="Введите почту"
|
||||
aria-label="Username" aria-describedby="addon-wrapping"/>
|
||||
</div>
|
||||
<div className="form-check">
|
||||
<input className="form-check-input" type="checkbox" value="" id="flexCheckDefault"/>
|
||||
<label className="form-check-label" htmlFor="flexCheckDefault">
|
||||
<h2 className="h2_light">
|
||||
Согласен на обработку <Link to="./page2.html">персональных данных</Link>
|
||||
</h2>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
</>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default Page2;
|
69
4_laba_IP_project/src/pages/Page3.jsx
Normal file
@ -0,0 +1,69 @@
|
||||
import Object1 from '../assets/object_1.png';
|
||||
import BackArrow from '../components/BackArrow/BackArrow.jsx';
|
||||
|
||||
const Page3 = () => {
|
||||
return (
|
||||
<>
|
||||
<main className="container main_pannel">
|
||||
|
||||
<ul className="nav nav-pills mb-3 justify-content-center" id="pills-tab" role="tablist">
|
||||
<li className="nav-item" role="presentation">
|
||||
<button className="nav-link active me-2" id="pills-home-tab" data-bs-toggle="pill"
|
||||
data-bs-target="#pills-home"
|
||||
type="button" role="tab" aria-controls="pills-home" aria-selected="true">
|
||||
<h2>Корзина</h2></button>
|
||||
</li>
|
||||
<li className="nav-item" role="presentation">
|
||||
<button className="nav-link" id="pills-profile-tab" data-bs-toggle="pill"
|
||||
data-bs-target="#pills-profile"
|
||||
type="button" role="tab" aria-controls="pills-profile" aria-selected="false"><h2>История
|
||||
Заказов</h2></button>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<div className="tab-content" id="pills-tabContent">
|
||||
<div className="tab-pane fade show active" id="pills-home" role="tabpanel"
|
||||
aria-labelledby="pills-home-tab"
|
||||
tabIndex="0">
|
||||
<div className="container table">
|
||||
<div className="row">
|
||||
<div className="col">
|
||||
<img className="objects_basket" src={Object1} alt="object"/>
|
||||
</div>
|
||||
<div className="col">
|
||||
<div className="caption_basket"> Букет из клубники 108. <br/>Набор из клубники в
|
||||
шоколаде в коробке
|
||||
</div>
|
||||
</div>
|
||||
<div className="col">
|
||||
<div className="caption_basket_price"> 3000₽</div>
|
||||
</div>
|
||||
<div className="col">
|
||||
<button className="btn btn-primary add_object-button w-100" type="submit">Перейти к
|
||||
оплате
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<BackArrow/>
|
||||
|
||||
</div>
|
||||
<div className="tab-pane fade" id="pills-profile" role="tabpanel"
|
||||
aria-labelledby="pills-profile-tab" tabIndex="0">
|
||||
<div className="container table">
|
||||
<div className="row">
|
||||
<div className="col">
|
||||
<img className="objects_basket" src={Object1} alt="object"/>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default Page3;
|
28
4_laba_IP_project/src/pages/Page4.jsx
Normal file
@ -0,0 +1,28 @@
|
||||
import {Link} from 'react-router-dom';
|
||||
import object3 from '../assets/object_1.png';
|
||||
|
||||
const Page4 = () => {
|
||||
return (
|
||||
<>
|
||||
<main className="container main_pannel2">
|
||||
<div className="container view_object d-flex flex-column flex-md-row">
|
||||
<div className="left-cell">
|
||||
<img className="objects" src={object3} alt="object"/>
|
||||
</div>
|
||||
<div className="right-cell">
|
||||
<h3>Букет из клубники 108. <br/>Набор из клубники в шоколаде в коробке</h3>
|
||||
<div>
|
||||
<h3 style={{fontSize: '24px', color: '#a2a2a2'}}>Итого:</h3>
|
||||
<h3 className="price_object">3000₽</h3>
|
||||
<Link to="page5.html">
|
||||
<button type="button" className="btn btn-success btn-lg ">Добавить в корзину</button>
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default Page4;
|
12
4_laba_IP_project/vite.config.js
Normal file
@ -0,0 +1,12 @@
|
||||
import {defineConfig} from 'vite';
|
||||
import react from '@vitejs/plugin-react';
|
||||
|
||||
// https://vitejs.dev/config/
|
||||
export default defineConfig({
|
||||
plugins: [react()],
|
||||
build: {
|
||||
sourcemap: true,
|
||||
chunkSizeWarningLimit: 1024,
|
||||
emptyOutDir: true,
|
||||
},
|
||||
});
|