This commit is contained in:
DeerElk 2024-01-19 08:19:45 +04:00
parent fa38004a2e
commit 99a8851e2c
71 changed files with 4978 additions and 0 deletions

24
Lab4/.eslintrc.cjs Normal file
View File

@ -0,0 +1,24 @@
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',
},
}

15
Lab4/.vscode/launch.json vendored Normal file
View File

@ -0,0 +1,15 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "msedge",
"request": "launch",
"name": "Launch Edge",
"url": "http://localhost:5173",
"webRoot": "${workspaceFolder}"
},
]
}

150
Lab4/data.json Normal file

File diff suppressed because one or more lines are too long

15
Lab4/index.html Normal file
View File

@ -0,0 +1,15 @@
<html lang="ru">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Inkoria</title>
</head>
<body>
<div id="root" class="h-100 d-flex flex-column"></div>
<script type="module" src="/src/main.jsx"></script>
</body>
</html>

14
Lab4/jsconfig.json Normal file
View File

@ -0,0 +1,14 @@
{
"compilerOptions": {
"module": "ESNext",
"moduleResolution": "Node",
"target": "ES2020",
"jsx": "react",
"strictNullChecks": true,
"strictFunctionTypes": true
},
"exclude": [
"node_modules",
"**/node_modules/*"
]
}

4079
Lab4/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

33
Lab4/package.json Normal file
View File

@ -0,0 +1,33 @@
{
"name": "l4",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"build": "vite build",
"lint": "eslint . --ext js,jsx --report-unused-disable-directives --max-warnings 0",
"dev": "vite",
"preview": "vite preview"
},
"dependencies": {
"@fortawesome/fontawesome-free": "6.5.1",
"bootstrap": "5.3.2",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-router-dom": "^6.18.0",
"react-bootstrap": "^2.9.1",
"react-bootstrap-icons": "^1.10.3",
"prop-types": "^15.8.1"
},
"devDependencies": {
"eslint": "^8.50.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": "5.0.10",
"@types/react": "^18.2.15",
"@types/react-dom": "^18.2.7",
"@vitejs/plugin-react": "^4.0.3"
}
}

29
Lab4/public/favicon.svg Normal file
View File

@ -0,0 +1,29 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
width="120.000000pt" height="120.000000pt" viewBox="0 0 120.000000 120.000000"
preserveAspectRatio="xMidYMid meet">
<metadata>
Created by potrace 1.16, written by Peter Selinger 2001-2019
</metadata>
<g transform="translate(0.000000,120.000000) scale(0.009375,-0.009375)"
fill="#000000" stroke="none">
<path d="M5990 11035 c-404 -39 -762 -116 -1120 -241 -165 -57 -418 -164 -565
-239 -344 -176 -695 -413 -972 -657 -128 -113 -398 -388 -498 -508 -518 -624
-864 -1356 -1009 -2140 -102 -551 -102 -1149 0 -1700 145 -784 491 -1516 1009
-2140 172 -207 475 -499 703 -677 119 -94 431 -304 562 -378 700 -399 1486
-605 2299 -605 524 0 983 74 1466 235 550 183 1007 433 1475 809 176 141 540
508 682 686 561 706 890 1486 999 2370 30 239 37 713 15 950 -69 730 -270
1355 -634 1975 -310 526 -775 1033 -1292 1407 -598 433 -1294 712 -2067 827
-267 40 -775 53 -1053 26z m-1671 -1370 c223 -59 371 -250 371 -479 0 -143
-45 -253 -145 -353 -193 -193 -497 -196 -696 -7 -99 95 -149 218 -149 363 1
225 148 416 367 476 65 18 186 18 252 0z m396 -1866 c182 -155 398 -338 480
-409 262 -223 1703 -1446 1890 -1605 99 -84 322 -273 495 -420 l315 -268 6
1004 c3 552 7 1221 8 1487 l1 482 48 -4 c26 -2 215 -4 421 -5 l374 -1 -6
-1507 c-4 -830 -7 -1815 -7 -2190 l0 -682 -162 -3 -163 -3 -90 75 c-161 135
-1014 857 -2644 2236 -410 348 -747 631 -747 630 -4 -5 -14 -1484 -14 -2133
l0 -793 -437 0 -436 0 6 1298 c4 713 7 1701 7 2195 l0 897 163 0 162 -1 330
-280z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

