Лабораторная 5 с отчётом

This commit is contained in:
Никита Белянин 2023-12-25 15:50:03 +04:00
parent cddd312723
commit 7d929e7d7c
55 changed files with 1184 additions and 0 deletions

34
Lab5/src/App.jsx Normal file
View File

@ -0,0 +1,34 @@
import PropTypes from 'prop-types';
import { Container } from 'react-bootstrap';
import { Toaster } from 'react-hot-toast';
import { Outlet } from 'react-router-dom';
import { CartProvider } from './components/cart/CartContext.jsx';
import { AdvertProvider } from './components/advert/CartAdvertContext.jsx';
import { UserProvider } from './components/login/users/UserContext.jsx';
import Footer from './components/footer/Footer.jsx';
import Navigation from './components/navigation/Navigation.jsx';
const App = ({ routes }) => {
return (
<>
<UserProvider>
<CartProvider>
<AdvertProvider>
<Navigation routes={routes}></Navigation>
<Container className='p-2' as='main' fluid>
<Outlet />
</Container>
<Footer />
<Toaster position='top-center' reverseOrder={true} />
</AdvertProvider>
</CartProvider>
</UserProvider>
</>
);
};
App.propTypes = {
routes: PropTypes.array,
};
export default App;

BIN
Lab5/src/assets/200.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

BIN
Lab5/src/assets/Image1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

BIN
Lab5/src/assets/Image10.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 452 KiB

BIN
Lab5/src/assets/Image11.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 655 KiB

BIN
Lab5/src/assets/Image12.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 377 KiB

BIN
Lab5/src/assets/Image13.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 84 KiB

BIN
Lab5/src/assets/Image2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 363 KiB

BIN
Lab5/src/assets/Image3.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

BIN
Lab5/src/assets/Image4.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 76 KiB

BIN
Lab5/src/assets/Image5.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 82 KiB

BIN
Lab5/src/assets/Image6.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 179 KiB

BIN
Lab5/src/assets/Image7.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 156 KiB

BIN
Lab5/src/assets/Image8.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

BIN
Lab5/src/assets/Image9.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 248 KiB

BIN
Lab5/src/assets/banner1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 640 KiB

BIN
Lab5/src/assets/banner2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 812 KiB

BIN
Lab5/src/assets/banner3.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 767 KiB

BIN
Lab5/src/assets/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

View File

@ -0,0 +1,40 @@
import axios from 'axios';
import toast from 'react-hot-toast';
export class HttpError extends Error {
constructor(message = '') {
super(message);
this.name = 'HttpError';
Object.setPrototypeOf(this, new.target.prototype);
toast.error(message, { id: 'HttpError' });
}
}
function responseHandler(response) {
if (response.status === 200 || response.status === 201) {
const data = response?.data;
if (!data) {
throw new HttpError('API Error. No data!');
}
return data;
}
throw new HttpError(`API Error! Invalid status code ${response.status}!`);
}
function responseErrorHandler(error) {
if (error === null) {
throw new Error('Unrecoverable error!! Error is null!');
}
toast.error(error.message, { id: 'AxiosError' });
return Promise.reject(error.message);
}
export const ApiClient = axios.create({
baseURL: 'http://localhost:8081/',
timeout: '3000',
headers: {
Accept: 'application/json',
},
});
ApiClient.interceptors.response.use(responseHandler, responseErrorHandler);

View File

@ -0,0 +1,33 @@
import { ApiClient } from './ApiClient';
class ApiService {
constructor(url) {
this.url = url;
}
async getAll(expand) {
return ApiClient.get(`${this.url}${expand || ''}`);
}
async get(id, expand) {
return ApiClient.get(`${this.url}/${id}${expand || ''}`);
}
async getUser(id) {
return ApiClient.get(`${this.url}?id=${id}`);
}
async create(body) {
return ApiClient.post(this.url, body);
}
async update(id, body) {
return ApiClient.put(`${this.url}/${id}`, body);
}
async delete(id) {
return ApiClient.delete(`${this.url}/${id}`);
}
}
export default ApiService;

