ПРОГРЕСС УРА
This commit is contained in:
52
basket.html
52
basket.html
@@ -8,6 +8,33 @@
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.0/font/bootstrap-icons.css">
|
||||
<link rel="stylesheet" href="./styles.css" />
|
||||
|
||||
<style>
|
||||
@media (min-width: 992px) {
|
||||
.navbar .dropdown:hover .dropdown-menu {
|
||||
display: block;
|
||||
}
|
||||
.navbar .dropdown .dropdown-menu {
|
||||
margin-top: 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* прижимаем футер вниз */
|
||||
html, body {
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
body {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
main {
|
||||
flex: 1; /* растягивается, чтобы футер был внизу */
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<nav class="navbar navbar-expand-lg navbar-dark" style="background-color: #00264d;">
|
||||
@@ -46,19 +73,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<style>
|
||||
@media (min-width: 992px) {
|
||||
.navbar .dropdown:hover .dropdown-menu {
|
||||
display: block;
|
||||
}
|
||||
.navbar .dropdown .dropdown-menu {
|
||||
margin-top: 0;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<!-- В main контейнере basket.html замените содержимое на: -->
|
||||
<main class="container my-4">
|
||||
<div class="empty-basket text-center py-5">
|
||||
<h1 class="mb-4">Здесь будут лежать твои товары</h1>
|
||||
@@ -101,12 +116,13 @@
|
||||
</footer>
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
|
||||
<script src="./components/basket/model.js"></script>
|
||||
<script src="./components/basket/view.js"></script>
|
||||
<script src="./components/basket/controller.js"></script>
|
||||
<script>
|
||||
|
||||
<script type="module">
|
||||
import { Model } from '/components/basket/model.js';
|
||||
import { View } from '/components/basket/view.js';
|
||||
import { Controller } from '/components/basket/controller.js';
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
// Проверяем, есть ли необходимые элементы на странице
|
||||
if (document.getElementById('basketContainer') || document.getElementById('productsContainer')) {
|
||||
const model = new Model();
|
||||
const view = new View();
|
||||
@@ -115,4 +131,4 @@
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
|
||||
13
catalog.html
13
catalog.html
@@ -354,12 +354,14 @@
|
||||
});
|
||||
</script>
|
||||
|
||||
<script src="./components/basket/model.js"></script>
|
||||
<script src="./components/basket/view.js"></script>
|
||||
<script src="./components/basket/controller.js"></script>
|
||||
<script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
|
||||
|
||||
<script type="module">
|
||||
import { Model } from '/components/basket/model.js';
|
||||
import { View } from '/components/basket/view.js';
|
||||
import { Controller } from '/components/basket/controller.js';
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
// Проверяем, есть ли необходимые элементы на странице
|
||||
if (document.getElementById('basketContainer') || document.getElementById('productsContainer')) {
|
||||
const model = new Model();
|
||||
const view = new View();
|
||||
@@ -367,5 +369,6 @@
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
49
dist/assets/controller-BWr64z2B.js
vendored
Normal file
49
dist/assets/controller-BWr64z2B.js
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
(function(){const t=document.createElement("link").relList;if(t&&t.supports&&t.supports("modulepreload"))return;for(const a of document.querySelectorAll('link[rel="modulepreload"]'))e(a);new MutationObserver(a=>{for(const i of a)if(i.type==="childList")for(const o of i.addedNodes)o.tagName==="LINK"&&o.rel==="modulepreload"&&e(o)}).observe(document,{childList:!0,subtree:!0});function s(a){const i={};return a.integrity&&(i.integrity=a.integrity),a.referrerPolicy&&(i.referrerPolicy=a.referrerPolicy),a.crossOrigin==="use-credentials"?i.credentials="include":a.crossOrigin==="anonymous"?i.credentials="omit":i.credentials="same-origin",i}function e(a){if(a.ep)return;a.ep=!0;const i=s(a);fetch(a.href,i)}})();class r{constructor(){this.apiUrl="http://localhost:3000"}async request(t,s={}){try{const e=await fetch(`${this.apiUrl}${t}`,{...s,headers:{"Content-Type":"application/json",...s.headers}});if(!e.ok)throw new Error(`HTTP error! status: ${e.status}`);return await e.json()}catch(e){throw console.error("Request failed:",e),e}}async getBasketItems(){try{return await this.request("/basket")}catch(t){return console.error("Ошибка при получении корзины:",t),[]}}async addToBasket(t){try{const e=(await this.getBasketItems()).find(a=>a.id===t.id);if(e)await this.updateBasketItem(t.id,e.quantity+1);else{const a={...t,quantity:1,addedAt:new Date().toISOString()};return await(await fetch(`${this.apiUrl}/basket`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(a)})).json()}}catch(s){console.error("Ошибка при добавлении в корзину:",s)}}async updateBasketItem(t,s){try{return await(await fetch(`${this.apiUrl}/basket/${t}`,{method:"PATCH",headers:{"Content-Type":"application/json"},body:JSON.stringify({quantity:s})})).json()}catch(e){console.error("Ошибка при обновлении корзины:",e)}}async removeFromBasket(t){try{await fetch(`${this.apiUrl}/basket/${t}`,{method:"DELETE"})}catch(s){console.error("Ошибка при удалении из корзины:",s)}}async clearBasket(){try{const t=await this.getBasketItems();for(const s of t)await this.removeFromBasket(s.id)}catch(t){console.error("Ошибка при очистке корзины:",t)}}async getProducts(){try{return await(await fetch(`${this.apiUrl}/shmots`)).json()}catch(t){return console.error("Ошибка при получении товаров:",t),[]}}}class c{constructor(){this.basketContainer=document.getElementById("basketContainer"),this.emptyBasketElement=document.querySelector(".empty-basket")}showBasket(t){if(t.length===0){this.showEmptyBasket();return}this.hideEmptyBasket();const s=t.map(e=>this.createBasketItemHTML(e)).join("");this.basketContainer.innerHTML=`
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<div class="card border-0 shadow">
|
||||
<div class="card-header" style="background-color: #00264d; color: white;">
|
||||
<h5 class="mb-0"><i class="bi bi-cart me-2"></i>Корзина</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
${s}
|
||||
<div class="d-flex justify-content-between align-items-center mt-4 pt-3 border-top">
|
||||
<h5>Итого: $${this.calculateTotal(t).toFixed(2)}</h5>
|
||||
<button class="btn btn-lg" style="background-color: #00264d; color: white;" id="checkoutBtn">
|
||||
<i class="bi bi-credit-card me-2"></i>Оформить заказ
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`}createBasketItemHTML(t){return`
|
||||
<div class="row align-items-center mb-3 basket-item" data-id="${t.id}">
|
||||
<div class="col-md-2">
|
||||
<img src="${t.image}" alt="${t.name}" class="img-fluid rounded" style="max-height: 80px;">
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<h6 class="mb-1">${t.name}</h6>
|
||||
<p class="text-muted small mb-0">${t.description}</p>
|
||||
</div>
|
||||
<div class="col-md-2">
|
||||
<span class="fw-bold">$${t.price}</span>
|
||||
</div>
|
||||
<div class="col-md-2">
|
||||
<div class="input-group input-group-sm">
|
||||
<button class="btn btn-outline-secondary decrease-btn" type="button">-</button>
|
||||
<input type="number" class="form-control text-center quantity-input" value="${t.quantity}" min="1">
|
||||
<button class="btn btn-outline-secondary increase-btn" type="button">+</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-2">
|
||||
<span class="fw-bold me-3">$${(t.price*t.quantity).toFixed(2)}</span>
|
||||
<button class="btn btn-sm btn-outline-danger remove-btn">
|
||||
<i class="bi bi-trash"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
`}showEmptyBasket(){this.emptyBasketElement&&(this.emptyBasketElement.style.display="block"),this.basketContainer&&(this.basketContainer.innerHTML="")}hideEmptyBasket(){this.emptyBasketElement&&(this.emptyBasketElement.style.display="none")}calculateTotal(t){return t.reduce((s,e)=>s+e.price*e.quantity,0)}showNotification(t,s="success"){const e=document.createElement("div");e.className=`alert alert-${s==="success"?"success":"danger"} alert-dismissible fade show`,e.style.cssText="position: fixed; top: 20px; right: 20px; z-index: 1050; min-width: 300px;",e.innerHTML=`
|
||||
${t}
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
|
||||
`,document.body.appendChild(e),setTimeout(()=>{e.parentNode&&e.remove()},3e3)}}class l{constructor(t,s){this.model=t,this.view=s,this.init()}async init(){window.location.pathname.includes("basket.html")&&(await this.loadBasket(),this.setupBasketEventListeners()),window.location.pathname.includes("catalog.html")&&this.setupCatalogEventListeners()}async loadBasket(){const t=await this.model.getBasketItems();this.view.showBasket(t)}setupBasketEventListeners(){document.addEventListener("click",async t=>{const s=t.target.closest(".basket-item");if(!s)return;const e=s.dataset.id;if(t.target.closest(".remove-btn")&&(await this.model.removeFromBasket(e),this.view.showNotification("Товар удален из корзины"),await this.loadBasket()),t.target.closest(".increase-btn")){const a=s.querySelector(".quantity-input"),i=parseInt(a.value)+1;a.value=i,await this.model.updateBasketItem(e,i),await this.loadBasket()}if(t.target.closest(".decrease-btn")){const a=s.querySelector(".quantity-input");let i=parseInt(a.value)-1;i<1&&(i=1),a.value=i,await this.model.updateBasketItem(e,i),await this.loadBasket()}}),document.addEventListener("change",async t=>{if(t.target.classList.contains("quantity-input")){const e=t.target.closest(".basket-item").dataset.id,a=parseInt(t.target.value)||1;if(a<1){t.target.value=1;return}await this.model.updateBasketItem(e,a),await this.loadBasket()}}),document.addEventListener("click",async t=>{if(t.target.id==="checkoutBtn"){if((await this.model.getBasketItems()).length===0){this.view.showNotification("Корзина пуста","error");return}this.view.showNotification("Заказ оформлен! Спасибо за покупку!"),await this.model.clearBasket(),await this.loadBasket()}})}setupCatalogEventListeners(){document.addEventListener("click",async t=>{if(t.target.closest(".btn")&&t.target.closest(".btn").textContent.includes("В корзину")){const s=t.target.closest(".card"),e=this.extractProductData(s);e&&(await this.model.addToBasket(e),this.view.showNotification("Товар добавлен в корзину!"))}})}extractProductData(t){try{const s=t.querySelector(".card-title").textContent,e=t.querySelector(".text-muted").textContent.replace("$",""),a=t.querySelector(".card-text").textContent,i=t.querySelector("img").src;return{id:btoa(`${s}-${e}`).substring(0,8),name:s.trim(),price:parseFloat(e),description:a.trim(),image:i}}catch(s){return console.error("Ошибка при извлечении данных товара:",s),null}}}export{l as C,r as M,c as V};
|
||||
1
dist/assets/page2-Cyv2CTPS.js
vendored
Normal file
1
dist/assets/page2-Cyv2CTPS.js
vendored
Normal file
@@ -0,0 +1 @@
|
||||
import{V as t,C as o,M as d}from"./controller-BWr64z2B.js";/* empty css */document.addEventListener("DOMContentLoaded",function(){if(document.getElementById("basketContainer")||document.getElementById("productsContainer")){const e=new d,n=new t;new o(e,n)}});
|
||||
1
dist/assets/page5-Cyv2CTPS.js
vendored
Normal file
1
dist/assets/page5-Cyv2CTPS.js
vendored
Normal file
@@ -0,0 +1 @@
|
||||
import{V as t,C as o,M as d}from"./controller-BWr64z2B.js";/* empty css */document.addEventListener("DOMContentLoaded",function(){if(document.getElementById("basketContainer")||document.getElementById("productsContainer")){const e=new d,n=new t;new o(e,n)}});
|
||||
57
dist/basket.html
vendored
57
dist/basket.html
vendored
@@ -7,6 +7,35 @@
|
||||
<link rel="shortcut icon" href="/assets/favicon-cXvr3Sfo.ico" type="image/x-icon">
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.0/font/bootstrap-icons.css">
|
||||
|
||||
|
||||
<style>
|
||||
@media (min-width: 992px) {
|
||||
.navbar .dropdown:hover .dropdown-menu {
|
||||
display: block;
|
||||
}
|
||||
.navbar .dropdown .dropdown-menu {
|
||||
margin-top: 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* прижимаем футер вниз */
|
||||
html, body {
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
body {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
main {
|
||||
flex: 1; /* растягивается, чтобы футер был внизу */
|
||||
}
|
||||
</style>
|
||||
<script type="module" crossorigin src="/assets/page5-Cyv2CTPS.js"></script>
|
||||
<link rel="modulepreload" crossorigin href="/assets/controller-BWr64z2B.js">
|
||||
<link rel="stylesheet" crossorigin href="/assets/styles-cpwRBDRQ.css">
|
||||
</head>
|
||||
@@ -46,19 +75,7 @@
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<style>
|
||||
@media (min-width: 992px) {
|
||||
.navbar .dropdown:hover .dropdown-menu {
|
||||
display: block;
|
||||
}
|
||||
.navbar .dropdown .dropdown-menu {
|
||||
margin-top: 0;
|
||||
}
|
||||
}
|
||||
</nav>
|
||||
|
||||
|
||||
<main class="container my-4">
|
||||
<div class="empty-basket text-center py-5">
|
||||
@@ -101,18 +118,6 @@
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
|
||||
<script src="./components/basket/model.js"></script>
|
||||
<script src="./components/basket/view.js"></script>
|
||||
<script src="./components/basket/controller.js"></script>
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
// Проверяем, есть ли необходимые элементы на странице
|
||||
if (document.getElementById('basketContainer') || document.getElementById('productsContainer')) {
|
||||
const model = new Model();
|
||||
const view = new View();
|
||||
new Controller(model, view);
|
||||
}
|
||||
});
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
|
||||
|
||||
</body>
|
||||
|
||||
|
||||
18
dist/catalog.html
vendored
18
dist/catalog.html
vendored
@@ -26,6 +26,8 @@
|
||||
.like-btn i {
|
||||
transition: text-shadow 0.2s ease;
|
||||
}
|
||||
</style>
|
||||
<script type="module" crossorigin src="/assets/page2-Cyv2CTPS.js"></script>
|
||||
<link rel="modulepreload" crossorigin href="/assets/controller-BWr64z2B.js">
|
||||
<link rel="stylesheet" crossorigin href="/assets/styles-cpwRBDRQ.css">
|
||||
</head>
|
||||
@@ -354,18 +356,8 @@
|
||||
this.reset();
|
||||
});
|
||||
</script>
|
||||
|
||||
<script src="./components/basket/model.js"></script>
|
||||
<script src="./components/basket/view.js"></script>
|
||||
<script src="./components/basket/controller.js"></script>
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
// Проверяем, есть ли необходимые элементы на странице
|
||||
if (document.getElementById('basketContainer') || document.getElementById('productsContainer')) {
|
||||
const model = new Model();
|
||||
const view = new View();
|
||||
new Controller(model, view);
|
||||
}
|
||||
});
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user