3
Lab4/src/App.css Normal file
View File

@ -0,0 +1,3 @@
.hide-overflow-x {
overflow-x: hidden;
}

24
Lab4/src/App.jsx Normal file
View File

@ -0,0 +1,24 @@
import PropTypes from 'prop-types';
import { Container } from 'react-bootstrap';
import { Outlet } from 'react-router-dom';
import './App.css';
import Footer from './components/footer/Footer.jsx';
import Navigation from './components/navigation/Navigation.jsx';
const App = ({ routes }) => {
return (
<div className="hide-overflow-x">
<Navigation routes={routes}></Navigation>
<Container as="main" fluid>
<Outlet />
</Container>
<Footer />
</div>
);
};
App.propTypes = {
routes: PropTypes.array,
};
export default App;

Binary file not shown.

After

Width:  |  Height:  |  Size: 182 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 109 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 137 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 241 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 363 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 166 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

BIN
Lab4/src/assets/sp/sp1.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 88 KiB

BIN
Lab4/src/assets/sp/sp2.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 76 KiB

BIN
Lab4/src/assets/sp/sp3.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 110 KiB

BIN
Lab4/src/assets/sp/sp4.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

BIN
Lab4/src/assets/sp/sp5.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

BIN
Lab4/src/assets/sp/sp6.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 75 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 75 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 117 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 93 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 63 KiB

View File

@ -0,0 +1,23 @@
import { useState } from 'react';
import PropTypes from 'prop-types';
import './Accordion.css';
const Accordion = ({ title, content }) => {
const [isOpen, setIsOpen] = useState(false);
return (
<div>
<div className='square rounded-4 bg-black p-3 m-2' onClick={() => setIsOpen(!isOpen)}>
<h3 className='fs-1 text-white'>{title}</h3>
</div>
{isOpen && <p className='rounded-4 bg-black text-white p-3 m-4'>{content}</p>}
</div>
);
};
Accordion.propTypes = {
title: PropTypes.string.isRequired,
content: PropTypes.string.isRequired,
};
export default Accordion;

View File

@ -0,0 +1,25 @@
#banner {
margin: 2px;
display: flex;
align-items: center;
flex-direction: column;
}
#banner img {
border: 1px solid #3c3c3f;
border-radius: 5px;
}
#banner img.banner-show {
width: 100%;
opacity: 1;
transition: opacity 1s, visibility 0s;
}
#banner img.banner-hide {
height: 0;
width: 0;
opacity: 0;
visibility: hidden;
transition: opacity 1s, visibility 0s 1s;
}

View File

@ -0,0 +1,43 @@
import { useEffect, useState } from 'react';
import banner1 from '../../assets/banners/banner1.jpg';
import banner2 from '../../assets/banners/banner2.jpg';
import banner3 from '../../assets/banners/banner3.jpg';
import banner4 from '../../assets/banners/banner4.jpg';
import banner5 from '../../assets/banners/banner5.jpg';
import banner6 from '../../assets/banners/banner6.jpg';
import './Banner.css';
const Banner = () => {
const [currentBanner, setCurrentBanner] = useState(0);
const banners = [banner1, banner2, banner3, banner4, banner5, banner6];
const getBannerClass = (index) => {
return currentBanner === index ? 'banner-show' : 'banner-hide';
};
useEffect(() => {
const bannerInterval = setInterval(
() => {
console.info('Banner changed');
let current = currentBanner + 1;
if (current === banners.length) {
current = 0;
}
setCurrentBanner(current);
},
5000,
);
return () => clearInterval(bannerInterval);
});
return (
<div id="banner" >
{
banners.map((banner, index) =>
<img key={index} className={getBannerClass(index)} src={banner} alt={`banner${index}`} />)
}
</div >
);
};
export default Banner;