View File

@ -0,0 +1,17 @@
.cart-image {
width: 4.5rem;
padding: .25rem;
}
.cart-item {
height: auto;
}
.cart-text{
color: White;
font-size: 32px;
}
.textlinkcart{
color: white;
}

View File

@ -0,0 +1,46 @@
import { Button, ButtonGroup, Card } from 'react-bootstrap';
import { XLg } from 'react-bootstrap-icons';
import imgPlaceholder from '../../assets/200.png';
import { GetUserId } from '../login/users/UserReducer';
import useCart from './CartHook';
import './Cart.css';
const Cart = () => {
const {
cart,
removeFromCart,
clearCart,
} = useCart();
const id = GetUserId();
console.log(id);
return (
<div className='d-flex flex-column align-items-center'>
<div className='mb-2 col-12 col-md-8 col-lg-6 d-flex align-items-center'>
<strong className='flex-fill col-3 cart-text'> Избранные объявления </strong>
<Button variant='danger' onClick={() => clearCart()}>
<XLg /> Очистить
</Button>
</div>
{
cart.map((cartItem) =>
<Card key={cartItem.id} className='mb-2 col-12 col-md-8 col-lg-6 w-50'>
<Card.Body className='p-2 d-flex flex-column flex-sm-row align-items-center'>
<div className='cart-item flex-fill'>
<img className='cart-image' src={cartItem.image || imgPlaceholder} alt="Cart Image" />
{cartItem.type.name}
</div>
<ButtonGroup className='mt-2 mt-sm-1' aria-label="Cart counter">
<Button variant="primary" onClick={() => removeFromCart(cartItem)}>
<XLg />
</Button>
</ButtonGroup>
</Card.Body>
</Card>)
}
</div>
);
};
export default Cart;

View File

@ -0,0 +1,29 @@
import PropTypes from 'prop-types';
import {
createContext,
useEffect,
useReducer,
} from 'react';
import { cartReducer, loadCart, saveCart } from './CartReducer';
const CartContext = createContext(null);
export const CartProvider = ({ children }) => {
const [cart, dispatch] = useReducer(cartReducer, [], loadCart);
useEffect(() => {
saveCart(cart || []);
}, [cart]);
return (
<CartContext.Provider value={{ cart, dispatch }}>
{children}
</CartContext.Provider>
);
};
CartProvider.propTypes = {
children: PropTypes.node,
};
export default CartContext;

View File

@ -0,0 +1,26 @@
import { useContext } from 'react';
import CartContext from './CartContext.jsx';
import { cartAdd, cartClear, cartRemove } from './CartReducer';
const useCart = () => {
const { cart, dispatch } = useContext(CartContext);
const cartSum = () => {
return parseFloat(
cart?.reduce((sum, cartItem) => {
return sum + (cartItem.price * cartItem.count);
}, 0)
?? 0,
).toFixed(2);
};
return {
cart,
getCartSum: () => cartSum(),
addToCart: (item) => dispatch(cartAdd(item)),
removeFromCart: (item) => dispatch(cartRemove(item)),
clearCart: () => dispatch(cartClear()),
};
};
export default useCart;

View File

@ -0,0 +1,71 @@
const setCartCount = (cart, item) => {
return cart.map((cartItem) => {
if (cartItem.id === item.id) {
return { ...cartItem, count: cartItem.count };
}
return cartItem;
});
};
const addToCart = (cart, item) => {
const existsItem = cart.find((cartItem) => cartItem.id === item.id);
if (existsItem !== undefined) {
return setCartCount(cart, item, 1);
}
return [...cart, { ...item, count: 1 }];
};
const removeFromCart = (cart, item) => {
const existsItem = cart.find((cartItem) => cartItem.id === item.id);
if (existsItem !== undefined && existsItem.count > 1) {
return setCartCount(cart, item, -1);
}
return cart.filter((cartItem) => cartItem.id !== item.id);
};
const CART_KEY = 'localCart';
const CART_ADD = 'cart/add';
const CART_REMOVE = 'cart/remove';
const CART_CLEAR = 'cart/clear';
export const saveCart = (cart) => {
localStorage.setItem(CART_KEY, JSON.stringify(cart));
};
export const loadCart = (initialValue = []) => {
const cartData = localStorage.getItem(CART_KEY);
if (cartData) {
return JSON.parse(cartData);
}
return initialValue;
};
export const cartReducer = (cart, action) => {
const { item } = action;
switch (action.type) {
case CART_ADD: {
return addToCart(cart, item);
}
case CART_REMOVE: {
return removeFromCart(cart, item);
}
case CART_CLEAR: {
return [];
}
default: {
throw Error(`Unknown action: ${action.type}`);
}
}
};
export const cartAdd = (item) => ({
value: CART_ADD, item,
});
export const cartRemove = (item) => ({
type: CART_REMOVE, item,
});
export const cartClear = () => ({
value: CART_CLEAR,
});

