Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
25469177e9 | ||
| 4249a0253e |
65
Account.html
Normal file
65
Account.html
Normal file
@@ -0,0 +1,65 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="ru">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0" />
|
||||
<title>Интернет-магазин: ЛК</title>
|
||||
<link rel="stylesheet" href="css/style.css"/>
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons/font/bootstrap-icons.css">
|
||||
</head>
|
||||
<body>
|
||||
<header">
|
||||
<div class="d-block mt-3 ms-3">
|
||||
<img src="images/logo.jpg" alt="Название магазина" class="me-3" style="width: 200px; height: auto;">
|
||||
<a href="newSite.html" class="text-decoration-none text-dark m-1"><h1 class="display-4 h3 mt-3"><b>Название магазина</b></h1></a>
|
||||
</div>
|
||||
<navbar>
|
||||
<div class="dropdown">
|
||||
<button class="btn btn-primary dropdown-toggle" type="button" id="navigationDropdown" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
Навигация
|
||||
</button>
|
||||
<ul class="dropdown-menu" aria-labelledby="navigationDropdown">
|
||||
<li><a class="dropdown-item d-flex justify-content-between align-items-center" href="Account.html">Личный кабинет<i class="bi bi-person-circle ms-2"></i></a></li>
|
||||
<li><a class="dropdown-item d-flex justify-content-between align-items-center" href="Basket.html">Корзина<i class="bi bi-cart4 ms-2"></i></a></li>
|
||||
<li><a class="dropdown-item d-flex justify-content-between align-items-center" href="Order.html">Заказы<i class="bi bi-receipt ms-2"></i></a></li>
|
||||
<li><a class="dropdown-item d-flex justify-content-between align-items-center" href="Favorites.html">Избранное<i class="bi bi-heart-fill ms-2"></i></a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</navbar>
|
||||
</header>
|
||||
<div class="container mt-5">
|
||||
<div class="card text-center mx-auto" style="max-width: 400px; max-height: 400px;">
|
||||
<img src="images/бананы.jpg" class="card-img-top" alt="Профиль" style="width: 100%; height: 300px; object-fit: cover;">
|
||||
<div class="card-body">
|
||||
<h3 class="card-title">Имя Фамилия</h3>
|
||||
<p class="card-text">Описание</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<footer class="container mt-5">
|
||||
<div class="bg-light p-4">
|
||||
<h5>Помощь:</h5>
|
||||
<div class="d-flex flex-wrap">
|
||||
<div class="d-flex align-items-center me-4 mb-3">
|
||||
<i class="bi bi-telephone-fill me-2"></i>
|
||||
<a href="#" class="text-decoration-none text-dark">8 (800)-555-35-35</a>
|
||||
</div>
|
||||
<div class="d-flex align-items-center me-4 mb-3">
|
||||
<img src="images/vk.png" alt="VK" class="me-2" style="width: 24px; height: 24px;">
|
||||
<a href="https://vk.com/howmakesite_nn?from=search" target="_blank" class="text-decoration-none text-dark">vk.com</a>
|
||||
</div>
|
||||
<div class="d-flex align-items-center me-4 mb-3">
|
||||
<img src="images/telegram.png" alt="Telegram" class="me-2" style="width: 24px; height: 24px;">
|
||||
<a href="#" class="text-decoration-none text-dark">tg.me</a>
|
||||
</div>
|
||||
<div class="d-flex align-items-center mb-3">
|
||||
<img src="images/gmail.png" alt="Gmail" class="me-2" style="width: 24px; height: 24px;">
|
||||
<a href="mailto:ozon-zon-zon@mail.joke" class="text-decoration-none text-dark">ozon-zon-zon@mail.joke</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-YvpcrYf0tY3lHB60NNkmXc5s9fDVZLESaAA55NDzOxhy9GkcIdslK1eN7N6jIeHz" crossorigin="anonymous"></script>
|
||||
</body>
|
||||
</html>
|
||||
80
Basket.html
Normal file
80
Basket.html
Normal file
@@ -0,0 +1,80 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="ru">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0" />
|
||||
<title>Интернет-магазин: Корзина</title>
|
||||
<link rel="stylesheet" href="css/style.css"/>
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons/font/bootstrap-icons.css">
|
||||
</head>
|
||||
<body>
|
||||
<header">
|
||||
<div class="d-block mt-3 ms-3">
|
||||
<img src="images/logo.jpg" alt="Название магазина" class="me-3" style="width: 200px; height: auto;">
|
||||
<a href="newSite.html" class="text-decoration-none text-dark m-1"><h1 class="display-4 h3 mt-3"><b>Название магазина</b></h1></a>
|
||||
</div>
|
||||
<navbar>
|
||||
<div class="dropdown">
|
||||
<button class="btn btn-primary dropdown-toggle" type="button" id="navigationDropdown" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
Навигация
|
||||
</button>
|
||||
<ul class="dropdown-menu" aria-labelledby="navigationDropdown">
|
||||
<li><a class="dropdown-item d-flex justify-content-between align-items-center" href="Account.html">Личный кабинет<i class="bi bi-person-circle ms-2"></i></a></li>
|
||||
<li><a class="dropdown-item d-flex justify-content-between align-items-center" href="Basket.html">Корзина<i class="bi bi-cart4 ms-2"></i></a></li>
|
||||
<li><a class="dropdown-item d-flex justify-content-between align-items-center" href="Order.html">Заказы<i class="bi bi-receipt ms-2"></i></a></li>
|
||||
<li><a class="dropdown-item d-flex justify-content-between align-items-center" href="Favorites.html">Избранное<i class="bi bi-heart-fill ms-2"></i></a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</navbar>
|
||||
</header>
|
||||
<main class="container d-flex justify-content-center align-items-center" style="min-height: 60vh;">
|
||||
<div class="card p-4 shadow" style="min-width: 60vw;">
|
||||
<h2 class="text-center">Корзина</h2>
|
||||
<ul class="list-group list-group-flush">
|
||||
<li class="list-group-item d-flex align-items-center">
|
||||
<img src="images/glasses.jpg" alt="Очки" style="width: 100px; height: 100px;" class="me-3">
|
||||
Очки <span class="ms-auto">349 руб.</span>
|
||||
</li>
|
||||
<li class="list-group-item d-flex align-items-center">
|
||||
<img src="images/chery.jpg" alt="Chery Tiggo" style="width: 100px; height: 100px;" class="me-3">
|
||||
Chery Tiggo 7 Pro Max <span class="ms-auto">5 руб.</span>
|
||||
</li>
|
||||
<li class="list-group-item d-flex align-items-center">
|
||||
<img src="images/vanadiy.jpg" alt="Ванадий" style="width: 100px; height: 100px;" class="me-3">
|
||||
Ванадий <span class="ms-auto">2099 руб.</span>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="text-center mt-3">
|
||||
<a href="https://xn----7sbon6aucai8a.xn--p1ai/wa-data/public/shop/products/98/27/2798/images/6060/6060.970.jpg" target="_blank" class="btn btn-success w-100">
|
||||
Оплатить
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
<footer class="container mt-5">
|
||||
<div class="bg-light p-4">
|
||||
<h5>Помощь:</h5>
|
||||
<div class="d-flex flex-wrap">
|
||||
<div class="d-flex align-items-center me-4 mb-3">
|
||||
<i class="bi bi-telephone-fill me-2"></i>
|
||||
<a href="#" class="text-decoration-none text-dark">8 (800)-555-35-35</a>
|
||||
</div>
|
||||
<div class="d-flex align-items-center me-4 mb-3">
|
||||
<img src="images/vk.png" alt="VK" class="me-2" style="width: 24px; height: 24px;">
|
||||
<a href="https://vk.com/howmakesite_nn?from=search" target="_blank" class="text-decoration-none text-dark">vk.com</a>
|
||||
</div>
|
||||
<div class="d-flex align-items-center me-4 mb-3">
|
||||
<img src="images/telegram.png" alt="Telegram" class="me-2" style="width: 24px; height: 24px;">
|
||||
<a href="#" class="text-decoration-none text-dark">tg.me</a>
|
||||
</div>
|
||||
<div class="d-flex align-items-center mb-3">
|
||||
<img src="images/gmail.png" alt="Gmail" class="me-2" style="width: 24px; height: 24px;">
|
||||
<a href="mailto:ozon-zon-zon@mail.joke" class="text-decoration-none text-dark">ozon-zon-zon@mail.joke</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-YvpcrYf0tY3lHB60NNkmXc5s9fDVZLESaAA55NDzOxhy9GkcIdslK1eN7N6jIeHz" crossorigin="anonymous"></script>
|
||||
</body>
|
||||
</html>
|
||||
79
Favorites.html
Normal file
79
Favorites.html
Normal file
@@ -0,0 +1,79 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="ru">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0" />
|
||||
<title>Интернет-магазин: Избранное</title>
|
||||
<link rel="stylesheet" href="css/style.css"/>
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons/font/bootstrap-icons.css">
|
||||
</head>
|
||||
<body>
|
||||
<header">
|
||||
<div class="d-block mt-3 ms-3">
|
||||
<img src="images/logo.jpg" alt="Название магазина" class="me-3" style="width: 200px; height: auto;">
|
||||
<a href="newSite.html" class="text-decoration-none text-dark m-1"><h1 class="display-4 h3 mt-3"><b>Название магазина</b></h1></a>
|
||||
</div>
|
||||
<navbar>
|
||||
<div class="dropdown">
|
||||
<button class="btn btn-primary dropdown-toggle" type="button" id="navigationDropdown" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
Навигация
|
||||
</button>
|
||||
<ul class="dropdown-menu" aria-labelledby="navigationDropdown">
|
||||
<li><a class="dropdown-item d-flex justify-content-between align-items-center" href="Account.html">Личный кабинет<i class="bi bi-person-circle ms-2"></i></a></li>
|
||||
<li><a class="dropdown-item d-flex justify-content-between align-items-center" href="Basket.html">Корзина<i class="bi bi-cart4 ms-2"></i></a></li>
|
||||
<li><a class="dropdown-item d-flex justify-content-between align-items-center" href="Order.html">Заказы<i class="bi bi-receipt ms-2"></i></a></li>
|
||||
<li><a class="dropdown-item d-flex justify-content-between align-items-center" href="Favorites.html">Избранное<i class="bi bi-heart-fill ms-2"></i></a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</navbar>
|
||||
</header>
|
||||
<div class="container mt-4">
|
||||
<h2 class="mb-4">Избранное</h2>
|
||||
<div class="row row-cols-1 row-cols-md-2 g-4">
|
||||
<div class="col">
|
||||
<div class="card mx-auto" style="width: 70%;">
|
||||
<img src="images/masha.jpg" class="card-img-top" alt="Женщина" style="width: 100%; height: 300px; object-fit: cover;">
|
||||
<div class="card-body text-center">
|
||||
<h5 class="card-title">Женщина</h5>
|
||||
<p class="card-text">бесценна</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col">
|
||||
<div class="card mx-auto" style="width: 70%;">
|
||||
<img src="images/screwdriver.jpg" class="card-img-top" alt="Отвертка" style="width: 100%; height: 300px; object-fit: cover;">
|
||||
<div class="card-body text-center">
|
||||
<h5 class="card-title">Отвертка</h5>
|
||||
<p class="card-text">219 руб</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<footer class="container mt-5">
|
||||
<div class="bg-light p-4">
|
||||
<h5>Помощь:</h5>
|
||||
<div class="d-flex flex-wrap">
|
||||
<div class="d-flex align-items-center me-4 mb-3">
|
||||
<i class="bi bi-telephone-fill me-2"></i>
|
||||
<a href="#" class="text-decoration-none text-dark">8 (800)-555-35-35</a>
|
||||
</div>
|
||||
<div class="d-flex align-items-center me-4 mb-3">
|
||||
<img src="images/vk.png" alt="VK" class="me-2" style="width: 24px; height: 24px;">
|
||||
<a href="https://vk.com/howmakesite_nn?from=search" target="_blank" class="text-decoration-none text-dark">vk.com</a>
|
||||
</div>
|
||||
<div class="d-flex align-items-center me-4 mb-3">
|
||||
<img src="images/telegram.png" alt="Telegram" class="me-2" style="width: 24px; height: 24px;">
|
||||
<a href="#" class="text-decoration-none text-dark">tg.me</a>
|
||||
</div>
|
||||
<div class="d-flex align-items-center mb-3">
|
||||
<img src="images/gmail.png" alt="Gmail" class="me-2" style="width: 24px; height: 24px;">
|
||||
<a href="mailto:ozon-zon-zon@mail.joke" class="text-decoration-none text-dark">ozon-zon-zon@mail.joke</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-YvpcrYf0tY3lHB60NNkmXc5s9fDVZLESaAA55NDzOxhy9GkcIdslK1eN7N6jIeHz" crossorigin="anonymous"></script>
|
||||
</body>
|
||||
</html>
|
||||
101
Order.html
Normal file
101
Order.html
Normal file
@@ -0,0 +1,101 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="ru">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0" />
|
||||
<title>Интернет-магазин: Заказы</title>
|
||||
<link rel="stylesheet" href="css/style.css"/>
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons/font/bootstrap-icons.css">
|
||||
</head>
|
||||
<body>
|
||||
<header">
|
||||
<div class="d-block mt-3 ms-3">
|
||||
<img src="images/logo.jpg" alt="Название магазина" class="me-3" style="width: 200px; height: auto;">
|
||||
<a href="newSite.html" class="text-decoration-none text-dark m-1"><h1 class="display-4 h3 mt-3"><b>Название магазина</b></h1></a>
|
||||
</div>
|
||||
<navbar>
|
||||
<div class="dropdown">
|
||||
<button class="btn btn-primary dropdown-toggle" type="button" id="navigationDropdown" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
Навигация
|
||||
</button>
|
||||
<ul class="dropdown-menu" aria-labelledby="navigationDropdown">
|
||||
<li><a class="dropdown-item d-flex justify-content-between align-items-center" href="Account.html">Личный кабинет<i class="bi bi-person-circle ms-2"></i></a></li>
|
||||
<li><a class="dropdown-item d-flex justify-content-between align-items-center" href="Basket.html">Корзина<i class="bi bi-cart4 ms-2"></i></a></li>
|
||||
<li><a class="dropdown-item d-flex justify-content-between align-items-center" href="Order.html">Заказы<i class="bi bi-receipt ms-2"></i></a></li>
|
||||
<li><a class="dropdown-item d-flex justify-content-between align-items-center" href="Favorites.html">Избранное<i class="bi bi-heart-fill ms-2"></i></a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</navbar>
|
||||
</header>
|
||||
<div class="container mt-4">
|
||||
<h1 class="text-center">Заказы</h1>
|
||||
<div class="row">
|
||||
<!-- Заказы в процессе -->
|
||||
<div class="col-md-6">
|
||||
<div class="card shadow-sm">
|
||||
<div class="card-header bg-warning text-dark">
|
||||
<h2 class="h5 m-0">В процессе</h2>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<ul class="list-group list-group-flush">
|
||||
<li class="list-group-item d-flex align-items-center mb-2">
|
||||
<img src="images/spoon.jpg" class="me-2" style="min-width: 90px;"> Ложка
|
||||
</li>
|
||||
<li class="list-group-item d-flex align-items-center mb-2">
|
||||
<img src="images/fork.jpg" class="me-2" style="min-width: 90px;"> Вилка
|
||||
</li>
|
||||
<li class="list-group-item d-flex align-items-center">
|
||||
<img src="images/knife.jpg" class="me-2" style="min-width: 90px;"> Нож
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Завершённые заказы -->
|
||||
<div class="col-md-6">
|
||||
<div class="card shadow-sm">
|
||||
<div class="card-header bg-success text-white">
|
||||
<h2 class="h5 m-0">Завершённые</h2>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<ul class="list-group list-group-flush">
|
||||
<li class="list-group-item d-flex align-items-center mb-2">
|
||||
<img src="images/iron.jpg" class="me-2" style="min-width: 90px;"> Утюг
|
||||
</li>
|
||||
<li class="list-group-item d-flex align-items-center mb-2">
|
||||
<img src="images/bananas.jpg" class="me-2" style="min-width: 90px;"> Бананы
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<footer class="container mt-5">
|
||||
<div class="bg-light p-4">
|
||||
<h5>Помощь:</h5>
|
||||
<div class="d-flex flex-wrap">
|
||||
<div class="d-flex align-items-center me-4 mb-3">
|
||||
<i class="bi bi-telephone-fill me-2"></i>
|
||||
<a href="#" class="text-decoration-none text-dark">8 (800)-555-35-35</a>
|
||||
</div>
|
||||
<div class="d-flex align-items-center me-4 mb-3">
|
||||
<img src="images/vk.png" alt="VK" class="me-2" style="width: 24px; height: 24px;">
|
||||
<a href="https://vk.com/howmakesite_nn?from=search" target="_blank" class="text-decoration-none text-dark">vk.com</a>
|
||||
</div>
|
||||
<div class="d-flex align-items-center me-4 mb-3">
|
||||
<img src="images/telegram.png" alt="Telegram" class="me-2" style="width: 24px; height: 24px;">
|
||||
<a href="#" class="text-decoration-none text-dark">tg.me</a>
|
||||
</div>
|
||||
<div class="d-flex align-items-center mb-3">
|
||||
<img src="images/gmail.png" alt="Gmail" class="me-2" style="width: 24px; height: 24px;">
|
||||
<a href="mailto:ozon-zon-zon@mail.joke" class="text-decoration-none text-dark">ozon-zon-zon@mail.joke</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-YvpcrYf0tY3lHB60NNkmXc5s9fDVZLESaAA55NDzOxhy9GkcIdslK1eN7N6jIeHz" crossorigin="anonymous"></script>
|
||||
</body>
|
||||
</html>
|
||||
90
css/style.css
Normal file
90
css/style.css
Normal file
@@ -0,0 +1,90 @@
|
||||
/* Общие стили */
|
||||
body {
|
||||
background-color: #edf7f6;
|
||||
}
|
||||
|
||||
/* Заголовки */
|
||||
h2 {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/* Изображения */
|
||||
img {
|
||||
width: 180px;
|
||||
height: 150px;
|
||||
margin-right: 10px;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
/* Ссылки */
|
||||
a {
|
||||
text-decoration: none;
|
||||
color: black;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/* Навигация */
|
||||
navbar {
|
||||
position: fixed;
|
||||
top: 40px;
|
||||
right: 20px;
|
||||
z-index: 3;
|
||||
}
|
||||
|
||||
/* Контент */
|
||||
.goods img {
|
||||
width: 250px;
|
||||
height: 250px;
|
||||
}
|
||||
|
||||
/* Заказы */
|
||||
.inProcess h2 {
|
||||
background-color: yellow;
|
||||
}
|
||||
|
||||
.done h2 {
|
||||
background-color: green;
|
||||
}
|
||||
|
||||
/* Кнопка оплаты */
|
||||
.buy {
|
||||
position: fixed;
|
||||
bottom: 20px;
|
||||
right: 20px;
|
||||
background-color: greenyellow;
|
||||
text-align: center;
|
||||
border: 2px solid black;
|
||||
border-radius: 10px;
|
||||
width: 110px;
|
||||
height: 35px;
|
||||
transition: background-color 0.3s ease-in-out;
|
||||
}
|
||||
|
||||
.buy:hover {
|
||||
background-color: lightgreen;
|
||||
}
|
||||
|
||||
/* Личный кабинет */
|
||||
.account img {
|
||||
border: 3px solid black;
|
||||
}
|
||||
|
||||
.recomended .card {
|
||||
transition: transform 0.3s ease, box-shadow 0.3s ease;
|
||||
}
|
||||
|
||||
.recomended .card:hover {
|
||||
transform: translateY(-5px) scale(1.02);
|
||||
}
|
||||
|
||||
/* Адаптивность */
|
||||
@media only screen and (min-width: 400px) {
|
||||
body {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.buy {
|
||||
width: 200px;
|
||||
height: 60px;
|
||||
}
|
||||
}
|
||||
74
db.json
74
db.json
@@ -1,74 +0,0 @@
|
||||
{
|
||||
"products": [
|
||||
{
|
||||
"id": "1a54",
|
||||
"name": "новый товар",
|
||||
"price": 102,
|
||||
"image": "images/fork.jpg"
|
||||
},
|
||||
{
|
||||
"id": "f4f8",
|
||||
"name": "товарчик",
|
||||
"price": 111,
|
||||
"image": "images/chery.jpg"
|
||||
},
|
||||
{
|
||||
"id": "0fda",
|
||||
"name": "ложка",
|
||||
"price": 48,
|
||||
"image": "images/bananas.jpg"
|
||||
}
|
||||
],
|
||||
"basket": [
|
||||
{
|
||||
"id": "0fda",
|
||||
"name": "ложка",
|
||||
"price": 48,
|
||||
"image": "images/bananas.jpg"
|
||||
}
|
||||
],
|
||||
"favorites": [
|
||||
{
|
||||
"id": "1a54",
|
||||
"name": "новый товар",
|
||||
"price": 102,
|
||||
"image": "images/fork.jpg"
|
||||
}
|
||||
],
|
||||
"orders": [
|
||||
{
|
||||
"id": "1",
|
||||
"items": [
|
||||
{
|
||||
"name": "Ложка",
|
||||
"image": "images/spoon.jpg"
|
||||
},
|
||||
{
|
||||
"name": "Вилка",
|
||||
"image": "images/fork.jpg"
|
||||
}
|
||||
],
|
||||
"status": "in-process"
|
||||
},
|
||||
{
|
||||
"id": "2",
|
||||
"items": [
|
||||
{
|
||||
"name": "Утюг",
|
||||
"image": "images/iron.jpg"
|
||||
},
|
||||
{
|
||||
"name": "Бананы",
|
||||
"image": "images/bananas.jpg"
|
||||
}
|
||||
],
|
||||
"status": "completed"
|
||||
}
|
||||
],
|
||||
"profile": {
|
||||
"id": 1,
|
||||
"firstName": "Иван",
|
||||
"lastName": "Иванов",
|
||||
"image": "images/бананы.jpg"
|
||||
}
|
||||
}
|
||||
15
index.html
15
index.html
@@ -1,15 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="ru">
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0" />
|
||||
<title>Интернет-магазин</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
<script type="module" src="/src/index.jsx"></script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
191
newSite.html
Normal file
191
newSite.html
Normal file
@@ -0,0 +1,191 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="ru">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0" />
|
||||
<title>Интернет-магазин</title>
|
||||
<link rel="stylesheet" href="css/style.css"/>
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons/font/bootstrap-icons.css">
|
||||
</head>
|
||||
<body>
|
||||
<header">
|
||||
<div class="d-block mt-3 ms-3">
|
||||
<img src="images/logo.jpg" alt="Название магазина" class="me-3" style="width: 200px; height: auto;">
|
||||
<a href="newSite.html" class="text-decoration-none text-dark m-1"><h1 class="display-4 h3 mt-3"><b>Название магазина</b></h1></a>
|
||||
</div>
|
||||
<navbar>
|
||||
<div class="dropdown">
|
||||
<button class="btn btn-primary dropdown-toggle" type="button" id="navigationDropdown" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
Навигация
|
||||
</button>
|
||||
<ul class="dropdown-menu" aria-labelledby="navigationDropdown">
|
||||
<li><a class="dropdown-item d-flex justify-content-between align-items-center" href="Account.html">Личный кабинет<i class="bi bi-person-circle ms-2"></i></a></li>
|
||||
<li><a class="dropdown-item d-flex justify-content-between align-items-center" href="Basket.html">Корзина<i class="bi bi-cart4 ms-2"></i></a></li>
|
||||
<li><a class="dropdown-item d-flex justify-content-between align-items-center" href="Order.html">Заказы<i class="bi bi-receipt ms-2"></i></a></li>
|
||||
<li><a class="dropdown-item d-flex justify-content-between align-items-center" href="Favorites.html">Избранное<i class="bi bi-heart-fill ms-2"></i></a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</navbar>
|
||||
</header>
|
||||
<main class="container">
|
||||
<div class="card mb-5 border-primary">
|
||||
<div class="card-header bg-primary text-white">
|
||||
<h3 class="mb-0">Добавить новый товар</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<form id="addProductForm" class="row g-3">
|
||||
<div class="col-md-6">
|
||||
<label for="productName" class="form-label">Название товара</label>
|
||||
<input type="text" class="form-control" id="productName" required>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label for="productPrice" class="form-label">Цена (руб)</label>
|
||||
<input type="number" class="form-control" step="10" id="productPrice" required>
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<label for="productImage" class="form-label">Изображение товара</label>
|
||||
<input type="file" class="form-control" id="productImage" accept="image/*" required>
|
||||
</div>
|
||||
<div class="col-12 d-flex justify-content-end">
|
||||
<button type="submit" class="btn btn-success">
|
||||
<i class="bi bi-plus-circle"></i> Добавить товар
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h2 class="text-center my-3">Рекомендуемые товары:</h2>
|
||||
<div class="row row-cols-1 row-cols-md-3 g-4 recomended">
|
||||
<div class="col">
|
||||
<div class="card h-100">
|
||||
<img src="images/iron.jpg" class="card-img-top" alt="Утюг" style="width: 100%; height: 300%; object-fit: cover;">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">Утюг</h5>
|
||||
<p class="card-text">2600 руб</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col">
|
||||
<div class="card h-100">
|
||||
<img src="images/child.jpg" class="card-img-top" alt="Ребёнок" style="width: 100%; height: 300%; object-fit: cover;">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">Ребёнок</h5>
|
||||
<p class="card-text">2600 без костей</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col">
|
||||
<div class="card h-100">
|
||||
<img src="images/screwdriver.jpg" class="card-img-top" alt="Отвертка" style="width: 100%; height: 300%; object-fit: cover;">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">Отвертка</h5>
|
||||
<p class="card-text">620 руб</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col">
|
||||
<div class="card h-100">
|
||||
<img src="images/skateboard.jpg" class="card-img-top" alt="Скейтборд" style="width: 100%; height: 300%; object-fit: cover;">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">Скейтборд</h5>
|
||||
<p class="card-text">4300 руб</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col">
|
||||
<div class="card h-100">
|
||||
<img src="images/bananas.jpg" class="card-img-top" alt="Бананы" style="width: 100%; height: 300%; object-fit: cover;">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">Бананы</h5>
|
||||
<p class="card-text">120 руб</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
<footer class="container mt-5">
|
||||
<div class="bg-light p-4">
|
||||
<h5>Помощь:</h5>
|
||||
<div class="d-flex flex-wrap">
|
||||
<div class="d-flex align-items-center me-4 mb-3">
|
||||
<i class="bi bi-telephone-fill me-2"></i>
|
||||
<a href="#" class="text-decoration-none text-dark">8 (800)-555-35-35</a>
|
||||
</div>
|
||||
<div class="d-flex align-items-center me-4 mb-3">
|
||||
<img src="images/vk.png" alt="VK" class="me-2" style="width: 24px; height: 24px;">
|
||||
<a href="https://vk.com/howmakesite_nn?from=search" target="_blank" class="text-decoration-none text-dark">vk.com</a>
|
||||
</div>
|
||||
<div class="d-flex align-items-center me-4 mb-3">
|
||||
<img src="images/telegram.png" alt="Telegram" class="me-2" style="width: 24px; height: 24px;">
|
||||
<a href="#" class="text-decoration-none text-dark">tg.me</a>
|
||||
</div>
|
||||
<div class="d-flex align-items-center mb-3">
|
||||
<img src="images/gmail.png" alt="Gmail" class="me-2" style="width: 24px; height: 24px;">
|
||||
<a href="mailto:ozon-zon-zon@mail.joke" class="text-decoration-none text-dark">ozon-zon-zon@mail.joke</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="text-center mt-4">
|
||||
<img src="images/бананы.jpg" alt="Бананы" class="img-fluid">
|
||||
</div>
|
||||
</footer>
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-YvpcrYf0tY3lHB60NNkmXc5s9fDVZLESaAA55NDzOxhy9GkcIdslK1eN7N6jIeHz" crossorigin="anonymous"></script>
|
||||
<script>
|
||||
document.getElementById('addProductForm').addEventListener('submit', function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
const name = document.getElementById('productName').value;
|
||||
const price = document.getElementById('productPrice').value;
|
||||
const imageInput = document.getElementById('productImage');
|
||||
|
||||
// Проверка выбора файла
|
||||
if (imageInput.files.length === 0) {
|
||||
alert('Пожалуйста, выберите изображение!');
|
||||
return;
|
||||
}
|
||||
|
||||
var text = document.getElementById('productName').value;
|
||||
if(!text.match(/^[А-Яа-яЁё]+(?: [А-Яа-яЁё]+)*$/)){
|
||||
alert('Пожалуйста, введите корректное название на русском!');
|
||||
return;
|
||||
}
|
||||
|
||||
const file = imageInput.files[0];
|
||||
|
||||
// Проверка размера файла (до 5MB)
|
||||
if (file.size > 5 * 1024 * 1024) {
|
||||
alert('Файл слишком большой! Максимум 5MB.');
|
||||
return;
|
||||
}
|
||||
|
||||
// Создаем превью изображения
|
||||
const reader = new FileReader();
|
||||
|
||||
reader.onload = function(e) {
|
||||
const imageUrl = e.target.result;
|
||||
|
||||
// Создаем карточку товара
|
||||
const productCard = `
|
||||
<div class="col">
|
||||
<div class="card h-100">
|
||||
<img src="${imageUrl}" class="card-img-top" alt="${name}" style="width: 100%; height: 300%; object-fit: cover;">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">${name}</h5>
|
||||
<p class="card-text">${price} руб</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
document.querySelector('.row-cols-1').insertAdjacentHTML('afterbegin', productCard);
|
||||
alert('Товар успешно добавлен!');
|
||||
};
|
||||
|
||||
reader.readAsDataURL(file);
|
||||
this.reset();
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
1312
package-lock.json
generated
1312
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
21
package.json
21
package.json
@@ -3,35 +3,28 @@
|
||||
"version": "1.0.0",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"dev": "npm-run-all --parallel start json-server",
|
||||
"start": "vite",
|
||||
"build": "vite build",
|
||||
"server": "http-server -p 3000 ./dist/",
|
||||
"prod": "npm-run-all build server",
|
||||
"lint": "eslint …",
|
||||
"json-server": "json-server --watch db.json --port 5000"
|
||||
"lint": "eslint …"
|
||||
},
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"description": "",
|
||||
"dependencies": {
|
||||
"bootstrap": "5.3.3",
|
||||
"bootstrap-icons": "1.11.3",
|
||||
"react": "^19.1.0",
|
||||
"react-dom": "^19.1.0",
|
||||
"react-router-dom": "^7.6.0"
|
||||
"bootstrap":"5.3.3",
|
||||
"bootstrap-icons": "1.11.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@vitejs/plugin-react": "^4.4.1",
|
||||
"http-server": "14.1.1",
|
||||
"vite": "6.2.0",
|
||||
"npm-run-all": "4.1.5",
|
||||
"eslint": "8.56.0",
|
||||
"eslint-config-airbnb-base": "15.0.0",
|
||||
"eslint-config-prettier": "10.0.2",
|
||||
"eslint-plugin-html": "8.1.2",
|
||||
"eslint-plugin-import": "2.31.0",
|
||||
"eslint-plugin-prettier": "5.2.3",
|
||||
"http-server": "14.1.1",
|
||||
"json-server": "^1.0.0-beta.3",
|
||||
"npm-run-all": "4.1.5",
|
||||
"vite": "6.2.0"
|
||||
"eslint-plugin-html": "8.1.2"
|
||||
}
|
||||
}
|
||||
|
||||
26
src/App.jsx
26
src/App.jsx
@@ -1,26 +0,0 @@
|
||||
import React, { useState } from 'react';
|
||||
import { BrowserRouter, Routes, Route } from "react-router-dom";
|
||||
import Header from "./components/Header";
|
||||
import Footer from "./components/Footer";
|
||||
import MainPage from "./pages/MainPage";
|
||||
import BasketPage from "./pages/BasketPage";
|
||||
import FavoritesPage from "./pages/FavoritesPage";
|
||||
import OrderPage from "./pages/OrderPage";
|
||||
import AccountPage from "./pages/AccountPage";
|
||||
|
||||
export default function App() {
|
||||
|
||||
return (
|
||||
<BrowserRouter>
|
||||
<Header />
|
||||
<Routes>
|
||||
<Route path="/" element={<MainPage />} />
|
||||
<Route path="/basket" element={<BasketPage />} />
|
||||
<Route path="/favorites" element={<FavoritesPage />} />
|
||||
<Route path="/orders" element={<OrderPage />} />
|
||||
<Route path="/account" element={<AccountPage />} />
|
||||
</Routes>
|
||||
<Footer />
|
||||
</BrowserRouter>
|
||||
);
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
import React from "react";
|
||||
|
||||
export default function Footer() {
|
||||
return (
|
||||
<footer className="container mt-5">
|
||||
<div className="bg-light p-4">
|
||||
<h5>Помощь:</h5>
|
||||
<div className="d-flex flex-wrap">
|
||||
<div className="d-flex align-items-center me-4 mb-3">
|
||||
<i className="bi bi-telephone-fill me-2"></i>
|
||||
<a href="#" className="text-decoration-none text-dark">8 (800)-555-35-35</a>
|
||||
</div>
|
||||
<div className="d-flex align-items-center me-4 mb-3">
|
||||
<img src="images/vk.png" alt="VK" className="me-2" style={{ width: 24, height: 24 }} />
|
||||
<a href="https://vk.com/howmakesite_nn?from=search" target="_blank" className="text-decoration-none text-dark">vk.com</a>
|
||||
</div>
|
||||
<div className="d-flex align-items-center me-4 mb-3">
|
||||
<img src="images/telegram.png" alt="Telegram" className="me-2" style={{ width: 24, height: 24 }} />
|
||||
<a href="#" className="text-decoration-none text-dark">tg.me</a>
|
||||
</div>
|
||||
<div className="d-flex align-items-center mb-3">
|
||||
<img src="images/gmail.png" alt="Gmail" className="me-2" style={{ width: 24, height: 24 }} />
|
||||
<a href="mailto:ozon-zon-zon@mail.joke" className="text-decoration-none text-dark">ozon-zon-zon@mail.joke</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
);
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
import React from "react";
|
||||
import { Link } from "react-router-dom";
|
||||
|
||||
export default function Header() {
|
||||
return (
|
||||
<header>
|
||||
<div className="d-block mt-3 ms-3">
|
||||
<img src="images/logo.jpg" alt="Название магазина" className="me-3" style={{ width: 200, height: "auto" }} />
|
||||
<Link to="/" className="text-decoration-none text-dark m-1">
|
||||
<h1 className="display-4 h3 mt-3"><b>Название магазина</b></h1>
|
||||
</Link>
|
||||
</div>
|
||||
<nav>
|
||||
<div className="dropdown">
|
||||
<button className="btn btn-primary dropdown-toggle ms-3" type="button" id="navigationDropdown" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
Навигация
|
||||
</button>
|
||||
<ul className="dropdown-menu" aria-labelledby="navigationDropdown">
|
||||
<li><Link className="dropdown-item d-flex justify-content-between align-items-center" to="/account">Личный кабинет<i className="bi bi-person-circle ms-2"></i></Link></li>
|
||||
<li><Link className="dropdown-item d-flex justify-content-between align-items-center" to="/basket">Корзина<i className="bi bi-cart4 ms-2"></i></Link></li>
|
||||
<li><Link className="dropdown-item d-flex justify-content-between align-items-center" to="/orders">Заказы<i className="bi bi-receipt ms-2"></i></Link></li>
|
||||
<li><Link className="dropdown-item d-flex justify-content-between align-items-center" to="/favorites">Избранное<i className="bi bi-heart-fill ms-2"></i></Link></li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
</header>
|
||||
);
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
import React from 'react';
|
||||
|
||||
export default function ProductCard({ product, onEdit, onDelete, onAddToFavorites }) {
|
||||
return (
|
||||
<div className="col">
|
||||
<div className="card h-100">
|
||||
{product.image && (
|
||||
<img src={product.image} className="card-img-top" alt={product.name} style={{ height: 300, objectFit: 'cover' }} />
|
||||
)}
|
||||
<div className="card-body">
|
||||
<h5 className="card-title">{product.name}</h5>
|
||||
<p className="card-text">Цена: {product.price} ₽</p>
|
||||
<button className="btn btn-sm btn-outline-primary me-2" onClick={() => onEdit(product)}>Изменить</button>
|
||||
<button className="btn btn-sm btn-outline-danger me-2" onClick={() => onDelete(product.id)}>Удалить</button>
|
||||
<button className="btn btn-sm btn-outline-success" onClick={() => onAddToFavorites(product)}>
|
||||
<i className="bi bi-heart"></i> В избранное
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,72 +0,0 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
|
||||
export default function ProductForm({ initial, onSave, onCancel }) {
|
||||
const [form, setForm] = useState({ name: '', price: '', image: '' });
|
||||
|
||||
useEffect(() => {
|
||||
if (initial) {
|
||||
setForm({
|
||||
name: initial.name || '',
|
||||
price: initial.price || '',
|
||||
image: initial.image || ''
|
||||
});
|
||||
} else {
|
||||
setForm({ name: '', price: '', image: '' });
|
||||
}
|
||||
}, [initial]);
|
||||
|
||||
const handleChange = e => setForm({ ...form, [e.target.name]: e.target.value });
|
||||
|
||||
const handleSubmit = e => {
|
||||
e.preventDefault();
|
||||
onSave({ ...initial, name: form.name, price: Number(form.price), image: form.image });
|
||||
setForm({ name: '', price: '', image: '' });
|
||||
};
|
||||
|
||||
return (
|
||||
<form onSubmit={handleSubmit} className="card p-3 mb-4">
|
||||
<div className="mb-2">
|
||||
<label className="form-label">Название</label>
|
||||
<input
|
||||
name="name"
|
||||
value={form.name}
|
||||
onChange={handleChange}
|
||||
required
|
||||
className="form-control"
|
||||
/>
|
||||
</div>
|
||||
<div className="mb-2">
|
||||
<label className="form-label">Цена</label>
|
||||
<input
|
||||
name="price"
|
||||
value={form.price}
|
||||
onChange={handleChange}
|
||||
type="number"
|
||||
required
|
||||
className="form-control"
|
||||
/>
|
||||
</div>
|
||||
<div className="mb-2">
|
||||
<label className="form-label">Ссылка на картинку</label>
|
||||
<input
|
||||
name="image"
|
||||
value={form.image}
|
||||
onChange={handleChange}
|
||||
className="form-control"
|
||||
placeholder="Например: images/glasses.jpg или https://example.com/photo.jpg"
|
||||
/>
|
||||
</div>
|
||||
{form.image && (
|
||||
<div className="mb-2 text-center">
|
||||
<img
|
||||
src={form.image}
|
||||
alt="Превью"
|
||||
style={{ maxHeight: 120, objectFit: 'contain', maxWidth: "100%" }}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
<button type="submit" className="btn btn-primary mb-2" style={{ width: 'auto' }}>Сохранить</button>
|
||||
<button type="button" className="btn btn-secondary" style={{ width: 'auto' }} onClick={onCancel}>Отмена</button>
|
||||
</form>
|
||||
);
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
import React from 'react';
|
||||
import ProductCard from './ProductCard';
|
||||
|
||||
export default function ProductList({ products, onEdit, onDelete, onAddToFavorites }) {
|
||||
return (
|
||||
<div className="row row-cols-1 row-cols-md-3 g-4">
|
||||
{products.map(prod => (
|
||||
<ProductCard
|
||||
key={prod.id}
|
||||
product={prod}
|
||||
onEdit={onEdit}
|
||||
onDelete={onDelete}
|
||||
onAddToFavorites={onAddToFavorites}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
import { useState, useEffect } from "react";
|
||||
|
||||
export default function useBasket() {
|
||||
const [basket, setBasket] = useState([]);
|
||||
|
||||
useEffect(() => {
|
||||
fetch('http://localhost:5000/basket')
|
||||
.then(res => res.json())
|
||||
.then(setBasket);
|
||||
}, []);
|
||||
|
||||
const addToBasket = async (item) => {
|
||||
const res = await fetch('http://localhost:5000/basket', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(item)
|
||||
});
|
||||
const newItem = await res.json();
|
||||
setBasket([...basket, newItem]);
|
||||
};
|
||||
|
||||
const removeFromBasket = async (id) => {
|
||||
await fetch(`http://localhost:5000/basket/${id}`, { method: 'DELETE' });
|
||||
setBasket(basket.filter(item => item.id !== id));
|
||||
};
|
||||
|
||||
const clearBasket = async () => {
|
||||
for (let item of basket) {
|
||||
await fetch(`http://localhost:5000/basket/${item.id}`, { method: 'DELETE' });
|
||||
}
|
||||
setBasket([]);
|
||||
};
|
||||
|
||||
return { basket, addToBasket, removeFromBasket, clearBasket };
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
import { useState, useEffect } from "react";
|
||||
|
||||
export default function useFavorites() {
|
||||
const [favorites, setFavorites] = useState([]);
|
||||
|
||||
useEffect(() => {
|
||||
fetch('http://localhost:5000/favorites')
|
||||
.then(res => res.json())
|
||||
.then(setFavorites);
|
||||
}, []);
|
||||
|
||||
const addToFavorites = async (item) => {
|
||||
const res = await fetch('http://localhost:5000/favorites', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(item)
|
||||
});
|
||||
const newItem = await res.json();
|
||||
setFavorites([...favorites, newItem]);
|
||||
};
|
||||
|
||||
const removeFromFavorites = async (id) => {
|
||||
await fetch(`http://localhost:5000/favorites/${id}`, { method: 'DELETE' });
|
||||
setFavorites(favorites.filter(item => item.id !== id));
|
||||
};
|
||||
|
||||
return { favorites, addToFavorites, removeFromFavorites };
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
import { useState, useEffect } from "react";
|
||||
|
||||
export default function useOrders() {
|
||||
const [orders, setOrders] = useState([]);
|
||||
|
||||
useEffect(() => {
|
||||
fetch('http://localhost:5000/orders')
|
||||
.then(res => res.json())
|
||||
.then(setOrders);
|
||||
}, []);
|
||||
|
||||
const addOrder = async (order) => {
|
||||
const res = await fetch('http://localhost:5000/orders', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(order)
|
||||
});
|
||||
const newOrder = await res.json();
|
||||
setOrders([...orders, newOrder]);
|
||||
};
|
||||
|
||||
const inProcess = orders.filter(o => o.status === "in-process");
|
||||
const completed = orders.filter(o => o.status === "completed");
|
||||
|
||||
return { orders, addOrder, inProcess, completed };
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
|
||||
export default function useProducts() {
|
||||
const [products, setProducts] = useState([]);
|
||||
|
||||
useEffect(() => {
|
||||
fetch('http://localhost:5000/products')
|
||||
.then(res => res.json())
|
||||
.then(setProducts);
|
||||
}, []);
|
||||
|
||||
const add = async prod => {
|
||||
const res = await fetch('http://localhost:5000/products', {
|
||||
method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(prod)
|
||||
});
|
||||
const newProd = await res.json();
|
||||
setProducts([...products, newProd]);
|
||||
};
|
||||
|
||||
const update = async prod => {
|
||||
await fetch(`http://localhost:5000/products/${prod.id}`, {
|
||||
method: 'PUT', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(prod)
|
||||
});
|
||||
setProducts(products.map(p => p.id === prod.id ? prod : p));
|
||||
};
|
||||
|
||||
const remove = async id => {
|
||||
await fetch(`http://localhost:5000/products/${id}`, { method: 'DELETE' });
|
||||
setProducts(products.filter(p => p.id !== id));
|
||||
};
|
||||
|
||||
return { products, add, update, remove };
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
import { useState, useEffect } from "react";
|
||||
|
||||
export default function useProfile() {
|
||||
const [profile, setProfile] = useState(null);
|
||||
|
||||
useEffect(() => {
|
||||
fetch('http://localhost:5000/profile')
|
||||
.then(res => res.json())
|
||||
.then(setProfile);
|
||||
}, []);
|
||||
|
||||
const updateProfile = async (newProfile) => {
|
||||
// PATCH или PUT — по ситуации
|
||||
const res = await fetch('http://localhost:5000/profile', {
|
||||
method: 'PUT',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(newProfile)
|
||||
});
|
||||
const updated = await res.json();
|
||||
setProfile(updated);
|
||||
};
|
||||
|
||||
return { profile, updateProfile };
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
import React from "react";
|
||||
import { createRoot } from "react-dom/client";
|
||||
import App from "./App";
|
||||
import "bootstrap/dist/css/bootstrap.min.css";
|
||||
import 'bootstrap/dist/js/bootstrap.bundle.min.js';
|
||||
|
||||
const container = document.getElementById("root");
|
||||
createRoot(container).render(<App />);
|
||||
@@ -1,76 +0,0 @@
|
||||
import React, { useState } from "react";
|
||||
import useProfile from "../hooks/useProfile";
|
||||
|
||||
export default function AccountPage() {
|
||||
const { profile, updateProfile } = useProfile();
|
||||
const [showEdit, setShowEdit] = useState(false);
|
||||
const [form, setForm] = useState(null);
|
||||
|
||||
if (!profile) {
|
||||
return <div className="text-center">Загрузка...</div>;
|
||||
}
|
||||
|
||||
const handleEdit = () => {
|
||||
setForm(profile);
|
||||
setShowEdit(true);
|
||||
};
|
||||
|
||||
const handleChange = e => {
|
||||
setForm({ ...form, [e.target.name]: e.target.value });
|
||||
};
|
||||
|
||||
const handleSave = async e => {
|
||||
e.preventDefault();
|
||||
await updateProfile(form);
|
||||
setShowEdit(false);
|
||||
};
|
||||
|
||||
const handleCancel = () => setShowEdit(false);
|
||||
|
||||
return (
|
||||
<div className="container mt-5">
|
||||
<div className="card text-center mx-auto" style={{ maxWidth: 400, maxHeight: 400 }}>
|
||||
<img src={profile.image} className="card-img-top" alt="Профиль" style={{ width: "100%", height: 300, objectFit: "cover" }} />
|
||||
<div className="card-body">
|
||||
<h3 className="card-title">{profile.firstName} {profile.lastName}</h3>
|
||||
<button className="btn btn-primary" onClick={handleEdit}>
|
||||
<i className="bi bi-pencil"></i> Редактировать профиль
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{showEdit && (
|
||||
<div className="modal d-block" tabIndex="-1" style={{ background: 'rgba(0,0,0,0.3)' }}>
|
||||
<div className="modal-dialog">
|
||||
<div className="modal-content">
|
||||
<form onSubmit={handleSave}>
|
||||
<div className="modal-header">
|
||||
<h5 className="modal-title">Редактировать профиль</h5>
|
||||
<button type="button" className="btn-close" onClick={handleCancel}></button>
|
||||
</div>
|
||||
<div className="modal-body">
|
||||
<div className="mb-2">
|
||||
<label className="form-label">Имя</label>
|
||||
<input className="form-control" name="firstName" value={form.firstName} onChange={handleChange} required />
|
||||
</div>
|
||||
<div className="mb-2">
|
||||
<label className="form-label">Фамилия</label>
|
||||
<input className="form-control" name="lastName" value={form.lastName} onChange={handleChange} required />
|
||||
</div>
|
||||
<div className="mb-2">
|
||||
<label className="form-label">URL аватара</label>
|
||||
<input className="form-control" name="image" value={form.image} onChange={handleChange} />
|
||||
</div>
|
||||
</div>
|
||||
<div className="modal-footer">
|
||||
<button type="submit" className="btn btn-success">Сохранить</button>
|
||||
<button type="button" className="btn btn-secondary" onClick={handleCancel}>Отмена</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
import React from "react";
|
||||
import useBasket from "../hooks/useBasket";
|
||||
import useOrders from "../hooks/useOrders";
|
||||
|
||||
export default function BasketPage() {
|
||||
|
||||
const { basket, removeFromBasket, clearBasket } = useBasket();
|
||||
const { addOrder } = useOrders();
|
||||
|
||||
const handleCheckout = () => {
|
||||
if (basket.length === 0) {
|
||||
alert("Корзина пуста");
|
||||
return;
|
||||
}
|
||||
// Сформируем заказ
|
||||
addOrder({
|
||||
items: basket,
|
||||
status: "in-process"
|
||||
});
|
||||
clearBasket(); // Очищаем корзину
|
||||
alert("Заказ оформлен!");
|
||||
};
|
||||
|
||||
return (
|
||||
<main className="container d-flex justify-content-center align-items-center" style={{ minHeight: "60vh" }}>
|
||||
<div className="card p-4 shadow" style={{ minWidth: "60vw" }}>
|
||||
<h2 className="text-center">Корзина</h2>
|
||||
<ul className="list-group list-group-flush">
|
||||
{basket.map(item => (
|
||||
<li className="list-group-item d-flex align-items-center" key={item.id}>
|
||||
<img src={item.image} alt={item.name} style={{ width: 100, height: 100 }} className="me-3" />
|
||||
{item.name} <span className="ms-auto">{item.price} руб.</span>
|
||||
<button onClick={() => removeFromBasket(item.id)} className="btn btn-danger ms-2">Удалить</button>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
<div className="text-center mt-3">
|
||||
<button className={`btn w-100 ${basket.length === 0 ? "btn-secondary" : "btn-success"}`} onClick={handleCheckout}>
|
||||
Оплатить {}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
);
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
import React from "react";
|
||||
import useBasket from "../hooks/useBasket";
|
||||
import useFavorites from "../hooks/useFavorites";
|
||||
|
||||
export default function FavoritesPage() {
|
||||
const { favorites, removeFromFavorites } = useFavorites();
|
||||
const { basket, addToBasket } = useBasket();
|
||||
|
||||
const handleAddToBasket = (item) => {
|
||||
addToBasket(item);
|
||||
removeFromFavorites(item.id);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="container mt-4">
|
||||
<h2 className="mb-4">Избранное</h2>
|
||||
<div className="row row-cols-1 row-cols-md-2 g-4">
|
||||
{favorites.map(item => (
|
||||
<div className="col" key={item.id}>
|
||||
<div className="card mx-auto" style={{ width: "70%" }}>
|
||||
<img src={item.image} className="card-img-top" alt={item.name} style={{ width: "100%", height: 300, objectFit: "cover" }} />
|
||||
<div className="card-body text-center">
|
||||
<h5 className="card-title">{item.name}</h5>
|
||||
<p className="card-text">{item.price}</p>
|
||||
<button className="btn btn-success me-2" onClick={() => handleAddToBasket(item)}>В корзину</button>
|
||||
<button onClick={() => removeFromFavorites(item.id)} className="btn btn-danger">Удалить</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
import React, { useState } from "react";
|
||||
import useProducts from "../hooks/useProducts";
|
||||
import useFavorites from "../hooks/useFavorites";
|
||||
import ProductList from "../components/ProductList";
|
||||
import ProductForm from "../components/ProductForm";
|
||||
|
||||
export default function MainPage() {
|
||||
const { products, add, update, remove } = useProducts();
|
||||
const { favorites, addToFavorites } = useFavorites();
|
||||
const [editing, setEditing] = useState(null);
|
||||
const [showForm, setShowForm] = useState(false);
|
||||
|
||||
const handleAdd = () => { setEditing(null); setShowForm(true); };
|
||||
const handleEdit = prod => { setEditing(prod); setShowForm(true); };
|
||||
const handleDelete = id => remove(id);
|
||||
const handleSave = prod => {
|
||||
editing ? update({ ...prod, id: editing.id }) : add(prod);
|
||||
setShowForm(false);
|
||||
};
|
||||
const handleCancel = () => setShowForm(false);
|
||||
|
||||
const handleAddToFavorites = product => {
|
||||
if (!favorites.some(fav => fav.id === product.id)) {
|
||||
addToFavorites(product);
|
||||
}
|
||||
else alert('Товар уже в избранном!');
|
||||
};
|
||||
|
||||
return (
|
||||
<main className="container my-4">
|
||||
<button className="btn btn-success mb-3" onClick={handleAdd}>Добавить товар</button>
|
||||
{showForm && <ProductForm initial={editing} onSave={handleSave} onCancel={handleCancel} />}
|
||||
<h2 className="text-center my-3">Рекомендуемые товары:</h2>
|
||||
<ProductList
|
||||
products={products}
|
||||
onEdit={handleEdit}
|
||||
onDelete={handleDelete}
|
||||
onAddToFavorites={handleAddToFavorites}
|
||||
/>
|
||||
</main>
|
||||
);
|
||||
}
|
||||
@@ -1,58 +0,0 @@
|
||||
import React from "react";
|
||||
import useOrders from "../hooks/useOrders";
|
||||
|
||||
export default function OrderPage() {
|
||||
const { inProcess, completed } = useOrders();
|
||||
|
||||
return (
|
||||
<div className="container mt-4">
|
||||
<h1 className="text-center">Заказы</h1>
|
||||
<div className="row">
|
||||
<div className="col-md-6">
|
||||
<div className="card shadow-sm">
|
||||
<div className="card-header bg-warning text-dark">
|
||||
<h2 className="h5 m-0">В процессе</h2>
|
||||
</div>
|
||||
<div className="card-body">
|
||||
{inProcess.length === 0 ? (
|
||||
<div className="text-center text-muted">Нет заказов</div>
|
||||
) : (
|
||||
inProcess.map(order => (
|
||||
<ul className="list-group list-group-flush mb-3" key={order.id}>
|
||||
{order.items.map((item, idx) => (
|
||||
<li className="list-group-item d-flex align-items-center mb-2" key={idx}>
|
||||
<img src={item.image} className="me-2" style={{ width: 120, height: 120, objectFit: "cover" }} alt={item.name} /> {item.name}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
))
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-md-6">
|
||||
<div className="card shadow-sm">
|
||||
<div className="card-header bg-success text-white">
|
||||
<h2 className="h5 m-0">Завершённые</h2>
|
||||
</div>
|
||||
<div className="card-body">
|
||||
{completed.length === 0 ? (
|
||||
<div className="text-center text-muted">Нет завершённых заказов</div>
|
||||
) : (
|
||||
completed.map(order => (
|
||||
<ul className="list-group list-group-flush mb-3" key={order.id}>
|
||||
{order.items.map((item, idx) => (
|
||||
<li className="list-group-item d-flex align-items-center mb-2" key={idx}>
|
||||
<img src={item.image} className="me-2" style={{ width: 120, height: 120, objectFit: "cover" }} alt={item.name} /> {item.name}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
))
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,28 +1,16 @@
|
||||
import { resolve } from 'path';
|
||||
import { defineConfig } from "vite";
|
||||
import react from '@vitejs/plugin-react';
|
||||
|
||||
export default defineConfig({
|
||||
root: '.',
|
||||
plugins: [react()],
|
||||
build: {
|
||||
outDir: 'dist',
|
||||
rollupOptions: {
|
||||
input: {
|
||||
build: {
|
||||
rollupOptions: {
|
||||
input: {
|
||||
main: resolve(__dirname, "newSite.html"),
|
||||
basketPage: resolve(__dirname, "Basket.html"),
|
||||
favouritesPage: resolve(__dirname, "Favorites.html"),
|
||||
orderPage: resolve(__dirname, "Order.html"),
|
||||
accountPage: resolve(__dirname, "Account.html"),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
server: {
|
||||
open: '/',
|
||||
},
|
||||
resolve: {
|
||||
alias: {
|
||||
'@': resolve(__dirname, 'src'),
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
BIN
Отчет3.docx
BIN
Отчет3.docx
Binary file not shown.
BIN
Отчет4.docx
BIN
Отчет4.docx
Binary file not shown.
BIN
Отчет5.docx
BIN
Отчет5.docx
Binary file not shown.
BIN
Отчет6.docx
BIN
Отчет6.docx
Binary file not shown.
Reference in New Issue
Block a user