View File

View File

@ -0,0 +1,39 @@
import './Footer.css';
import {
Container,
Row,
Col,
} from 'react-bootstrap';
const Footer = () => {
const year = new Date().getFullYear();
return (
<Container fluid className="bg-black text-secondary pt-4" id="footer">
<Row className="lh-1">
<Col className="col-12 col-sm-12 col-md-6 col-lg-6 col-xl-6 d-flex justify-content-start">
<ul className="list-unstyled">
<p>
© ООО INKORIA, {year}
</p>
<p>
<a href="" className="underlined text-secondary">Авторизация</a>
</p>
</ul>
</Col>
<Col className="col-12 col-sm-12 col-md-6 col-lg-6 col-xl-6 d-flex justify-content-start">
<ul className="list-unstyled">
<p>
Контактная информация:
</p>
<p>
т. + 7 (996) 953-68-27, e-mail: inkoria@mail.ru
</p>
</ul>
</Col>
</Row>
</Container>
);
};
export default Footer;

View File

View File

@ -0,0 +1,18 @@
import PropTypes from 'prop-types';
import './FormOtz.css';
const FormOtz = ({ title, text }) => {
return (
<div className="square rounded-4 m-3 p-3 bg-black col-11 col-sm-11 col-md-11 col-lg-2 col-xl-3">
<p className="fs-4 text-white">{title}</p>
<p className="text-white">{text}</p>
</div>
);
};
FormOtz.propTypes = {
title: PropTypes.string.isRequired,
text: PropTypes.string.isRequired,
};
export default FormOtz;

View File

View File

@ -0,0 +1,20 @@
import PropTypes from 'prop-types';
import './FormSp.css';
const FormSp = ({ imageSrc, title, text }) => {
return (
<div className="square rounded-4 m-3 p-0 bg-black col-11 col-sm-11 col-md-11 col-lg-2 col-xl-3">
<img src={imageSrc} className="square rounded-top-4 d-block w-100 p-0 object-fit-cover" alt={title} />
<p className="text-center fs-2 mt-1 mb-0 text-white fw-bold">{title}</p>
<p className="text-center fs-5 mb-3 mt-0 text-white">{text}</p>
</div>
);
};
FormSp.propTypes = {
imageSrc: PropTypes.string.isRequired,
title: PropTypes.string.isRequired,
text: PropTypes.string.isRequired,
};
export default FormSp;

View File

View File

@ -0,0 +1,18 @@
import PropTypes from 'prop-types';
import './FormUsl.css';
const FormUsl = ({ title, text }) => {
return (
<div className="square rounded-4 m-3 p-3 bg-black col-11 col-sm-11 col-md-11 col-lg-3 col-xl-3 text-center align-items-center justify-content-center text-center">
<p className="fs-3 text-white fw-bold">{title}</p>
<p className="fs-5 text-white">{text}</p>
</div>
);
};
FormUsl.propTypes = {
title: PropTypes.string.isRequired,
text: PropTypes.string.isRequired,
};
export default FormUsl;

View File

View File