View File

@ -0,0 +1,23 @@
import PropTypes from 'prop-types';
import { Form } from 'react-bootstrap';
const Input = ({
name, label, value, onChange, className, ...rest
}) => {
return (
<Form.Group className={`mb-2 ${className || ''}`} controlId={name}>
<Form.Label>{label}</Form.Label>
<Form.Control name={name || ''} value={value || ''} onChange={onChange} {...rest} />
</Form.Group>
);
};
Input.propTypes = {
name: PropTypes.string,
label: PropTypes.string,
value: PropTypes.string,
onChange: PropTypes.func,
className: PropTypes.string,
};
export default Input;

View File

@ -0,0 +1,3 @@
.form1{
width: 16rem;
}

View File

@ -0,0 +1,30 @@
import PropTypes from 'prop-types';
import { Form } from 'react-bootstrap';
import './Select.css';
const Select = ({
values, name, label, value, onChange, className, ...rest
}) => {
return (
<Form.Group className={`form1 mb-2 ${className || ''}`} controlId={name}>
<Form.Label className='form-label'>{label}</Form.Label>
<Form.Select name={name || ''} value={value || ''} onChange={onChange} {...rest}>
<option value=''> Все квартиры </option>
{
values.map((type) => <option key={type.id} value={type.id}>{type.name}</option>)
}
</Form.Select>
</Form.Group>
);
};
Select.propTypes = {
values: PropTypes.array,
name: PropTypes.string,
label: PropTypes.string,
value: PropTypes.string,
onChange: PropTypes.func,
className: PropTypes.string,
};
export default Select;

View File

@ -0,0 +1,49 @@
import PropTypes from 'prop-types';
import { Button, Form } from 'react-bootstrap';
import { useNavigate } from 'react-router-dom';
import useLinesItemForm from '../hooks/LinesItemFormHook';
import LinesItemForm from './LinesItemForm.jsx';
import './LinesItemForm.css';
const LinesForm = ({ id }) => {
const navigate = useNavigate();
const {
item,
validated,
handleSubmit,
handleChange,
} = useLinesItemForm(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}>
<LinesItemForm item={item} 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>
</>
);
};
LinesForm.propTypes = {
id: PropTypes.string,
};
export default LinesForm;

View File

@ -0,0 +1,3 @@
#image-preview {
width: 200px;
}

View File

@ -0,0 +1,30 @@
import PropTypes from 'prop-types';
import imgPlaceholder from '../../../assets/200.png';
import Input from '../../input/Input.jsx';
import Select from '../../input/Select.jsx';
import useTypes from '../../types/hooks/TypesHook';
import './LinesItemForm.css';
const LinesItemForm = ({ item, handleChange }) => {
const { types } = useTypes();
return (
<>
<div className='text-center'>
<img id='image-preview' className='rounded' alt='placeholder'
src={item.image || imgPlaceholder} />
</div>
<Select values={types} name='typeId' label='Квартиры' value={item.typeId} onChange={handleChange} required />
<Input name='price' label='Цена' value={item.price} onChange={handleChange} type='number' min='1000.0' step='0.50' required />
<Input name='description' label='Текст' value={item.description} onChange={handleChange} type='text' required />
<Input name='image' label='Изображение' onChange={handleChange} type='file' accept='image/*' />
</>
);
};
LinesItemForm.propTypes = {
item: PropTypes.object,
handleChange: PropTypes.func,
};
export default LinesItemForm;

