Compare commits
2 Commits
прикручива
...
9114d1f29d
| Author | SHA1 | Date | |
|---|---|---|---|
| 9114d1f29d | |||
| 1fe1094277 |
363
catalog.html
363
catalog.html
@@ -9,20 +9,64 @@
|
||||
<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>
|
||||
.card-actions {
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
right: 10px;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.card-actions .btn {
|
||||
background-color: white !important;
|
||||
border: 1px solid !important;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.card-actions .btn:hover {
|
||||
background-color: white !important;
|
||||
transform: scale(1.1);
|
||||
}
|
||||
|
||||
/* Стили для кнопки редактирования */
|
||||
.card-actions .btn-outline-primary {
|
||||
color: #0d6efd !important;
|
||||
border-color: #0d6efd !important;
|
||||
}
|
||||
|
||||
.card-actions .btn-outline-primary:hover {
|
||||
color: #0d6efd !important;
|
||||
border-color: #0d6efd !important;
|
||||
background-color: white !important;
|
||||
}
|
||||
|
||||
/* Стили для кнопки удаления */
|
||||
.card-actions .btn-outline-danger {
|
||||
color: #dc3545 !important;
|
||||
border-color: #dc3545 !important;
|
||||
}
|
||||
|
||||
.card-actions .btn-outline-danger:hover {
|
||||
color: #dc3545 !important;
|
||||
border-color: #dc3545 !important;
|
||||
background-color: white !important;
|
||||
}
|
||||
|
||||
/* Стили для лайков */
|
||||
.like-btn.liked {
|
||||
color: #000000 !important;
|
||||
border-color: #dc3545 !important;
|
||||
}
|
||||
|
||||
.like-btn.liked i {
|
||||
color: #dc3545 !important;
|
||||
}
|
||||
/* Черная оконтовка при наведении на нажатую кнопку */
|
||||
|
||||
.like-btn.liked:hover i {
|
||||
text-shadow: 0 0 2px #000000,
|
||||
0 0 2px #000000,
|
||||
0 0 2px #000000;
|
||||
0 0 2px #000000,
|
||||
0 0 2px #000000;
|
||||
}
|
||||
/* Плавное изменение */
|
||||
|
||||
.like-btn i {
|
||||
transition: text-shadow 0.2s ease;
|
||||
}
|
||||
@@ -77,6 +121,62 @@
|
||||
}
|
||||
</style>
|
||||
|
||||
<!-- Модальное окно редактирования товара -->
|
||||
<div class="modal fade" id="editProductModal" tabindex="-1" aria-labelledby="editProductModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="editProductModalLabel">Редактировать товар</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form id="editProductForm" class="row g-3">
|
||||
<input type="hidden" id="editProductIndex">
|
||||
<div class="col-md-6">
|
||||
<label for="editProductName" class="form-label">Название товара</label>
|
||||
<input type="text" class="form-control" id="editProductName" required>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label for="editProductPrice" class="form-label">Цена</label>
|
||||
<input type="text" class="form-control" id="editProductPrice" required>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label for="editProductCategory" class="form-label">Категория</label>
|
||||
<select class="form-select" id="editProductCategory" required>
|
||||
<option value="">Выберите категорию</option>
|
||||
<option value="1">Для мужчин</option>
|
||||
<option value="2">Для женщин</option>
|
||||
<option value="3">Унисекс</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label for="editProductCondition" class="form-label">Состояние</label>
|
||||
<select class="form-select" id="editProductCondition" required>
|
||||
<option value="">Выберите состояние</option>
|
||||
<option value="1">Новый</option>
|
||||
<option value="2">Б/У</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<label for="editProductDescription" class="form-label">Описание</label>
|
||||
<textarea class="form-control" id="editProductDescription" rows="3" required></textarea>
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<label for="editProductImage" class="form-label">Ссылка на изображение</label>
|
||||
<input type="text" class="form-control" id="editProductImage" required>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Отмена</button>
|
||||
<button type="button" class="btn" style="background-color: #00264d; color: white;" id="saveProductChanges">
|
||||
<i class="bi bi-check-circle me-2"></i>Сохранить изменения
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<main class="container my-4">
|
||||
<div class="accordion" id="accordionExample">
|
||||
<div class="accordion-item">
|
||||
@@ -141,7 +241,15 @@
|
||||
<div class="row row-cols-1 row-cols-md-2 row-cols-lg-3 g-4 mb-5" id="productsContainer">
|
||||
<!-- Карточка товара 1 -->
|
||||
<div class="col">
|
||||
<div class="card h-100 border-0 shadow">
|
||||
<div class="card h-100 border-0 shadow position-relative">
|
||||
<div class="card-actions">
|
||||
<button class="btn btn-sm btn-outline-primary edit-btn me-1" data-product-index="0">
|
||||
<i class="bi bi-pencil"></i>
|
||||
</button>
|
||||
<button class="btn btn-sm btn-outline-danger delete-btn">
|
||||
<i class="bi bi-trash"></i>
|
||||
</button>
|
||||
</div>
|
||||
<img src="img/stonik.jpg" class="card-img-top" alt="Stone Island">
|
||||
<div class="card-body">
|
||||
<h4 class="card-title">Stone Island</h4>
|
||||
@@ -150,17 +258,17 @@
|
||||
<div class="row">
|
||||
<div class="col-6">
|
||||
<h5 class="card-text mb-1">Category:</h5>
|
||||
<p class="card-text">men</p>
|
||||
<p class="card-text category-text">men</p>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<h5 class="card-text mb-1">Condition:</h5>
|
||||
<p class="card-text">new</p>
|
||||
<p class="card-text condition-text">new</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-footer bg-transparent">
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<span class="text-muted">$1999.99</span>
|
||||
<span class="text-muted price-text">$1999.99</span>
|
||||
<button class="btn btn-sm" style="background-color: #00264d; color: white;">
|
||||
<i class="bi bi-cart-plus me-1"></i>В корзину
|
||||
</button>
|
||||
@@ -179,7 +287,15 @@
|
||||
|
||||
<!-- Карточка товара 2 -->
|
||||
<div class="col">
|
||||
<div class="card h-100 border-0 shadow">
|
||||
<div class="card h-100 border-0 shadow position-relative">
|
||||
<div class="card-actions">
|
||||
<button class="btn btn-sm btn-outline-primary edit-btn me-1" data-product-index="1">
|
||||
<i class="bi bi-pencil"></i>
|
||||
</button>
|
||||
<button class="btn btn-sm btn-outline-danger delete-btn">
|
||||
<i class="bi bi-trash"></i>
|
||||
</button>
|
||||
</div>
|
||||
<img src="img/adidas.jpg" class="card-img-top" alt="Adidas">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">Adidas</h5>
|
||||
@@ -188,17 +304,17 @@
|
||||
<div class="row">
|
||||
<div class="col-6">
|
||||
<h5 class="card-text mb-1">Category:</h5>
|
||||
<p class="card-text">men</p>
|
||||
<p class="card-text category-text">men</p>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<h5 class="card-text mb-1">Condition:</h5>
|
||||
<p class="card-text">wu</p>
|
||||
<p class="card-text condition-text">wu</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-footer bg-transparent">
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<span class="text-muted">$19.99</span>
|
||||
<span class="text-muted price-text">$19.99</span>
|
||||
<button class="btn btn-sm" style="background-color: #00264d; color: white;">
|
||||
<i class="bi bi-cart-plus me-1"></i>В корзину
|
||||
</button>
|
||||
@@ -217,7 +333,15 @@
|
||||
|
||||
<!-- Карточка товара 3 -->
|
||||
<div class="col">
|
||||
<div class="card h-100 border-0 shadow">
|
||||
<div class="card h-100 border-0 shadow position-relative">
|
||||
<div class="card-actions">
|
||||
<button class="btn btn-sm btn-outline-primary edit-btn me-1" data-product-index="2">
|
||||
<i class="bi bi-pencil"></i>
|
||||
</button>
|
||||
<button class="btn btn-sm btn-outline-danger delete-btn">
|
||||
<i class="bi bi-trash"></i>
|
||||
</button>
|
||||
</div>
|
||||
<img src="img/napapisaj.jpg" class="card-img-top" alt="Napapisaj">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">Napapisaj</h5>
|
||||
@@ -226,17 +350,17 @@
|
||||
<div class="row">
|
||||
<div class="col-6">
|
||||
<h5 class="card-text mb-1">Category:</h5>
|
||||
<p class="card-text">men</p>
|
||||
<p class="card-text category-text">men</p>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<h5 class="card-text mb-1">Condition:</h5>
|
||||
<p class="card-text">wu</p>
|
||||
<p class="card-text condition-text">wu</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-footer bg-transparent">
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<span class="text-muted">$1499.99</span>
|
||||
<span class="text-muted price-text">$1499.99</span>
|
||||
<button class="btn btn-sm" style="background-color: #00264d; color: white;">
|
||||
<i class="bi bi-cart-plus me-1"></i>В корзину
|
||||
</button>
|
||||
@@ -255,7 +379,15 @@
|
||||
|
||||
<!-- Карточка товара 4 -->
|
||||
<div class="col">
|
||||
<div class="card h-100 border-0 shadow">
|
||||
<div class="card h-100 border-0 shadow position-relative">
|
||||
<div class="card-actions">
|
||||
<button class="btn btn-sm btn-outline-primary edit-btn me-1" data-product-index="3">
|
||||
<i class="bi bi-pencil"></i>
|
||||
</button>
|
||||
<button class="btn btn-sm btn-outline-danger delete-btn">
|
||||
<i class="bi bi-trash"></i>
|
||||
</button>
|
||||
</div>
|
||||
<img src="img/lacoste.png" class="card-img-top" alt="Lacoste">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">Lacoste</h5>
|
||||
@@ -264,17 +396,17 @@
|
||||
<div class="row">
|
||||
<div class="col-6">
|
||||
<h5 class="card-text mb-1">Category:</h5>
|
||||
<p class="card-text">uni</p>
|
||||
<p class="card-text category-text">uni</p>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<h5 class="card-text mb-1">Condition:</h5>
|
||||
<p class="card-text">wu</p>
|
||||
<p class="card-text condition-text">wu</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-footer bg-transparent">
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<span class="text-muted">$399.99</span>
|
||||
<span class="text-muted price-text">$399.99</span>
|
||||
<button class="btn btn-sm" style="background-color: #00264d; color: white;">
|
||||
<i class="bi bi-cart-plus me-1"></i>В корзину
|
||||
</button>
|
||||
@@ -293,7 +425,15 @@
|
||||
|
||||
<!-- Карточка товара 5 -->
|
||||
<div class="col">
|
||||
<div class="card h-100 border-0 shadow">
|
||||
<div class="card h-100 border-0 shadow position-relative">
|
||||
<div class="card-actions">
|
||||
<button class="btn btn-sm btn-outline-primary edit-btn me-1" data-product-index="4">
|
||||
<i class="bi bi-pencil"></i>
|
||||
</button>
|
||||
<button class="btn btn-sm btn-outline-danger delete-btn">
|
||||
<i class="bi bi-trash"></i>
|
||||
</button>
|
||||
</div>
|
||||
<img src="img/samba.png" class="card-img-top" alt="Samba">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">Samba</h5>
|
||||
@@ -302,17 +442,17 @@
|
||||
<div class="row">
|
||||
<div class="col-6">
|
||||
<h5 class="card-text mb-1">Category:</h5>
|
||||
<p class="card-text">women</p>
|
||||
<p class="card-text category-text">women</p>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<h5 class="card-text mb-1">Condition:</h5>
|
||||
<p class="card-text">new</p>
|
||||
<p class="card-text condition-text">new</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-footer bg-transparent">
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<span class="text-muted">$449.99</span>
|
||||
<span class="text-muted price-text">$449.99</span>
|
||||
<button class="btn btn-sm" style="background-color: #00264d; color: white;">
|
||||
<i class="bi bi-cart-plus me-1"></i>В корзину
|
||||
</button>
|
||||
@@ -360,6 +500,112 @@
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
|
||||
|
||||
<script>
|
||||
// Функция для открытия модального окна редактирования
|
||||
function openEditModal(productIndex) {
|
||||
const card = document.querySelectorAll('#productsContainer .col')[productIndex];
|
||||
|
||||
// Получаем текущие данные карточки
|
||||
const title = card.querySelector('.card-title').textContent;
|
||||
const description = card.querySelector('.card-text').textContent;
|
||||
const price = card.querySelector('.price-text').textContent;
|
||||
const category = card.querySelector('.category-text').textContent;
|
||||
const condition = card.querySelector('.condition-text').textContent;
|
||||
const image = card.querySelector('.card-img-top').src;
|
||||
|
||||
// Заполняем форму редактирования
|
||||
document.getElementById('editProductName').value = title;
|
||||
document.getElementById('editProductDescription').value = description;
|
||||
document.getElementById('editProductPrice').value = price;
|
||||
document.getElementById('editProductImage').value = image;
|
||||
|
||||
// Устанавливаем выбранные значения для категории и состояния
|
||||
setSelectValue('editProductCategory', getCategoryValue(category));
|
||||
setSelectValue('editProductCondition', getConditionValue(condition));
|
||||
|
||||
// Сохраняем индекс редактируемого товара
|
||||
document.getElementById('editProductIndex').value = productIndex;
|
||||
|
||||
// Показываем модальное окно
|
||||
const editModal = new bootstrap.Modal(document.getElementById('editProductModal'));
|
||||
editModal.show();
|
||||
}
|
||||
|
||||
// Функция для установки значения в select
|
||||
function setSelectValue(selectId, value) {
|
||||
const select = document.getElementById(selectId);
|
||||
for (let i = 0; i < select.options.length; i++) {
|
||||
if (select.options[i].value === value) {
|
||||
select.selectedIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Функция для получения значения категории из текста
|
||||
function getCategoryValue(categoryText) {
|
||||
switch(categoryText.toLowerCase()) {
|
||||
case 'men': return '1';
|
||||
case 'women': return '2';
|
||||
case 'uni': return '3';
|
||||
default: return '1';
|
||||
}
|
||||
}
|
||||
|
||||
// Функция для получения текста категории из значения
|
||||
function getCategoryText(categoryValue) {
|
||||
switch(categoryValue) {
|
||||
case '1': return 'men';
|
||||
case '2': return 'women';
|
||||
case '3': return 'uni';
|
||||
default: return 'men';
|
||||
}
|
||||
}
|
||||
|
||||
// Функция для получения значения состояния из текста
|
||||
function getConditionValue(conditionText) {
|
||||
switch(conditionText.toLowerCase()) {
|
||||
case 'new': return '1';
|
||||
case 'wu': return '2';
|
||||
default: return '1';
|
||||
}
|
||||
}
|
||||
|
||||
// Функция для получения текста состояния из значения
|
||||
function getConditionText(conditionValue) {
|
||||
switch(conditionValue) {
|
||||
case '1': return 'new';
|
||||
case '2': return 'wu';
|
||||
default: return 'new';
|
||||
}
|
||||
}
|
||||
|
||||
// Обработчик сохранения изменений
|
||||
document.getElementById('saveProductChanges').addEventListener('click', function() {
|
||||
const productIndex = document.getElementById('editProductIndex').value;
|
||||
const card = document.querySelectorAll('#productsContainer .col')[productIndex];
|
||||
|
||||
// Получаем новые значения из формы
|
||||
const newTitle = document.getElementById('editProductName').value;
|
||||
const newDescription = document.getElementById('editProductDescription').value;
|
||||
const newPrice = document.getElementById('editProductPrice').value;
|
||||
const newCategory = document.getElementById('editProductCategory').value;
|
||||
const newCondition = document.getElementById('editProductCondition').value;
|
||||
const newImage = document.getElementById('editProductImage').value;
|
||||
|
||||
// Обновляем карточку
|
||||
card.querySelector('.card-title').textContent = newTitle;
|
||||
card.querySelector('.card-text').textContent = newDescription;
|
||||
card.querySelector('.price-text').textContent = newPrice;
|
||||
card.querySelector('.category-text').textContent = getCategoryText(newCategory);
|
||||
card.querySelector('.condition-text').textContent = getConditionText(newCondition);
|
||||
card.querySelector('.card-img-top').src = newImage;
|
||||
card.querySelector('.card-img-top').alt = newTitle;
|
||||
|
||||
// Закрываем модальное окно
|
||||
const editModal = bootstrap.Modal.getInstance(document.getElementById('editProductModal'));
|
||||
editModal.hide();
|
||||
});
|
||||
|
||||
document.getElementById("addProductForm").addEventListener("submit", function (e) {
|
||||
e.preventDefault();
|
||||
const name = document.getElementById("productName").value;
|
||||
@@ -370,12 +616,20 @@
|
||||
const image = document.getElementById("productImage").value;
|
||||
|
||||
// Получаем текстовые значения для отображения
|
||||
const categoryText = document.getElementById("productCategory").options[document.getElementById("productCategory").selectedIndex].text;
|
||||
const conditionText = document.getElementById("productCondition").options[document.getElementById("productCondition").selectedIndex].text;
|
||||
const categoryText = getCategoryText(category);
|
||||
const conditionText = getConditionText(condition);
|
||||
|
||||
const productCard = `
|
||||
<div class="col">
|
||||
<div class="card h-100 border-0 shadow">
|
||||
<div class="card h-100 border-0 shadow position-relative">
|
||||
<div class="card-actions">
|
||||
<button class="btn btn-sm btn-outline-primary edit-btn me-1" data-product-index="${document.querySelectorAll('#productsContainer .col').length}">
|
||||
<i class="bi bi-pencil"></i>
|
||||
</button>
|
||||
<button class="btn btn-sm btn-outline-danger delete-btn">
|
||||
<i class="bi bi-trash"></i>
|
||||
</button>
|
||||
</div>
|
||||
<img src="${image}" class="card-img-top" alt="${name}">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">${name}</h5>
|
||||
@@ -383,17 +637,17 @@
|
||||
<div class="row">
|
||||
<div class="col-6">
|
||||
<h5 class="card-text mb-1">Category:</h5>
|
||||
<p class="card-text">${categoryText}</p>
|
||||
<p class="card-text category-text">${categoryText}</p>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<h5 class="card-text mb-1">Condition:</h5>
|
||||
<p class="card-text">${conditionText}</p>
|
||||
<p class="card-text condition-text">${conditionText}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-footer bg-transparent">
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<span class="text-muted">${price}</span>
|
||||
<span class="text-muted price-text">${price}</span>
|
||||
<button class="btn btn-sm" style="background-color: #00264d; color: white;">
|
||||
<i class="bi bi-cart-plus me-1"></i>В корзину
|
||||
</button>
|
||||
@@ -412,8 +666,57 @@
|
||||
`;
|
||||
|
||||
document.getElementById("productsContainer").insertAdjacentHTML("beforeend", productCard);
|
||||
|
||||
// Добавляем обработчики событий для новых кнопок
|
||||
addEventListenersToNewCard();
|
||||
|
||||
this.reset();
|
||||
});
|
||||
|
||||
// Функция для добавления обработчиков событий к новым карточкам
|
||||
function addEventListenersToNewCard() {
|
||||
const lastCard = document.querySelector('#productsContainer .col:last-child');
|
||||
const editBtn = lastCard.querySelector('.edit-btn');
|
||||
const deleteBtn = lastCard.querySelector('.delete-btn');
|
||||
|
||||
editBtn.addEventListener('click', function() {
|
||||
const productIndex = this.getAttribute('data-product-index');
|
||||
openEditModal(productIndex);
|
||||
});
|
||||
|
||||
deleteBtn.addEventListener('click', function() {
|
||||
const card = this.closest('.col');
|
||||
const title = card.querySelector('.card-title').textContent;
|
||||
|
||||
if (confirm(`Вы уверены, что хотите удалить товар "${title}"?`)) {
|
||||
card.remove();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Добавляем обработчики событий для существующих карточек
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const editButtons = document.querySelectorAll('.edit-btn');
|
||||
const deleteButtons = document.querySelectorAll('.delete-btn');
|
||||
|
||||
editButtons.forEach(btn => {
|
||||
btn.addEventListener('click', function() {
|
||||
const productIndex = this.getAttribute('data-product-index');
|
||||
openEditModal(productIndex);
|
||||
});
|
||||
});
|
||||
|
||||
deleteButtons.forEach(btn => {
|
||||
btn.addEventListener('click', function() {
|
||||
const card = this.closest('.col');
|
||||
const title = card.querySelector('.card-title').textContent;
|
||||
|
||||
if (confirm(`Вы уверены, что хотите удалить товар "${title}"?`)) {
|
||||
card.remove();
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
|
||||
|
||||
@@ -25,6 +25,21 @@ export class LikesController {
|
||||
setupLikesEventListeners() {
|
||||
document.addEventListener('click', async (e) => {
|
||||
const likeItem = e.target.closest('.like-item');
|
||||
|
||||
// Обработка кнопки очистки всего избранного
|
||||
if (e.target.closest('#clearAllLikesBtn')) {
|
||||
if (confirm('Вы уверены, что хотите очистить всё избранное?')) {
|
||||
try {
|
||||
await this.model.clearAllLikes();
|
||||
this.view.showNotification('Все товары удалены из избранного');
|
||||
await this.loadLikes();
|
||||
} catch (error) {
|
||||
this.view.showNotification('Ошибка при очистке избранного', 'error');
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (!likeItem) return;
|
||||
|
||||
const productId = likeItem.dataset.id;
|
||||
@@ -71,7 +86,7 @@ export class LikesController {
|
||||
const description = card.querySelector('.card-text').textContent;
|
||||
const image = card.querySelector('img').src;
|
||||
|
||||
// ✅ Вытаскиваем category и condition
|
||||
//Вытаскиваем category и condition
|
||||
const category = card.querySelector('.col-6:nth-child(1) p')?.textContent.trim() || '';
|
||||
const condition = card.querySelector('.col-6:nth-child(2) p')?.textContent.trim() || '';
|
||||
|
||||
@@ -91,4 +106,4 @@ export class LikesController {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -50,6 +50,19 @@ export class LikesModel {
|
||||
}
|
||||
}
|
||||
|
||||
async clearAllLikes() {
|
||||
try {
|
||||
const items = await this.getLikesItems();
|
||||
// Удаляем все товары из избранного
|
||||
for (const item of items) {
|
||||
await this.removeFromLikes(item.id);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Ошибка при очистке избранного:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
async moveToBasket(product) {
|
||||
try {
|
||||
// 1. Добавляем в корзину
|
||||
@@ -66,4 +79,4 @@ export class LikesModel {
|
||||
console.error('Ошибка при переносе товара в корзину:', error);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -13,20 +13,27 @@ export class LikesView {
|
||||
return;
|
||||
}
|
||||
|
||||
// 👉 Если товары есть — убираем блок "пусто"
|
||||
// Если товары есть — убираем блок "пусто"
|
||||
this.hideEmptyLikes();
|
||||
|
||||
const likesHTML = items.map(item => this.createLikesItemHTML(item)).join('');
|
||||
|
||||
// 👉 Добавляем заголовок "Избранное"
|
||||
// Добавляем заголовок "Избранное" и кнопку очистки
|
||||
this.likesContainer.innerHTML = `
|
||||
<h2 class="mb-4 text-center">Избранное</h2>
|
||||
<div class="row g-3">${likesHTML}</div>
|
||||
<div class="d-flex justify-content-between align-items-center mb-4">
|
||||
<h2 class="mb-0">Избранное</h2>
|
||||
<button class="btn btn-outline-danger" id="clearAllLikesBtn">
|
||||
<i class="bi bi-trash me-2"></i>Очистить избранное
|
||||
</button>
|
||||
</div>
|
||||
<div class="row g-3">
|
||||
${likesHTML}
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
createLikesItemHTML(item) {
|
||||
return `
|
||||
return `
|
||||
<div class="col-md-4">
|
||||
<div class="card h-100 border-0 shadow like-item" data-id="${item.id}">
|
||||
<img src="${item.image}" class="card-img-top" alt="${item.name}">
|
||||
@@ -34,7 +41,7 @@ export class LikesView {
|
||||
<h5 class="card-title">${item.name}</h5>
|
||||
<p class="card-text">${item.description}</p>
|
||||
|
||||
<!-- ✅ Добавляем Category и Condition -->
|
||||
<!-- Добавляем Category и Condition -->
|
||||
<div class="row">
|
||||
<div class="col-6">
|
||||
<h6 class="mb-1">Category:</h6>
|
||||
@@ -45,8 +52,6 @@ export class LikesView {
|
||||
<p class="card-text">${item.condition || '-'}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<div class="card-footer bg-transparent">
|
||||
@@ -65,8 +70,10 @@ export class LikesView {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
showEmptyLikes() {
|
||||
if (this.emptyLikesElement) {
|
||||
@@ -96,4 +103,4 @@ export class LikesView {
|
||||
if (notification.parentNode) notification.remove();
|
||||
}, 3000);
|
||||
}
|
||||
}
|
||||
}
|
||||
46
dist/assets/controller-BsNF2rMP.js
vendored
46
dist/assets/controller-BsNF2rMP.js
vendored
@@ -1,46 +0,0 @@
|
||||
class h{constructor(){this.apiUrl="http://localhost:3000"}async request(t,e={}){const s=await fetch(`${this.apiUrl}${t}`,{...e,headers:{"Content-Type":"application/json",...e.headers}});if(!s.ok)throw new Error(`HTTP error! status: ${s.status}`);return await s.json()}async getLikesItems(){try{return await this.request("/likes")}catch(t){return console.error("Ошибка при получении избранного:",t),[]}}async addToLikes(t){try{if(!(await this.getLikesItems()).find(i=>i.id===t.id))return await(await fetch(`${this.apiUrl}/likes`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(t)})).json()}catch(e){console.error("Ошибка при добавлении в избранное:",e)}}async removeFromLikes(t){try{await fetch(`${this.apiUrl}/likes/${t}`,{method:"DELETE"})}catch(e){console.error("Ошибка при удалении из избранного:",e)}}async moveToBasket(t){try{await(await fetch(`${this.apiUrl}/basket`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({...t,quantity:1,addedAt:new Date().toISOString()})})).json(),await this.removeFromLikes(t.id)}catch(e){console.error("Ошибка при переносе товара в корзину:",e)}}}class m{constructor(){this.likesContainer=document.getElementById("likesContainer"),this.emptyLikesElement=document.querySelector(".empty-likes")}showLikes(t){if(!this.likesContainer)return;if(!t||t.length===0){this.showEmptyLikes();return}this.hideEmptyLikes();const e=t.map(s=>this.createLikesItemHTML(s)).join("");this.likesContainer.innerHTML=`
|
||||
<h2 class="mb-4 text-center">Избранное</h2>
|
||||
<div class="row g-3">${e}</div>
|
||||
`}createLikesItemHTML(t){return`
|
||||
<div class="col-md-4">
|
||||
<div class="card h-100 border-0 shadow like-item" data-id="${t.id}">
|
||||
<img src="${t.image}" class="card-img-top" alt="${t.name}">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">${t.name}</h5>
|
||||
<p class="card-text">${t.description}</p>
|
||||
|
||||
<!-- ✅ Добавляем Category и Condition -->
|
||||
<div class="row">
|
||||
<div class="col-6">
|
||||
<h6 class="mb-1">Category:</h6>
|
||||
<p class="card-text">${t.category||"-"}</p>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<h6 class="mb-1">Condition:</h6>
|
||||
<p class="card-text">${t.condition||"-"}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<div class="card-footer bg-transparent">
|
||||
<div class="d-flex justify-content-between align-items-end">
|
||||
<!-- Цена слева -->
|
||||
<span class="fw-bold text-muted fs-3 price-large">$${t.price}</span>
|
||||
|
||||
<!-- Кнопки справа -->
|
||||
<div class="d-flex flex-column gap-1">
|
||||
<button class="btn btn-sm btn-outline-primary move-to-basket-btn">
|
||||
<i class="bi bi-cart-plus"></i> В корзину
|
||||
</button>
|
||||
<button class="btn btn-sm btn-outline-danger remove-like-btn">
|
||||
<i class="bi bi-trash"></i> Удалить
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`}showEmptyLikes(){this.emptyLikesElement&&(this.emptyLikesElement.style.display="block"),this.likesContainer&&(this.likesContainer.innerHTML="")}hideEmptyLikes(){this.emptyLikesElement&&(this.emptyLikesElement.style.display="none")}showNotification(t,e="success"){const s=document.createElement("div");s.className=`alert alert-${e==="success"?"success":"danger"} alert-dismissible fade show`,s.style.cssText="position: fixed; top: 20px; right: 20px; z-index: 1050; min-width: 300px;",s.innerHTML=`
|
||||
${t}
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
|
||||
`,document.body.appendChild(s),setTimeout(()=>{s.parentNode&&s.remove()},3e3)}}class p{constructor(t,e){this.model=t,this.view=e,this.init()}async init(){window.location.pathname.includes("likes.html")&&(await this.loadLikes(),this.setupLikesEventListeners()),window.location.pathname.includes("catalog.html")&&this.setupCatalogEventListeners()}async loadLikes(){const t=await this.model.getLikesItems();this.view.showLikes(t)}setupLikesEventListeners(){document.addEventListener("click",async t=>{const e=t.target.closest(".like-item");if(!e)return;const s=e.dataset.id;if(t.target.closest(".remove-like-btn")&&(await this.model.removeFromLikes(s),this.view.showNotification("Товар удален из избранного"),await this.loadLikes()),t.target.closest(".move-to-basket-btn")){const o=(await this.model.getLikesItems()).find(a=>a.id===s);o&&(await this.model.moveToBasket(o),this.view.showNotification("Товар перенесен в корзину"),await this.loadLikes())}})}setupCatalogEventListeners(){document.addEventListener("click",async t=>{const e=t.target.closest(".card");if(e&&t.target.closest(".like-btn")){const s=this.extractProductData(e);s&&(await this.model.addToLikes(s),this.view.showNotification("Товар добавлен в избранное!"))}})}extractProductData(t){var e,s;try{const i=t.querySelector(".card-title").textContent,o=t.querySelector(".text-muted").textContent.replace("$",""),a=t.querySelector(".card-text").textContent,r=t.querySelector("img").src,c=((e=t.querySelector(".col-6:nth-child(1) p"))==null?void 0:e.textContent.trim())||"",l=((s=t.querySelector(".col-6:nth-child(2) p"))==null?void 0:s.textContent.trim())||"";return{id:btoa(`${i}-${o}`).substring(0,8),name:i.trim(),price:parseFloat(o),description:a.trim(),image:r,category:c,condition:l}}catch(i){return console.error("Ошибка при извлечении данных товара:",i),null}}}export{m as L,p as a,h as b};
|
||||
53
dist/assets/controller-DVj45vQ2.js
vendored
Normal file
53
dist/assets/controller-DVj45vQ2.js
vendored
Normal file
@@ -0,0 +1,53 @@
|
||||
class h{constructor(){this.apiUrl="http://localhost:3000"}async request(t,e={}){const s=await fetch(`${this.apiUrl}${t}`,{...e,headers:{"Content-Type":"application/json",...e.headers}});if(!s.ok)throw new Error(`HTTP error! status: ${s.status}`);return await s.json()}async getLikesItems(){try{return await this.request("/likes")}catch(t){return console.error("Ошибка при получении избранного:",t),[]}}async addToLikes(t){try{if(!(await this.getLikesItems()).find(i=>i.id===t.id))return await(await fetch(`${this.apiUrl}/likes`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(t)})).json()}catch(e){console.error("Ошибка при добавлении в избранное:",e)}}async removeFromLikes(t){try{await fetch(`${this.apiUrl}/likes/${t}`,{method:"DELETE"})}catch(e){console.error("Ошибка при удалении из избранного:",e)}}async clearAllLikes(){try{const t=await this.getLikesItems();for(const e of t)await this.removeFromLikes(e.id)}catch(t){throw console.error("Ошибка при очистке избранного:",t),t}}async moveToBasket(t){try{await(await fetch(`${this.apiUrl}/basket`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({...t,quantity:1,addedAt:new Date().toISOString()})})).json(),await this.removeFromLikes(t.id)}catch(e){console.error("Ошибка при переносе товара в корзину:",e)}}}class m{constructor(){this.likesContainer=document.getElementById("likesContainer"),this.emptyLikesElement=document.querySelector(".empty-likes")}showLikes(t){if(!this.likesContainer)return;if(!t||t.length===0){this.showEmptyLikes();return}this.hideEmptyLikes();const e=t.map(s=>this.createLikesItemHTML(s)).join("");this.likesContainer.innerHTML=`
|
||||
<div class="d-flex justify-content-between align-items-center mb-4">
|
||||
<h2 class="mb-0">Избранное</h2>
|
||||
<button class="btn btn-outline-danger" id="clearAllLikesBtn">
|
||||
<i class="bi bi-trash me-2"></i>Очистить избранное
|
||||
</button>
|
||||
</div>
|
||||
<div class="row g-3">
|
||||
${e}
|
||||
</div>
|
||||
`}createLikesItemHTML(t){return`
|
||||
<div class="col-md-4">
|
||||
<div class="card h-100 border-0 shadow like-item" data-id="${t.id}">
|
||||
<img src="${t.image}" class="card-img-top" alt="${t.name}">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">${t.name}</h5>
|
||||
<p class="card-text">${t.description}</p>
|
||||
|
||||
<!-- Добавляем Category и Condition -->
|
||||
<div class="row">
|
||||
<div class="col-6">
|
||||
<h6 class="mb-1">Category:</h6>
|
||||
<p class="card-text">${t.category||"-"}</p>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<h6 class="mb-1">Condition:</h6>
|
||||
<p class="card-text">${t.condition||"-"}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card-footer bg-transparent">
|
||||
<div class="d-flex justify-content-between align-items-end">
|
||||
<!-- Цена слева -->
|
||||
<span class="fw-bold text-muted fs-3 price-large">$${t.price}</span>
|
||||
|
||||
<!-- Кнопки справа -->
|
||||
<div class="d-flex flex-column gap-1">
|
||||
<button class="btn btn-sm btn-outline-primary move-to-basket-btn">
|
||||
<i class="bi bi-cart-plus"></i> В корзину
|
||||
</button>
|
||||
<button class="btn btn-sm btn-outline-danger remove-like-btn">
|
||||
<i class="bi bi-trash"></i> Удалить
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`}showEmptyLikes(){this.emptyLikesElement&&(this.emptyLikesElement.style.display="block"),this.likesContainer&&(this.likesContainer.innerHTML="")}hideEmptyLikes(){this.emptyLikesElement&&(this.emptyLikesElement.style.display="none")}showNotification(t,e="success"){const s=document.createElement("div");s.className=`alert alert-${e==="success"?"success":"danger"} alert-dismissible fade show`,s.style.cssText="position: fixed; top: 20px; right: 20px; z-index: 1050; min-width: 300px;",s.innerHTML=`
|
||||
${t}
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
|
||||
`,document.body.appendChild(s),setTimeout(()=>{s.parentNode&&s.remove()},3e3)}}class p{constructor(t,e){this.model=t,this.view=e,this.init()}async init(){window.location.pathname.includes("likes.html")&&(await this.loadLikes(),this.setupLikesEventListeners()),window.location.pathname.includes("catalog.html")&&this.setupCatalogEventListeners()}async loadLikes(){const t=await this.model.getLikesItems();this.view.showLikes(t)}setupLikesEventListeners(){document.addEventListener("click",async t=>{const e=t.target.closest(".like-item");if(t.target.closest("#clearAllLikesBtn")){if(confirm("Вы уверены, что хотите очистить всё избранное?"))try{await this.model.clearAllLikes(),this.view.showNotification("Все товары удалены из избранного"),await this.loadLikes()}catch{this.view.showNotification("Ошибка при очистке избранного","error")}return}if(!e)return;const s=e.dataset.id;if(t.target.closest(".remove-like-btn")&&(await this.model.removeFromLikes(s),this.view.showNotification("Товар удален из избранного"),await this.loadLikes()),t.target.closest(".move-to-basket-btn")){const o=(await this.model.getLikesItems()).find(a=>a.id===s);o&&(await this.model.moveToBasket(o),this.view.showNotification("Товар перенесен в корзину"),await this.loadLikes())}})}setupCatalogEventListeners(){document.addEventListener("click",async t=>{const e=t.target.closest(".card");if(e&&t.target.closest(".like-btn")){const s=this.extractProductData(e);s&&(await this.model.addToLikes(s),this.view.showNotification("Товар добавлен в избранное!"))}})}extractProductData(t){var e,s;try{const i=t.querySelector(".card-title").textContent,o=t.querySelector(".text-muted").textContent.replace("$",""),a=t.querySelector(".card-text").textContent,r=t.querySelector("img").src,c=((e=t.querySelector(".col-6:nth-child(1) p"))==null?void 0:e.textContent.trim())||"",l=((s=t.querySelector(".col-6:nth-child(2) p"))==null?void 0:s.textContent.trim())||"";return{id:btoa(`${i}-${o}`).substring(0,8),name:i.trim(),price:parseFloat(o),description:a.trim(),image:r,category:c,condition:l}}catch(i){return console.error("Ошибка при извлечении данных товара:",i),null}}}export{m as L,p as a,h as b};
|
||||
@@ -1 +1 @@
|
||||
import"./modulepreload-polyfill-B5Qt9EMX.js";/* empty css */import{L as t,a as o,b as d}from"./controller-BsNF2rMP.js";import{V as i,C as s,M as r}from"./controller-BHzoImTo.js";document.addEventListener("DOMContentLoaded",function(){if(document.getElementById("productsContainer")){const e=new d,n=new t;new o(e,n)}});document.addEventListener("DOMContentLoaded",function(){if(document.getElementById("basketContainer")||document.getElementById("productsContainer")){const e=new r,n=new i;new s(e,n)}});
|
||||
import"./modulepreload-polyfill-B5Qt9EMX.js";/* empty css */import{L as t,a as o,b as d}from"./controller-DVj45vQ2.js";import{V as i,C as s,M as r}from"./controller-BHzoImTo.js";document.addEventListener("DOMContentLoaded",function(){if(document.getElementById("productsContainer")){const e=new d,n=new t;new o(e,n)}});document.addEventListener("DOMContentLoaded",function(){if(document.getElementById("basketContainer")||document.getElementById("productsContainer")){const e=new r,n=new i;new s(e,n)}});
|
||||
@@ -1 +1 @@
|
||||
import"./modulepreload-polyfill-B5Qt9EMX.js";/* empty css */import{L as o,a as t,b as i}from"./controller-BsNF2rMP.js";document.addEventListener("DOMContentLoaded",function(){if(document.getElementById("likesContainer")){const e=new i,n=new o;new t(e,n)}});
|
||||
import"./modulepreload-polyfill-B5Qt9EMX.js";/* empty css */import{L as o,a as t,b as i}from"./controller-DVj45vQ2.js";document.addEventListener("DOMContentLoaded",function(){if(document.getElementById("likesContainer")){const e=new i,n=new o;new t(e,n)}});
|
||||
367
dist/catalog.html
vendored
367
dist/catalog.html
vendored
@@ -8,27 +8,71 @@
|
||||
<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>
|
||||
.card-actions {
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
right: 10px;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.card-actions .btn {
|
||||
background-color: white !important;
|
||||
border: 1px solid !important;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.card-actions .btn:hover {
|
||||
background-color: white !important;
|
||||
transform: scale(1.1);
|
||||
}
|
||||
|
||||
/* Стили для кнопки редактирования */
|
||||
.card-actions .btn-outline-primary {
|
||||
color: #0d6efd !important;
|
||||
border-color: #0d6efd !important;
|
||||
}
|
||||
|
||||
.card-actions .btn-outline-primary:hover {
|
||||
color: #0d6efd !important;
|
||||
border-color: #0d6efd !important;
|
||||
background-color: white !important;
|
||||
}
|
||||
|
||||
/* Стили для кнопки удаления */
|
||||
.card-actions .btn-outline-danger {
|
||||
color: #dc3545 !important;
|
||||
border-color: #dc3545 !important;
|
||||
}
|
||||
|
||||
.card-actions .btn-outline-danger:hover {
|
||||
color: #dc3545 !important;
|
||||
border-color: #dc3545 !important;
|
||||
background-color: white !important;
|
||||
}
|
||||
|
||||
/* Стили для лайков */
|
||||
.like-btn.liked {
|
||||
color: #000000 !important;
|
||||
border-color: #dc3545 !important;
|
||||
}
|
||||
|
||||
.like-btn.liked i {
|
||||
color: #dc3545 !important;
|
||||
}
|
||||
}
|
||||
|
||||
.like-btn.liked:hover i {
|
||||
text-shadow: 0 0 2px #000000,
|
||||
0 0 2px #000000,
|
||||
text-shadow: 0 0 2px #000000,
|
||||
0 0 2px #000000,
|
||||
0 0 2px #000000;
|
||||
}
|
||||
}
|
||||
|
||||
.like-btn i {
|
||||
transition: text-shadow 0.2s ease;
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
<script type="module" crossorigin src="/assets/page2-Bk9Tmp6W.js"></script>
|
||||
<link rel="modulepreload" crossorigin href="/assets/modulepreload-polyfill-B5Qt9EMX.js">
|
||||
<link rel="modulepreload" crossorigin href="/assets/modulepreload-polyfill-B5Qt9EMX.js">
|
||||
<link rel="modulepreload" crossorigin href="/assets/controller-DVj45vQ2.js">
|
||||
<link rel="modulepreload" crossorigin href="/assets/controller-BHzoImTo.js">
|
||||
<link rel="stylesheet" crossorigin href="/assets/styles-cpwRBDRQ.css">
|
||||
@@ -81,6 +125,62 @@
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<!-- Модальное окно редактирования товара -->
|
||||
<div class="modal fade" id="editProductModal" tabindex="-1" aria-labelledby="editProductModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="editProductModalLabel">Редактировать товар</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form id="editProductForm" class="row g-3">
|
||||
<input type="hidden" id="editProductIndex">
|
||||
<div class="col-md-6">
|
||||
<label for="editProductName" class="form-label">Название товара</label>
|
||||
<input type="text" class="form-control" id="editProductName" required>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label for="editProductPrice" class="form-label">Цена</label>
|
||||
<input type="text" class="form-control" id="editProductPrice" required>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label for="editProductCategory" class="form-label">Категория</label>
|
||||
<select class="form-select" id="editProductCategory" required>
|
||||
<option value="">Выберите категорию</option>
|
||||
<option value="1">Для мужчин</option>
|
||||
<option value="2">Для женщин</option>
|
||||
<option value="3">Унисекс</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label for="editProductCondition" class="form-label">Состояние</label>
|
||||
<select class="form-select" id="editProductCondition" required>
|
||||
<option value="">Выберите состояние</option>
|
||||
<option value="1">Новый</option>
|
||||
<option value="2">Б/У</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<label for="editProductDescription" class="form-label">Описание</label>
|
||||
<textarea class="form-control" id="editProductDescription" rows="3" required></textarea>
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<label for="editProductImage" class="form-label">Ссылка на изображение</label>
|
||||
<input type="text" class="form-control" id="editProductImage" required>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Отмена</button>
|
||||
<button type="button" class="btn" style="background-color: #00264d; color: white;" id="saveProductChanges">
|
||||
<i class="bi bi-check-circle me-2"></i>Сохранить изменения
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<main class="container my-4">
|
||||
<div class="accordion" id="accordionExample">
|
||||
@@ -145,7 +245,15 @@
|
||||
<!-- Карточки товаров -->
|
||||
<div class="row row-cols-1 row-cols-md-2 row-cols-lg-3 g-4 mb-5" id="productsContainer">
|
||||
<!-- Карточка товара 1 -->
|
||||
<div class="col">
|
||||
<div class="col">
|
||||
<div class="card h-100 border-0 shadow position-relative">
|
||||
<div class="card-actions">
|
||||
<button class="btn btn-sm btn-outline-primary edit-btn me-1" data-product-index="0">
|
||||
<i class="bi bi-pencil"></i>
|
||||
</button>
|
||||
<button class="btn btn-sm btn-outline-danger delete-btn">
|
||||
<i class="bi bi-trash"></i>
|
||||
</button>
|
||||
</div>
|
||||
<img src="/assets/stonik-D_cwcHTM.jpg" class="card-img-top" alt="Stone Island">
|
||||
<div class="card-body">
|
||||
@@ -154,17 +262,17 @@
|
||||
|
||||
<div class="row">
|
||||
<div class="col-6">
|
||||
<h5 class="card-text mb-1">Category:</h5>
|
||||
<h5 class="card-text mb-1">Category:</h5>
|
||||
<p class="card-text category-text">men</p>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<h5 class="card-text mb-1">Condition:</h5>
|
||||
<h5 class="card-text mb-1">Condition:</h5>
|
||||
<p class="card-text condition-text">new</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-footer bg-transparent">
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<span class="text-muted price-text">$1999.99</span>
|
||||
<button class="btn btn-sm" style="background-color: #00264d; color: white;">
|
||||
<i class="bi bi-cart-plus me-1"></i>В корзину
|
||||
@@ -183,7 +291,15 @@
|
||||
</div>
|
||||
|
||||
<!-- Карточка товара 2 -->
|
||||
<div class="col">
|
||||
<div class="col">
|
||||
<div class="card h-100 border-0 shadow position-relative">
|
||||
<div class="card-actions">
|
||||
<button class="btn btn-sm btn-outline-primary edit-btn me-1" data-product-index="1">
|
||||
<i class="bi bi-pencil"></i>
|
||||
</button>
|
||||
<button class="btn btn-sm btn-outline-danger delete-btn">
|
||||
<i class="bi bi-trash"></i>
|
||||
</button>
|
||||
</div>
|
||||
<img src="/assets/adidas-gadQV-Lz.jpg" class="card-img-top" alt="Adidas">
|
||||
<div class="card-body">
|
||||
@@ -192,17 +308,17 @@
|
||||
|
||||
<div class="row">
|
||||
<div class="col-6">
|
||||
<h5 class="card-text mb-1">Category:</h5>
|
||||
<h5 class="card-text mb-1">Category:</h5>
|
||||
<p class="card-text category-text">men</p>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<h5 class="card-text mb-1">Condition:</h5>
|
||||
<h5 class="card-text mb-1">Condition:</h5>
|
||||
<p class="card-text condition-text">wu</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-footer bg-transparent">
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<span class="text-muted price-text">$19.99</span>
|
||||
<button class="btn btn-sm" style="background-color: #00264d; color: white;">
|
||||
<i class="bi bi-cart-plus me-1"></i>В корзину
|
||||
@@ -221,7 +337,15 @@
|
||||
</div>
|
||||
|
||||
<!-- Карточка товара 3 -->
|
||||
<div class="col">
|
||||
<div class="col">
|
||||
<div class="card h-100 border-0 shadow position-relative">
|
||||
<div class="card-actions">
|
||||
<button class="btn btn-sm btn-outline-primary edit-btn me-1" data-product-index="2">
|
||||
<i class="bi bi-pencil"></i>
|
||||
</button>
|
||||
<button class="btn btn-sm btn-outline-danger delete-btn">
|
||||
<i class="bi bi-trash"></i>
|
||||
</button>
|
||||
</div>
|
||||
<img src="/assets/napapisaj-DNuXYAGR.jpg" class="card-img-top" alt="Napapisaj">
|
||||
<div class="card-body">
|
||||
@@ -230,17 +354,17 @@
|
||||
|
||||
<div class="row">
|
||||
<div class="col-6">
|
||||
<h5 class="card-text mb-1">Category:</h5>
|
||||
<h5 class="card-text mb-1">Category:</h5>
|
||||
<p class="card-text category-text">men</p>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<h5 class="card-text mb-1">Condition:</h5>
|
||||
<h5 class="card-text mb-1">Condition:</h5>
|
||||
<p class="card-text condition-text">wu</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-footer bg-transparent">
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<span class="text-muted price-text">$1499.99</span>
|
||||
<button class="btn btn-sm" style="background-color: #00264d; color: white;">
|
||||
<i class="bi bi-cart-plus me-1"></i>В корзину
|
||||
@@ -259,7 +383,15 @@
|
||||
</div>
|
||||
|
||||
<!-- Карточка товара 4 -->
|
||||
<div class="col">
|
||||
<div class="col">
|
||||
<div class="card h-100 border-0 shadow position-relative">
|
||||
<div class="card-actions">
|
||||
<button class="btn btn-sm btn-outline-primary edit-btn me-1" data-product-index="3">
|
||||
<i class="bi bi-pencil"></i>
|
||||
</button>
|
||||
<button class="btn btn-sm btn-outline-danger delete-btn">
|
||||
<i class="bi bi-trash"></i>
|
||||
</button>
|
||||
</div>
|
||||
<img src="/assets/lacoste-BSTUvTkt.png" class="card-img-top" alt="Lacoste">
|
||||
<div class="card-body">
|
||||
@@ -268,17 +400,17 @@
|
||||
|
||||
<div class="row">
|
||||
<div class="col-6">
|
||||
<h5 class="card-text mb-1">Category:</h5>
|
||||
<h5 class="card-text mb-1">Category:</h5>
|
||||
<p class="card-text category-text">uni</p>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<h5 class="card-text mb-1">Condition:</h5>
|
||||
<h5 class="card-text mb-1">Condition:</h5>
|
||||
<p class="card-text condition-text">wu</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-footer bg-transparent">
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<span class="text-muted price-text">$399.99</span>
|
||||
<button class="btn btn-sm" style="background-color: #00264d; color: white;">
|
||||
<i class="bi bi-cart-plus me-1"></i>В корзину
|
||||
@@ -297,7 +429,15 @@
|
||||
</div>
|
||||
|
||||
<!-- Карточка товара 5 -->
|
||||
<div class="col">
|
||||
<div class="col">
|
||||
<div class="card h-100 border-0 shadow position-relative">
|
||||
<div class="card-actions">
|
||||
<button class="btn btn-sm btn-outline-primary edit-btn me-1" data-product-index="4">
|
||||
<i class="bi bi-pencil"></i>
|
||||
</button>
|
||||
<button class="btn btn-sm btn-outline-danger delete-btn">
|
||||
<i class="bi bi-trash"></i>
|
||||
</button>
|
||||
</div>
|
||||
<img src="/assets/samba-C8wu5LAG.png" class="card-img-top" alt="Samba">
|
||||
<div class="card-body">
|
||||
@@ -306,17 +446,17 @@
|
||||
|
||||
<div class="row">
|
||||
<div class="col-6">
|
||||
<h5 class="card-text mb-1">Category:</h5>
|
||||
<h5 class="card-text mb-1">Category:</h5>
|
||||
<p class="card-text category-text">women</p>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<h5 class="card-text mb-1">Condition:</h5>
|
||||
<h5 class="card-text mb-1">Condition:</h5>
|
||||
<p class="card-text condition-text">new</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-footer bg-transparent">
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<span class="text-muted price-text">$449.99</span>
|
||||
<button class="btn btn-sm" style="background-color: #00264d; color: white;">
|
||||
<i class="bi bi-cart-plus me-1"></i>В корзину
|
||||
@@ -364,6 +504,112 @@
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
|
||||
|
||||
<script>
|
||||
// Функция для открытия модального окна редактирования
|
||||
function openEditModal(productIndex) {
|
||||
const card = document.querySelectorAll('#productsContainer .col')[productIndex];
|
||||
|
||||
// Получаем текущие данные карточки
|
||||
const title = card.querySelector('.card-title').textContent;
|
||||
const description = card.querySelector('.card-text').textContent;
|
||||
const price = card.querySelector('.price-text').textContent;
|
||||
const category = card.querySelector('.category-text').textContent;
|
||||
const condition = card.querySelector('.condition-text').textContent;
|
||||
const image = card.querySelector('.card-img-top').src;
|
||||
|
||||
// Заполняем форму редактирования
|
||||
document.getElementById('editProductName').value = title;
|
||||
document.getElementById('editProductDescription').value = description;
|
||||
document.getElementById('editProductPrice').value = price;
|
||||
document.getElementById('editProductImage').value = image;
|
||||
|
||||
// Устанавливаем выбранные значения для категории и состояния
|
||||
setSelectValue('editProductCategory', getCategoryValue(category));
|
||||
setSelectValue('editProductCondition', getConditionValue(condition));
|
||||
|
||||
// Сохраняем индекс редактируемого товара
|
||||
document.getElementById('editProductIndex').value = productIndex;
|
||||
|
||||
// Показываем модальное окно
|
||||
const editModal = new bootstrap.Modal(document.getElementById('editProductModal'));
|
||||
editModal.show();
|
||||
}
|
||||
|
||||
// Функция для установки значения в select
|
||||
function setSelectValue(selectId, value) {
|
||||
const select = document.getElementById(selectId);
|
||||
for (let i = 0; i < select.options.length; i++) {
|
||||
if (select.options[i].value === value) {
|
||||
select.selectedIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Функция для получения значения категории из текста
|
||||
function getCategoryValue(categoryText) {
|
||||
switch(categoryText.toLowerCase()) {
|
||||
case 'men': return '1';
|
||||
case 'women': return '2';
|
||||
case 'uni': return '3';
|
||||
default: return '1';
|
||||
}
|
||||
}
|
||||
|
||||
// Функция для получения текста категории из значения
|
||||
function getCategoryText(categoryValue) {
|
||||
switch(categoryValue) {
|
||||
case '1': return 'men';
|
||||
case '2': return 'women';
|
||||
case '3': return 'uni';
|
||||
default: return 'men';
|
||||
}
|
||||
}
|
||||
|
||||
// Функция для получения значения состояния из текста
|
||||
function getConditionValue(conditionText) {
|
||||
switch(conditionText.toLowerCase()) {
|
||||
case 'new': return '1';
|
||||
case 'wu': return '2';
|
||||
default: return '1';
|
||||
}
|
||||
}
|
||||
|
||||
// Функция для получения текста состояния из значения
|
||||
function getConditionText(conditionValue) {
|
||||
switch(conditionValue) {
|
||||
case '1': return 'new';
|
||||
case '2': return 'wu';
|
||||
default: return 'new';
|
||||
}
|
||||
}
|
||||
|
||||
// Обработчик сохранения изменений
|
||||
document.getElementById('saveProductChanges').addEventListener('click', function() {
|
||||
const productIndex = document.getElementById('editProductIndex').value;
|
||||
const card = document.querySelectorAll('#productsContainer .col')[productIndex];
|
||||
|
||||
// Получаем новые значения из формы
|
||||
const newTitle = document.getElementById('editProductName').value;
|
||||
const newDescription = document.getElementById('editProductDescription').value;
|
||||
const newPrice = document.getElementById('editProductPrice').value;
|
||||
const newCategory = document.getElementById('editProductCategory').value;
|
||||
const newCondition = document.getElementById('editProductCondition').value;
|
||||
const newImage = document.getElementById('editProductImage').value;
|
||||
|
||||
// Обновляем карточку
|
||||
card.querySelector('.card-title').textContent = newTitle;
|
||||
card.querySelector('.card-text').textContent = newDescription;
|
||||
card.querySelector('.price-text').textContent = newPrice;
|
||||
card.querySelector('.category-text').textContent = getCategoryText(newCategory);
|
||||
card.querySelector('.condition-text').textContent = getConditionText(newCondition);
|
||||
card.querySelector('.card-img-top').src = newImage;
|
||||
card.querySelector('.card-img-top').alt = newTitle;
|
||||
|
||||
// Закрываем модальное окно
|
||||
const editModal = bootstrap.Modal.getInstance(document.getElementById('editProductModal'));
|
||||
editModal.hide();
|
||||
});
|
||||
|
||||
document.getElementById("addProductForm").addEventListener("submit", function (e) {
|
||||
e.preventDefault();
|
||||
@@ -374,12 +620,20 @@
|
||||
const description = document.getElementById("productDescription").value;
|
||||
const image = document.getElementById("productImage").value;
|
||||
|
||||
// Получаем текстовые значения для отображения
|
||||
const categoryText = document.getElementById("productCategory").options[document.getElementById("productCategory").selectedIndex].text;
|
||||
// Получаем текстовые значения для отображения
|
||||
const categoryText = getCategoryText(category);
|
||||
const conditionText = getConditionText(condition);
|
||||
|
||||
const productCard = `
|
||||
<div class="col">
|
||||
<div class="col">
|
||||
<div class="card h-100 border-0 shadow position-relative">
|
||||
<div class="card-actions">
|
||||
<button class="btn btn-sm btn-outline-primary edit-btn me-1" data-product-index="${document.querySelectorAll('#productsContainer .col').length}">
|
||||
<i class="bi bi-pencil"></i>
|
||||
</button>
|
||||
<button class="btn btn-sm btn-outline-danger delete-btn">
|
||||
<i class="bi bi-trash"></i>
|
||||
</button>
|
||||
</div>
|
||||
<img src="${image}" class="card-img-top" alt="${name}">
|
||||
<div class="card-body">
|
||||
@@ -387,17 +641,17 @@
|
||||
<p class="card-text">${description}</p>
|
||||
<div class="row">
|
||||
<div class="col-6">
|
||||
<h5 class="card-text mb-1">Category:</h5>
|
||||
<h5 class="card-text mb-1">Category:</h5>
|
||||
<p class="card-text category-text">${categoryText}</p>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<h5 class="card-text mb-1">Condition:</h5>
|
||||
<h5 class="card-text mb-1">Condition:</h5>
|
||||
<p class="card-text condition-text">${conditionText}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-footer bg-transparent">
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<span class="text-muted price-text">${price}</span>
|
||||
<button class="btn btn-sm" style="background-color: #00264d; color: white;">
|
||||
<i class="bi bi-cart-plus me-1"></i>В корзину
|
||||
@@ -416,8 +670,57 @@
|
||||
</div>
|
||||
`;
|
||||
|
||||
document.getElementById("productsContainer").insertAdjacentHTML("beforeend", productCard);
|
||||
|
||||
// Добавляем обработчики событий для новых кнопок
|
||||
addEventListenersToNewCard();
|
||||
|
||||
this.reset();
|
||||
});
|
||||
|
||||
// Функция для добавления обработчиков событий к новым карточкам
|
||||
function addEventListenersToNewCard() {
|
||||
const lastCard = document.querySelector('#productsContainer .col:last-child');
|
||||
const editBtn = lastCard.querySelector('.edit-btn');
|
||||
const deleteBtn = lastCard.querySelector('.delete-btn');
|
||||
|
||||
editBtn.addEventListener('click', function() {
|
||||
const productIndex = this.getAttribute('data-product-index');
|
||||
openEditModal(productIndex);
|
||||
});
|
||||
|
||||
deleteBtn.addEventListener('click', function() {
|
||||
const card = this.closest('.col');
|
||||
const title = card.querySelector('.card-title').textContent;
|
||||
|
||||
if (confirm(`Вы уверены, что хотите удалить товар "${title}"?`)) {
|
||||
card.remove();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Добавляем обработчики событий для существующих карточек
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const editButtons = document.querySelectorAll('.edit-btn');
|
||||
const deleteButtons = document.querySelectorAll('.delete-btn');
|
||||
|
||||
editButtons.forEach(btn => {
|
||||
btn.addEventListener('click', function() {
|
||||
const productIndex = this.getAttribute('data-product-index');
|
||||
openEditModal(productIndex);
|
||||
});
|
||||
});
|
||||
|
||||
deleteButtons.forEach(btn => {
|
||||
btn.addEventListener('click', function() {
|
||||
const card = this.closest('.col');
|
||||
const title = card.querySelector('.card-title').textContent;
|
||||
|
||||
if (confirm(`Вы уверены, что хотите удалить товар "${title}"?`)) {
|
||||
card.remove();
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
4
dist/likes.html
vendored
4
dist/likes.html
vendored
@@ -7,9 +7,9 @@
|
||||
<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">
|
||||
|
||||
|
||||
<script type="module" crossorigin src="/assets/page4-DL921iBt.js"></script>
|
||||
<link rel="modulepreload" crossorigin href="/assets/modulepreload-polyfill-B5Qt9EMX.js">
|
||||
<link rel="modulepreload" crossorigin href="/assets/modulepreload-polyfill-B5Qt9EMX.js">
|
||||
<link rel="modulepreload" crossorigin href="/assets/controller-DVj45vQ2.js">
|
||||
<link rel="stylesheet" crossorigin href="/assets/styles-cpwRBDRQ.css">
|
||||
</head>
|
||||
|
||||
Reference in New Issue
Block a user