@ -0,0 +1,13 @@
import './Map.css';
import { } from 'react-bootstrap';
const Map = () => {
return (
<iframe className="d-block w-100 square rounded-4 object-fit-cover"
src="https://yandex.ru/map-widget/v1/?ll=48.395364%2C54.326638&mode=search&oid=183869084795&ol=biz&sctx=ZAAAAAgBEAAaKAoSCe%2FlPjkKMkhAEd2XM9sVKktAEhIJfEYiNIKNvz8R%2FFbrxOV4pT8iBgABAgMEBSgKOABA8J8NSAFiIW1pZGRsZV9wb3N0ZmlsdGVyX3RocmVzaGNoYWluPTAuNGIcbWlkZGxlX3Bvc3RmaWx0ZXJfdGhyZXNoPTAuNGIucmVsZXZfcmFua2luZ19tc2VfZm9ybXVsYT0xLjA6bXNlX2RjMzM5NDQzX2V4cGJQcmVhcnI9c2NoZW1lX0xvY2FsL0dlby9CdXNHZW9DaG9vc2UvVGFrZVJ1YnJpY0ZpcnN0U2FtZUJ5UmVzdWx0c01zZVRocmVzaG9sZD0wLjRqAnJ1nQHNzEw9oAEAqAEAvQGVqpI%2BwgEG%2B6jO%2B6wF6gEA8gEA%2BAEAggIHaW5rb3JpYYoCAJICAJoCDGRlc2t0b3AtbWFwcw%3D%3D&sll=48.395364%2C54.326638&sspn=0.014475%2C0.004926&text=inkoria&z=17.09"
height="300">
</iframe>
);
};
export default Map;

View File

View File

@ -0,0 +1,14 @@
import PropTypes from 'prop-types';
import './Name.css';
const Name = ({ title }) => {
return (
<h1 className="text-center display-3 m-3 text-black fw-bold lh-lg">{title}</h1>
);
};
Name.propTypes = {
title: PropTypes.string.isRequired,
};
export default Name;

View File

@ -0,0 +1,36 @@
header {
background-color: #000000;
font-size: 2.2vh;
}
.nav-link {
color: #FFFFFF;
}
.nav-link.active {
color: #B2309D !important;
}
header a:hover:not(.active) {
color: #FF9FEF;
}
#logo {
background-color: #FFFFFF;
z-index: -1;
}
#logo:hover {
background-color: #FF9FEF;
z-index: -1;
}
.row img {
background-color: #FFFFFF;
z-index: -1;
}
.row img:hover {
background-color: #FF9FEF;
z-index: -1;
}

View File

@ -0,0 +1,80 @@
import PropTypes from 'prop-types';
import {
Container,
Nav,
Navbar,
Image,
Row,
Col,
} from 'react-bootstrap';
import { Link, useLocation } from 'react-router-dom';
import './Navigation.css';
import whatsapp from '../../assets/icons/whatsapp.png';
import inst from '../../assets/icons/inst.png';
import vk from '../../assets/icons/vk.png';
import tg from '../../assets/icons/tg.png';
import logo from '../../assets/logo/logotransp.png';
const Navigation = ({ routes }) => {
const location = useLocation();
const indexPageLink = routes.filter((route) => route.index === false).shift();
const pages = routes.filter((route) => Object.prototype.hasOwnProperty.call(route, 'title'));
return (
<>
<header className="fixed-top">
<Navbar expand='lg' data-bs-theme='dark' className='my-navbar'>
<Container fluid>
<Navbar.Brand as={Link} to={indexPageLink?.path ?? '/'}>
<div id="logo">
<Image src={logo} alt="Логотип INKORIA"></Image>
</div>
</Navbar.Brand>
<Navbar.Toggle aria-controls='main-navbar' />
<Navbar.Collapse id='main-navbar'>
<Nav className='me-auto link nav-fill w-100 justify-content-center align-items-center fw-bold' activeKey={location.pathname}>
{
pages.map((page) =>
<Nav.Link as={Link} key={page.path} eventKey={page.path} to={page.path ?? '/'}>
{page.title}
</Nav.Link>)
}
<Row id="social-icons">
<Col className="d-none d-xl-block">
<a href="https://www.wa.me/79969536827"><Image src={whatsapp}></Image></a>
</Col>
<Col className="d-none d-xl-block">
<a href="https://www.instagram.com/vrode__anya"><Image src={inst}></Image></a>
</Col>
<Col className="d-none d-xl-block">
<a href="https://www.vk.com/vrode_anya"><Image src={vk}></Image></a>
</Col>
<Col className="d-none d-xl-block">
<Link href="https://www.t.me/vrode_anyya"><Image src={tg}></Image></Link>
</Col>
</Row>
</Nav>
</Navbar.Collapse>
</Container>
</Navbar >
</header>
<header>
<Navbar expand='lg' className='my-navbar'>
<Container fluid>
<Navbar.Brand as={Link} to={indexPageLink?.path ?? '/'}>
<div id="logo">
<Image src={logo} alt="Логотип INKORIA"></Image>
</div>
</Navbar.Brand>
</Container>
</Navbar >
</header>
</>
);
};
Navigation.propTypes = {
routes: PropTypes.array,
};
export default Navigation;