11
Lab5/src/index.css Normal file
View File

@ -0,0 +1,11 @@
h1 {
font-size: 1.5em;
}
h2 {
font-size: 1.25em;
}
h3 {
font-size: 1.1em;
}

85
Lab5/src/main.jsx Normal file
View File

@ -0,0 +1,85 @@
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 PageMain from './pages/PageMain.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';
import Page5 from './pages/Page5.jsx';
import PageMyBulletin from './pages/PageMyBulletin.jsx';
import PageEdit from './pages/PageEdit.jsx';
import LogIn from './pages/LogIn.jsx';
import SignIn from './pages/SignIn.jsx';
import OrderPage from './pages/OrderPage.jsx';
const routes = [
{
index: true,
path: '/',
element: <PageMain />,
},
{
path: '/pageMyBulletin',
element: <PageMyBulletin />,
title: 'Обзор',
},
{
path: '/page2',
element: <Page2 />,
title: 'О нас',
},
{
path: '/page3',
element: <Page3 />,
title: 'Избранное',
},
{
path: '/page4',
element: <Page4 />,
title: 'Контакты',
},
{
path: '/page5',
element: <Page5 />,
},
{
path: '/page1',
element: <Page1 />,
},
{
path: '/page-edit/:id?',
element: <PageEdit />,
},
{
path: '/logIn',
element: <LogIn />,
},
{
path: '/signIn',
element: <SignIn />,
},
{
path: '/orderPage',
element: <OrderPage />,
},
];
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,5 @@
.back{
text-align: center;
font-size: 18px;
color: red;
}

View File

@ -0,0 +1,20 @@
import { Alert, Button, Container } from 'react-bootstrap';
import { useNavigate, useRouteError } from 'react-router-dom';
const ErrorPage = () => {
const navigate = useNavigate();
const error = useRouteError();
return (
<Container fluid className='m-0 p-3 row justify-content-center'>
<Alert className='col-12 col-lg-6' variant='danger'>
{error?.message ?? 'Страница не найдена'}
</Alert>
<div className='w-100'></div>
<Button className='col-12 col-lg-6' variant='primary'
onClick={() => navigate(-1)}> Назад </Button>
</Container>
);
};
export default ErrorPage;

21
Lab5/src/pages/LogIn.css Normal file
View File

@ -0,0 +1,21 @@
.TitleLogin{
text-align: center;
color: white;
font-size: 42px;
}
.btnLog{
color: red;
}
@media (max-width: 550px) {
.imgg1{
display: none;
}
}
@media (max-width: 500px) {
.col-7{
width: 100%;
}
}

37
Lab5/src/pages/LogIn.jsx Normal file
View File

@ -0,0 +1,37 @@
import PropTypes from 'prop-types';
import { Container, Row } from 'react-bootstrap';
import LoginForm from '../components/login/form/LoginForm.jsx';
import Image12 from '../assets/Image12.png';
import './LogIn.css';
const LogIn = () => {
return (
<Container fluid className='container-fluid wrapper'>
<div className="TitleLogin">
<p>Войти в профиль</p>
</div>
<Row>
<div className='col-7'>
<div className="row justify-content-center">
<LoginForm />
</div>
</div>
<div className="col">
<div className="col-md-10 offset">
<img className="imgg1 w-100 h-100" src={Image12} alt="banner" />
</div>
</div>
</Row>
</Container>
);
};
LogIn.propTypes = {
index: PropTypes.number,
line: PropTypes.object,
};
export default LogIn;

View File

@ -0,0 +1,12 @@
import { useParams } from 'react-router-dom';
import LinesFormOrder from '../components/lines/formOrder/LinesFormOrder.jsx';
const OrderPage = () => {
const { id } = useParams();
return (
<LinesFormOrder id={id} />
);
};
export default OrderPage;