5
Lab4/src/index.css Normal file
View File

@ -0,0 +1,5 @@
body {
overflow-x: hidden;
background-color: #B2309D;
min-height: 100vh;
}

62
Lab4/src/main.jsx Normal file
View File

@ -0,0 +1,62 @@
import 'bootstrap/dist/css/bootstrap.min.css';
import React from 'react';
import ReactDOM from 'react-dom/client';
import { RouterProvider, createBrowserRouter } from 'react-router-dom';
import App from './App.jsx';
import './index.css';
import ErrorPage from './pages/ErrorPage.jsx';
import Welcome from './pages/Welcome.jsx';
import Uslugi from './pages/Uslugi.jsx';
import Ukrasheniya from './pages/Ukrasheniya.jsx';
import Specialisty from './pages/Specialisty.jsx';
import Faq from './pages/Faq.jsx';
import Otzyvy from './pages/Otzyvy.jsx';
const routes = [
{
index: true,
path: '/',
element: <Welcome />,
title: 'ГЛАВНАЯ',
},
{
path: '/uslugi',
element: <Uslugi />,
title: 'УСЛУГИ',
},
{
path: '/ukrasheniya',
element: <Ukrasheniya />,
title: 'УКРАШЕНИЯ',
},
{
path: '/specialisty',
element: <Specialisty />,
title: 'СПЕЦИАЛИСТЫ',
},
{
path: '/otzyvy',
element: <Otzyvy />,
title: 'ОТЗЫВЫ',
},
{
path: '/faq',
element: <Faq />,
title: 'FAQ',
},
];
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>,
);

View 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;

26
Lab4/src/pages/Faq.jsx Normal file
View File

@ -0,0 +1,26 @@
import {
Container,
} from 'react-bootstrap';
import Accordion from '../components/accordion/Accordion.jsx';
import Name from '../components/name/Name.jsx';
const Faq = () => {
return (
<Container>
<Name title="FAQ"/>
<Accordion title="Что такое пирсинг?" content="Пирсинг - это процесс прокола кожи и введения украшения (обычно кольца, штифта или балла) в результате модификации тела. Он может быть выполнен на разных частях тела, включая уши, нос, губы, язык, брови, пупок и многие другие." />
<Accordion title="Бывает ли пирсинг безболезненным?" content="Боль при пирсинге может различаться в зависимости от места прокола, индивидуальной чувствительности и мастерства пирсера. Некоторые люди могут испытывать лишь небольшую боль или дискомфорт, а другие - более сильные ощущения. Однако, мастера пирсинга используют специальное оборудование и техники, чтобы сделать процесс как можно более комфортным для клиента." />
<Accordion title="Как подготовиться к пирсингу?" content="Перед пирсингом рекомендуется следующее:
- Выбрать сертифицированного и опытного мастера пирсинга
- Изучить место пирсинга
- Не употреблять алкоголь перед процедурой" />
<Accordion title="Как ухаживать за пирсингом после процедуры?" content="Уход за пирсингом является важной частью процесса заживления. Рекомендации по уходу могут различаться в зависимости от места пирсинга. Однако, в целом следующие советы могут быть полезными:
- Регулярно очищайте пирсинг с помощью нежного мыла и воды.
- Избегайте касания пирсинга грязными руками и трения об одежду.
- Следуйте инструкциям по использованию мазей или кремов."/>
<Accordion title="Как долго заживает пирсинг?" content="Время заживления пирсинга может варьироваться в зависимости от места пирсинга, вашего здоровья и других факторов. Обычно уши заживают примерно за 6-8 недель, нос - около 2-4 месяцев, а пирсинги с длинными канюлями (например, языка или пупка) могут заживать от 4 до 12 недель. Важно понимать, что время заживления может быть индивидуальным и может отличаться для каждого человека."/>
<Accordion title="Какие могут быть осложнения и риски при пирсинге?" content="Пирсинг, так же как и любая другая процедура, сопряжен со своими рисками. Осложнения могут включать инфекцию, аллергические реакции на металлы, кровотечение, а также риск повреждения нервов или других тканей. Поэтому очень важно обратиться к опытному мастеру пирсинга, соблюдать все рекомендации по уходу и следить за своими ощущениями после выполнения пирсинга"/>
</Container>
);
};
export default Faq;

40
Lab4/src/pages/Otzyvy.jsx Normal file
View File

@ -0,0 +1,40 @@
import { Container, Row } from 'react-bootstrap';
import FormOtz from '../components/formOtz/FormOtz.jsx';
import Name from '../components/name/Name.jsx';
const Otzyvy = () => {
return (
<>
<Name title="Отзывы"/>
<Container>
<Row className = "d-flex justify-content-between text-white">
<FormOtz title="Кирилл Пятаков" text=" Я был очень доволен своим первым опытом пирсинга в этой студии. Персонал
был профессиональным и добрым, они сразу ответили на все мои вопросы и
посвятили достаточно времени, чтобы убедиться, что я полностью понимаю
процесс. Результат был идеальным, и я чувствую, что я нашел место, где
могу делать пирсинги и доверять им своё тело." />
<FormOtz title="Анна Долгова" text="Я получил свой пирсинг в этой студии несколько месяцев назад, и я до сих
пор в восторге от результата. Чистота и гигиена здесь на самом высоком
уровне, что очень важно для меня. Работники были терпеливыми и
вежливыми, учитывая мои нервы и волнения. Теперь я регулярно посещаю
эту студию, чтобы обновить свой пирсинг и получить консультацию по
уходу за ним." />
<FormOtz title="Анна Долгова" text="Я получил свой пирсинг в этой студии несколько месяцев назад, и я до сих
пор в восторге от результата. Чистота и гигиена здесь на самом высоком
уровне, что очень важно для меня. Работники были терпеливыми и
вежливыми, учитывая мои нервы и волнения. Теперь я регулярно посещаю
эту студию, чтобы обновить свой пирсинг и получить консультацию по
уходу за ним." />
<FormOtz title="Анна Долгова" text="Я получил свой пирсинг в этой студии несколько месяцев назад, и я до сих
пор в восторге от результата. Чистота и гигиена здесь на самом высоком
уровне, что очень важно для меня. Работники были терпеливыми и
вежливыми, учитывая мои нервы и волнения. Теперь я регулярно посещаю
эту студию, чтобы обновить свой пирсинг и получить консультацию по
уходу за ним." />
</Row>
</Container>
</>
);
};
export default Otzyvy;

View File