44
Lab5/src/pages/Page1.css Normal file
View File

@ -0,0 +1,44 @@
body{
background-color: #85DADA;
}
.card-title{
color: black;
text-decoration: none;
}
.textlinkBut{
color: white;
text-decoration: none;
}
.textlinkButMy{
color: white;
text-decoration: none;
}
.card{
width: 18rem;
/* margin:0 !important; */
padding:0 !important;
}
.btn1{
background-color: #0d6efd;
}
.btn11{
background-color: #0d6efd;
width: 30px;
}
.btn2{
color: red;
width: 30rem;
}
@media (max-width: 325px) {
.card{
width: 100%;
}
}

12
Lab5/src/pages/Page1.jsx Normal file
View File

@ -0,0 +1,12 @@
import Lines from '../components/lines/table/Lines.jsx';
import './Page1.css';
const Page1 = () => {
return (
<>
<Lines />
</>
);
};
export default Page1;

27
Lab5/src/pages/Page2.css Normal file
View File

@ -0,0 +1,27 @@
body{
background-color: #85DADA;
}
.card-title{
color: black;
text-decoration: none;
}
.card{
width: 18rem;
}
.btn1{
background-color: #0d6efd;
}
.btn2{
color: red;
width: 30rem;
}
@media (max-width: 325px) {
.card{
width: 100%;
}
}

49
Lab5/src/pages/Page2.jsx Normal file
View File

@ -0,0 +1,49 @@
import { Container } from 'react-bootstrap';
import './Page2.css';
const Page2 = () => {
return (
<>
<Container fluid className='container-fluid wrapper flex-shrink-0 p-0'>
<div className="container">
<div className="textus">
<p> <u> О портале</u></p>
</div>
<div className="textus">
<p> <marquee direction="right"> Позвольте нам сэкономить ваше время и деньги </marquee> </p>
</div>
<div className="textus">
<p>Нужна квартира в Ульяновске? Не хотите перепачивать? Именно на нашем
сайте UlRent мы поможем вам найти необходимое жильё. На нашем портале
аренды недвижимости. Место, в котором можно снять квартиру посуточно
или на долгий срок с максимальной экономией. Почему портал назван
независимым? Потому что мы не связаны ни с одним агенством недвижимости
Ульяновска, И предлагаем только честные цены на квартиры от реальных
собственников. Почему портав назван выгодным и экономным?
Статистика показывает, что клиенты, работащие с посредниками переплатили
бы на 20%-30%
</p>
</div>
<div className="textus">
<p>Для собственников</p>
</div>
<div className="textus">
<p>Если вы являетесь собственником уютной, удобной и комфортной квартиры,
то вы можете разместить своё личное объявление об аренде вашего жилья.
Посуточно или на определённый продолжительный срок - выбор за вами.
Для вас в качестве арендодателя представляется возможность
определять цену и размещать свои контактные данные
</p>
</div>
</div>
</Container>
</>
);
};
export default Page2;

11
Lab5/src/pages/Page3.jsx Normal file
View File

@ -0,0 +1,11 @@
import Cart from '../components/cart/Cart.jsx';
const Page3 = () => {
return (
<>
<Cart/>
</>
);
};
export default Page3;

32
Lab5/src/pages/Page4.css Normal file
View File

@ -0,0 +1,32 @@
.textus{
color: white;
font-size: 36px
}
.ifram{
height: 600px;
}
@media (max-width: 900px) {
.ifram{
height: 500px;
}
}
@media (max-width: 750px) {
.ifram{
height: 400px;
}
}
@media (max-width: 500px) {
.ifram{
height: 300px;
}
}
@media (max-width: 400px) {
.ifram{
height: auto;
}
}

46
Lab5/src/pages/Page4.jsx Normal file
View File

@ -0,0 +1,46 @@
import { Container } from 'react-bootstrap';
import { Link } from 'react-router-dom';
import Image9 from '../assets/Image9.jpg';
import './Page4.css';
const Page4 = () => {
return (
<>
<Container fluid className="container-fluid wrapper mt-4">
<div className="container">
<Link to="/page3">
<img className="img223 w-100" src={Image9} alt="banner" />
</Link>
<div className="textus mt-2">
<p> Контактные данные </p>
</div>
<div className="textus">
<p> +7(909)-985-87-54</p>
<p> +7(909)-657-82-94</p>
<p> +7(909)-247-47-11</p>
</div>
<div className="textus">
<p> <i> E-mail </i> </p>
</div>
<div className="textus">
<p> Ulrent@mail.ru</p>
<p> Ulrent73@yandex.</p>
<p> RussianRent@mail.ru</p>
</div>
<div className="div d-flex justify-content-center">
<iframe src="https://yandex.ru/map-widget/v1/?um=constructor%3A0643c92cbdf3809080e5dfb2804b473ea00af31cfabe6fee08676c59d8675f01&amp;source=constructor" className="ifram w-75 mb-4"></iframe>
</div>
</div>
</Container>
</>
);
};
export default Page4;

68
Lab5/src/pages/Page5.css Normal file
View File

@ -0,0 +1,68 @@
.slide1{
color:aqua
}
.Slide {
background-color: white;
}
.textus1{
font-size: 28px;
color: white;
}
@media(max-width: 1200px) {
.textus1{
font-size: 24px;
}
}
@media(max-width: 1100px) {
.textus1{
font-size: 20px;
}
}
@media(max-width: 1000px) {
.textus1{
font-size: 16px;
}
}
@media(max-width: 900px) {
.textus1{
font-size: 14px;
}
}
@media(max-width: 500px) {
.textus1{
font-size: 32px;
}
.card-img-top1{
display: none;
}
}
@media(max-width: 412px) {
.textus1{
font-size: 32px;
}
.card-img-top1{
display: table;
}
}
@media(max-width: 360px) {
.textus1{
font-size: 28px;
}
}
@media(max-width: 270px) {
.textus1{
font-size: 18px;
}
}

51
Lab5/src/pages/Page5.jsx Normal file
View File

@ -0,0 +1,51 @@
import PropTypes from 'prop-types';
import { Container } from 'react-bootstrap';
import Carousel from 'react-bootstrap/Carousel';
import CartAdvert from '../components/advert/CartAdvert.jsx';
import Image6 from '../assets/Image6.jpg';
import Image7 from '../assets/Image7.jpg';
import Image9 from '../assets/Image9.jpg';
import './Page5.css';
const Page5 = () => {
return (
<>
<Container fluid></Container>
<article>
<div className="row mb-5 mx-auto w-100">
<CartAdvert/>
</div>
<div className="row margo me-4 ms-4 mt-5 mb-3 mx-auto">
<Carousel data-bs-theme="dark">
<Carousel.Item>
<img className="d-block w-100" src={Image7} alt="First slide"/>
<Carousel.Caption>
<div className='slide1'> <h5>First slide label</h5> </div>
</Carousel.Caption>
</Carousel.Item>
<Carousel.Item>
<img className="d-block w-100" src={Image9} alt="Second slide"/>
<Carousel.Caption>
<div className='slide1'> <h5>Second slide label</h5> </div>
</Carousel.Caption>
</Carousel.Item>
<Carousel.Item>
<img className="d-block w-100" src={Image6} alt="Third slide"/>
<Carousel.Caption>
<div className='slide1'> <h5>Third slide label</h5> </div>
</Carousel.Caption>
</Carousel.Item>
</Carousel>
</div>
</article>
</>
);
};
Page5.propTypes = {
index: PropTypes.number,
line: PropTypes.object,
};
export default Page5;

View File

@ -0,0 +1,12 @@
import { useParams } from 'react-router-dom';
import LinesForm from '../components/lines/form/LinesForm.jsx';
const PageEdit = () => {
const { id } = useParams();
return (
<LinesForm id={id} />
);
};
export default PageEdit;

View File