@ -0,0 +1,28 @@
import { Container, Row } from 'react-bootstrap';
import FormSp from '../components/formSp/FormSp.jsx';
import Name from '../components/name/Name.jsx';
import sp1 from '../assets/sp/sp1.jpg';
import sp2 from '../assets/sp/sp2.jpg';
import sp3 from '../assets/sp/sp3.jpg';
import sp4 from '../assets/sp/sp4.jpg';
import sp5 from '../assets/sp/sp5.jpg';
import sp6 from '../assets/sp/sp6.jpg';
const Specialisty = () => {
return (
<>
<Name title="Специалисты"/>
<Container>
<Row className="d-flex justify-content-between">
<FormSp imageSrc={sp1} title="Дмитрий Кузнецов" text="мастер" />
<FormSp imageSrc={sp2} title="Максим Булаев" text="мастер" />
<FormSp imageSrc={sp3} title="Даниил Касушкин" text="мастер" />
<FormSp imageSrc={sp4} title="Софья Ильина" text="мастер" />
<FormSp imageSrc={sp5} title="Анна Милашина" text="мастер" />
<FormSp imageSrc={sp6} title="Сергей Князькин" text="мастер" />
</Row>
</Container>
</>
);
};
export default Specialisty;

View File

@ -0,0 +1,16 @@
import { Button, Table } from 'react-bootstrap';
import Name from '../components/name/Name.jsx';
const Ukrasheniya = () => {
return (
<>
<Name title="Украшения"/>
<Button id="items-add" variant="info">Добавить товар</Button>
<Table className="mt-2" striped>
</Table>
</>
);
};
export default Ukrasheniya;

25
Lab4/src/pages/Uslugi.jsx Normal file
View File

@ -0,0 +1,25 @@
import { Container, Row } from 'react-bootstrap';
import FormUsl from '../components/formsUsl/FormUsl.jsx';
import Name from '../components/name/Name.jsx';
const Uslugi = () => {
return (
<>
<Name title="Услуги"/>
<Container>
<Row className="row d-flex justify-content-between">
<FormUsl title="Консультация" text="Получите профессиональную консультацию перед проколом" />
<FormUsl title="Стандартный прокол" text="Прокол ушей, носа, языка, губ, септум и др." />
<FormUsl title="Сложный прокол" text="Прокол хрящей, трагус, снаг и др." />
<FormUsl title="Чистка украшений" text="Очистка и полировка ваших украшений" />
<FormUsl title="Анодирование" text="Разнообразные цветовые варианты для украшений"/>
<FormUsl title="Восстановление" text="Восстановление старых заросших каналов"/>
<FormUsl title="Чистка прокола" text="Чистка прокола от грязи и выделений"/>
<FormUsl title="Удаление" text="Качественное удаление пирсинга"/>
<FormUsl title="Другие" text="Напишите нам, чтобы узнать больше"/>
</Row>
</Container>
</>
);
};
export default Uslugi;

View File

@ -0,0 +1,30 @@
import {
Button,
Container,
Row,
Col,
} from 'react-bootstrap';
import Banner from '../components/banner/Banner.jsx';
import Map from '../components/map/Map.jsx';
const Welcome = () => {
return (
<Container fluid className="p-0">
<Row className="p-0">
<Col xs={12} sm={12} md={12} lg={12} xl={6} className="p-0">
<Banner />
</Col>
<Col className="d-flex m-auto p-3 col-12 col-sm-12 col-md-12 col-lg-12 col-xl-6 text-black flex-column align-items-center text-center">
<h1 className="display-5 mb-3 text-black">Добро пожаловать в INKORIA</h1>
<div className="col-12">
<Map />
</div>
<Button type="button" className="btn col-6 btn-lg mt-3 bg-black text-white">
<a href="https://n879755.yclients.com" className="text-white">Записаться</a>
</Button>
</Col>
</Row>
</Container>
);
};
export default Welcome;

12
Lab4/vite.config.js Normal file
View File

@ -0,0 +1,12 @@
/* eslint-disable import/no-extraneous-dependencies */
import react from '@vitejs/plugin-react';
import { defineConfig } from 'vite';
export default defineConfig({
plugins: [react()],
build: {
sourcemap: true,
chunkSizeWarningLimit: 1024,
emptyOutDir: true,
},
});