@ -0,0 +1,68 @@
body{
background-color: #85DADA;
}
.btnmain{
background-color: white;
}
img {
height: auto;
/* max-width: 100%; */
}
.textlink{
color: red;
}
/* .col-8{
width: 200px;
} */
.img22{
height: 600px;
border-radius: 0px 120px;
}
@media(max-width: 600px) {
.img22{
width: 100px;
height:180px;
}
.img22{
width: 160px;
height: 210px;
}
}
@media (max-width: 450px){
.col1{
display: none;
}
.textlink{
font-size: 16px;
}
.col-8{
width: 100%;
}
.img22{
display: table; /*Отмена display: none*/
}
}
@media (max-width: 400px){
.col-8{
width: 100%;
justify-self: center;
}
.textlink{
font-size: 12px;
}
}
@media (max-width: 270px){
.img22{
display: table; /*Отмена display: none*/
}
}

View File

@ -0,0 +1,72 @@
import { Link, useNavigate } from 'react-router-dom';
import { Container, Row, Button } from 'react-bootstrap';
import Banner from '../components/banner/Banner.jsx';
import Image1 from '../assets/Image2.png';
import { GetUserId } from '../components/login/users/UserReducer';
import './PageMain.css';
const PageMain = () => {
const ForwardGo = useNavigate();
const GoSign = () => {
ForwardGo('/SignIn');
};
const GoLog = () => {
ForwardGo('/LogIn');
};
const id = GetUserId();
console.log(id);
const image = [Image1];
return (
<>
<Container fluid className='container-fluid p-4 wrapper flex-shrink-0 p-0'>
<Row>
<div className="col-8 pe-5 ps-5">
<div className="row">
<div className="col col1">
<Banner />
</div>
<div className="col col1">
<Banner />
<div className="pt-5"> </div>
</div>
<div className="col col1">
<Banner />
</div>
</div>
<div className="flex-column w-100 mx-auto">
<div className="pb-4 pe-4">
<Button type="button" onClick={GoLog} className="btnmain btn-default btn-lg w-100 pt-3 pb-3">
<Link to="LogIn" className='textlink'>Войти</Link>
</Button>
</div>
<div className="pb-4 pe-4">
<Button type="button" onClick={GoSign} className="btnmain btn-default btn-lg w-100 pt-3 pb-3">
<Link to="SignIn" className='textlink' target='_blank'>Регистрация</Link>
</Button>
</div>
</div>
</div>
<div className="col">
<div className='ms-3' >
<img className="img22 w-100 h-100" src={image} alt="banner" />
</div >
</div>
</Row>
</Container>
</>
);
};
export default PageMain;

View File

@ -0,0 +1,5 @@
.TitleMyBulletin{
color: white;
font-size: 32px;
text-align: center;
}

View File

@ -0,0 +1,12 @@
import Lines from '../components/lines/tableuser/Lines.jsx';
import './PageMyBulletin.css';
const pageMyBulletin = () => {
return (
<>
<Lines />
</>
);
};
export default pageMyBulletin;

16
Lab5/src/pages/SignIn.css Normal file
View File

@ -0,0 +1,16 @@
.imgSign {
display: block;
height: auto;
width: 100%;
height: auto;
}
@media (max-width: 500px) {
.imgSign{
display: none;
}
.col-7{
width: 100%;
}
}

34
Lab5/src/pages/SignIn.jsx Normal file
View File

@ -0,0 +1,34 @@
import { useParams } from 'react-router-dom';
import { Container, Row } from 'react-bootstrap';
import LinesFormSign from '../components/registration/formSign/LinesFormSign.jsx';
import Image5 from '../assets/Image5.png';
import './SignIn.css';
const SignIn = () => {
const { id } = useParams();
return (
<Container fluid className='container-fluid wrapper mb-5'>
<div className="TitleLogin mb-4">
<p> Регистрация </p>
</div>
<Row>
<div className='col-7'>
<div className="row justify-content-center">
<LinesFormSign id={id} />
</div>
</div>
<div className="col">
<div className="col-md-10 offset">
<img className="imgSign" src={Image5} alt="banner" />
</div>
</div>
</Row>
</Container>
);
};
export default SignIn;