add price policy
This commit is contained in:
@@ -8,6 +8,136 @@
|
||||
<link rel="stylesheet" href="assets/css/style.css">
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
|
||||
</head>
|
||||
<style>
|
||||
|
||||
.filter-modal {
|
||||
max-width: 400px;
|
||||
max-height: 80vh;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.filter-group {
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.filter-group-title {
|
||||
font-weight: 600;
|
||||
margin-bottom: 12px;
|
||||
color: #1f2937;
|
||||
}
|
||||
|
||||
.filter-options {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.filter-checkbox {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.filter-checkbox input {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.price-range input {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.modal-overlay {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: rgba(0,0,0,0.5);
|
||||
z-index: 1000;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.modal-content {
|
||||
background: white;
|
||||
border-radius: 12px;
|
||||
width: 100%;
|
||||
max-width: 500px;
|
||||
animation: slideUp 0.3s ease;
|
||||
}
|
||||
|
||||
@keyframes slideUp {
|
||||
from { transform: translateY(20px); opacity: 0; }
|
||||
to { transform: translateY(0); opacity: 1; }
|
||||
}
|
||||
|
||||
.modal-header {
|
||||
padding: 20px;
|
||||
border-bottom: 1px solid #e5e7eb;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.modal-body {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.modal-footer {
|
||||
padding: 20px;
|
||||
border-top: 1px solid #e5e7eb;
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.modal-close {
|
||||
background: none;
|
||||
border: none;
|
||||
font-size: 20px;
|
||||
color: #6b7280;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.badge {
|
||||
display: inline-block;
|
||||
padding: 2px 6px;
|
||||
border-radius: 12px;
|
||||
font-size: 11px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.badge-primary {
|
||||
background: #005B9A;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.heart-btn {
|
||||
background: none;
|
||||
border: none;
|
||||
color: #d1d5db;
|
||||
font-size: 16px;
|
||||
cursor: pointer;
|
||||
transition: color 0.2s;
|
||||
}
|
||||
|
||||
.heart-btn.active {
|
||||
color: #ef4444;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.products-grid {
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
}
|
||||
|
||||
.modal-content {
|
||||
margin: 20px;
|
||||
/*max-height: calc(100vh - 40px);*/
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<body>
|
||||
<div class="page-wrapper">
|
||||
<!-- Header -->
|
||||
@@ -24,19 +154,198 @@
|
||||
|
||||
<div class="container">
|
||||
<!-- Search Bar -->
|
||||
<div class="search-bar">
|
||||
<!--<div class="search-bar">
|
||||
<i class="fas fa-search search-icon"></i>
|
||||
<input type="text" class="search-input" placeholder="Tìm kiếm sản phẩm...">
|
||||
</div>-->
|
||||
|
||||
<!-- Search Bar & Filter Button -->
|
||||
<div class="flex gap-2 mb-4" style="margin-bottom: 0px;">
|
||||
<div class="search-bar flex-1">
|
||||
<i class="fas fa-search search-icon"></i>
|
||||
<input type="text" class="search-input" placeholder="Tìm kiếm sản phẩm" id="searchInput">
|
||||
</div>
|
||||
<button class="btn btn-secondary" id="filterBtn" onclick="openFilterModal()" style="min-width: auto;padding: 12px 8px;border-bottom-width: 0px;border-top-width: 0px;/* height: 69px; */margin-bottom: 16px;">
|
||||
<i class="fas fa-filter"></i>
|
||||
<span class="ml-1">Lọc</span>
|
||||
<span class="badge badge-primary ml-2" id="filterCount" style="display: none;">0</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- Filter Modal -->
|
||||
<div id="filterModal" class="modal-overlay" style="display: none;">
|
||||
<div class="modal-content filter-modal">
|
||||
<div class="modal-header">
|
||||
<h3 class="modal-title" style="font-weight: 600;">Bộ lọc sản phẩm</h3>
|
||||
<button class="modal-close" onclick="closeFilterModal()">
|
||||
<i class="fas fa-times"></i>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<!-- Dòng sản phẩm -->
|
||||
<div class="filter-group">
|
||||
<h4 class="filter-group-title">Dòng sản phẩm</h4>
|
||||
<div class="filter-options">
|
||||
<label class="filter-checkbox">
|
||||
<input type="checkbox" value="tam-lon"> Tấm lớn
|
||||
</label>
|
||||
<label class="filter-checkbox">
|
||||
<input type="checkbox" value="third-firing"> Third-Firing
|
||||
</label>
|
||||
<label class="filter-checkbox">
|
||||
<input type="checkbox" value="outdoor"> Outdoor
|
||||
</label>
|
||||
<label class="filter-checkbox">
|
||||
<input type="checkbox" value="van-da"> Vân đá
|
||||
</label>
|
||||
<label class="filter-checkbox">
|
||||
<input type="checkbox" value="xi-mang"> Xi măng
|
||||
</label>
|
||||
<label class="filter-checkbox">
|
||||
<input type="checkbox" value="van-go"> Vân gỗ
|
||||
</label>
|
||||
<label class="filter-checkbox">
|
||||
<input type="checkbox" value="xuong-trang"> Xương trắng
|
||||
</label>
|
||||
<label class="filter-checkbox">
|
||||
<input type="checkbox" value="cam-thach"> Cẩm thạch
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Không gian -->
|
||||
<div class="filter-group">
|
||||
<h4 class="filter-group-title">Không gian</h4>
|
||||
<div class="filter-options">
|
||||
<label class="filter-checkbox">
|
||||
<input type="checkbox" value="phong-khach"> Phòng khách
|
||||
</label>
|
||||
<label class="filter-checkbox">
|
||||
<input type="checkbox" value="phong-ngu"> Phòng ngủ
|
||||
</label>
|
||||
<label class="filter-checkbox">
|
||||
<input type="checkbox" value="phong-tam"> Phòng tắm
|
||||
</label>
|
||||
<label class="filter-checkbox">
|
||||
<input type="checkbox" value="nha-bep"> Nhà bếp
|
||||
</label>
|
||||
<label class="filter-checkbox">
|
||||
<input type="checkbox" value="khong-gian-khac"> Không gian khác
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Kích thước -->
|
||||
<div class="filter-group">
|
||||
<h4 class="filter-group-title">Kích thước</h4>
|
||||
<div class="filter-options">
|
||||
<label class="filter-checkbox">
|
||||
<input type="checkbox" value="200x1600"> 200x1600
|
||||
</label>
|
||||
<label class="filter-checkbox">
|
||||
<input type="checkbox" value="1200x2400"> 1200x2400
|
||||
</label>
|
||||
<label class="filter-checkbox">
|
||||
<input type="checkbox" value="7500x1500"> 7500x1500
|
||||
</label>
|
||||
<label class="filter-checkbox">
|
||||
<input type="checkbox" value="1200x1200"> 1200x1200
|
||||
</label>
|
||||
<label class="filter-checkbox">
|
||||
<input type="checkbox" value="600x1200"> 600x1200
|
||||
</label>
|
||||
<label class="filter-checkbox">
|
||||
<input type="checkbox" value="450x900"> 450x900
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Bề mặt -->
|
||||
<div class="filter-group">
|
||||
<h4 class="filter-group-title">Bề mặt</h4>
|
||||
<div class="filter-options">
|
||||
<label class="filter-checkbox">
|
||||
<input type="checkbox" value="satin"> SATIN
|
||||
</label>
|
||||
<label class="filter-checkbox">
|
||||
<input type="checkbox" value="honed"> HONED
|
||||
</label>
|
||||
<label class="filter-checkbox">
|
||||
<input type="checkbox" value="matt"> MATT
|
||||
</label>
|
||||
<label class="filter-checkbox">
|
||||
<input type="checkbox" value="polish"> POLISH
|
||||
</label>
|
||||
<label class="filter-checkbox">
|
||||
<input type="checkbox" value="babyskin"> BABYSKIN
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Khoảng giá -->
|
||||
<!--<div class="filter-group">
|
||||
<h4 class="filter-group-title">Khoảng giá</h4>
|
||||
<div class="price-range">
|
||||
<div class="flex gap-2 items-center">
|
||||
<input type="number" class="form-control" placeholder="Từ" id="priceMin">
|
||||
<span>-</span>
|
||||
<input type="number" class="form-control" placeholder="Đến" id="priceMax">
|
||||
<span class="text-sm">VNĐ/m²</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>-->
|
||||
|
||||
<!-- Thương hiệu -->
|
||||
<div class="filter-group">
|
||||
<h4 class="filter-group-title">Thương hiệu</h4>
|
||||
<div class="filter-options">
|
||||
<label class="filter-checkbox">
|
||||
<input type="checkbox" value="eurotile"> Eurotile
|
||||
</label>
|
||||
<label class="filter-checkbox">
|
||||
<input type="checkbox" value="vasta-stone"> Vasta Stone
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button class="btn btn-secondary flex-1" onclick="resetFilters()">Xóa bộ lọc</button>
|
||||
<button class="btn btn-primary flex-1" onclick="applyFilters()">Áp dụng</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Info Modal -->
|
||||
<div id="infoModal" class="modal-overlay" style="display: none;">
|
||||
<div class="modal-content info-modal">
|
||||
<div class="modal-header">
|
||||
<h3 class="modal-title">Hướng dẫn sử dụng</h3>
|
||||
<button class="modal-close" onclick="closeInfoModal()">
|
||||
<i class="fas fa-times"></i>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p>Đây là nội dung hướng dẫn sử dụng cho tính năng Sản phẩm:</p>
|
||||
<ul class="list-disc ml-6 mt-3">
|
||||
<li>Sử dụng thanh tìm kiếm để tìm sản phẩm theo tên hoặc mã</li>
|
||||
<li>Nhấn "Bộ lọc" để lọc sản phẩm theo nhiều tiêu chí</li>
|
||||
<li>Chuyển đổi giữa chế độ xem lưới và danh sách</li>
|
||||
<li>Nhấn vào sản phẩm để xem chi tiết</li>
|
||||
<li>Thêm sản phẩm yêu thích bằng icon tim</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button class="btn btn-primary" onclick="closeInfoModal()">Đóng</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Filter Pills -->
|
||||
<div class="filter-container">
|
||||
<button class="filter-pill active">Tất cả</button>
|
||||
<button class="filter-pill">Gạch lát nền</button>
|
||||
<button class="filter-pill">Gạch ốp tường</button>
|
||||
<button class="filter-pill">Gạch trang trí</button>
|
||||
<button class="filter-pill">Gạch ngoài trời</button>
|
||||
<button class="filter-pill">Phụ kiện</button>
|
||||
<button class="filter-pill">Eurotile</button>
|
||||
<button class="filter-pill">Vasta</button>
|
||||
<button class="filter-pill">Gia công</button>
|
||||
</div>
|
||||
|
||||
<!-- Product Grid -->
|
||||
@@ -143,7 +452,208 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<script>
|
||||
|
||||
let filteredProducts = [...products];
|
||||
let currentView = 'grid';
|
||||
let activeFilters = {
|
||||
categories: [],
|
||||
spaces: [],
|
||||
sizes: [],
|
||||
surfaces: [],
|
||||
brands: [],
|
||||
priceRange: { min: null, max: null }
|
||||
};
|
||||
|
||||
// Initialize page
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
renderProducts();
|
||||
});
|
||||
|
||||
function renderProducts() {
|
||||
const gridContainer = document.getElementById('productsGrid');
|
||||
const listContainer = document.getElementById('productsList');
|
||||
|
||||
document.getElementById('productCount').textContent = filteredProducts.length;
|
||||
|
||||
if (currentView === 'grid') {
|
||||
gridContainer.innerHTML = filteredProducts.map(product => `
|
||||
<div class="product-item" onclick="viewProduct('${product.id}')">
|
||||
<img src="${product.image}" alt="${product.name}" class="product-image">
|
||||
<div class="product-info">
|
||||
<div class="product-name">${product.name}</div>
|
||||
<div class="product-code">${product.code}</div>
|
||||
<div class="product-actions">
|
||||
<div class="product-price">${formatPrice(product.price)}</div>
|
||||
<button class="heart-btn" onclick="toggleFavorite('${product.id}', event)">
|
||||
<i class="far fa-heart"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`).join('');
|
||||
} else {
|
||||
listContainer.innerHTML = filteredProducts.map(product => `
|
||||
<div class="product-item" onclick="viewProduct('${product.id}')">
|
||||
<img src="${product.image}" alt="${product.name}" class="product-image">
|
||||
<div class="product-info">
|
||||
<div class="product-name">${product.name}</div>
|
||||
<div class="product-code">${product.code}</div>
|
||||
<div class="product-actions">
|
||||
<div class="product-price">${formatPrice(product.price)}</div>
|
||||
<button class="heart-btn" onclick="toggleFavorite('${product.id}', event)">
|
||||
<i class="far fa-heart"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`).join('');
|
||||
}
|
||||
}
|
||||
|
||||
function toggleView(view) {
|
||||
currentView = view;
|
||||
|
||||
// Update button states
|
||||
document.querySelectorAll('.btn-view').forEach(btn => {
|
||||
btn.classList.remove('active');
|
||||
});
|
||||
document.querySelector(`[data-view="${view}"]`).classList.add('active');
|
||||
|
||||
// Show/hide containers
|
||||
document.getElementById('productsGrid').style.display = view === 'grid' ? 'grid' : 'none';
|
||||
document.getElementById('productsList').style.display = view === 'list' ? 'block' : 'none';
|
||||
|
||||
renderProducts();
|
||||
}
|
||||
|
||||
function openFilterModal() {
|
||||
document.getElementById('filterModal').style.display = 'flex';
|
||||
}
|
||||
|
||||
function closeFilterModal() {
|
||||
document.getElementById('filterModal').style.display = 'none';
|
||||
}
|
||||
|
||||
function applyFilters() {
|
||||
// Collect filter values
|
||||
activeFilters.categories = Array.from(document.querySelectorAll('input[type="checkbox"]:checked'))
|
||||
.map(cb => cb.value)
|
||||
.filter(val => ['tam-lon', 'third-firing', 'outdoor', 'van-da', 'xi-mang', 'van-go', 'xuong-trang', 'cam-thach'].includes(val));
|
||||
|
||||
activeFilters.spaces = Array.from(document.querySelectorAll('input[type="checkbox"]:checked'))
|
||||
.map(cb => cb.value)
|
||||
.filter(val => ['phong-khach', 'phong-ngu', 'phong-tam', 'nha-bep', 'khong-gian-khac'].includes(val));
|
||||
|
||||
// Apply filters
|
||||
filteredProducts = products.filter(product => {
|
||||
if (activeFilters.categories.length && !activeFilters.categories.includes(product.category)) return false;
|
||||
if (activeFilters.spaces.length && !product.space.some(s => activeFilters.spaces.includes(s))) return false;
|
||||
return true;
|
||||
});
|
||||
|
||||
// Update filter count badge
|
||||
const totalFilters = activeFilters.categories.length + activeFilters.spaces.length;
|
||||
const badge = document.getElementById('filterCount');
|
||||
if (totalFilters > 0) {
|
||||
badge.style.display = 'inline';
|
||||
badge.textContent = totalFilters;
|
||||
} else {
|
||||
badge.style.display = 'none';
|
||||
}
|
||||
|
||||
renderProducts();
|
||||
closeFilterModal();
|
||||
}
|
||||
|
||||
function resetFilters() {
|
||||
// Uncheck all checkboxes
|
||||
document.querySelectorAll('#filterModal input[type="checkbox"]').forEach(cb => {
|
||||
cb.checked = false;
|
||||
});
|
||||
|
||||
// Reset price range
|
||||
document.getElementById('priceMin').value = '';
|
||||
document.getElementById('priceMax').value = '';
|
||||
|
||||
// Reset filters
|
||||
activeFilters = {
|
||||
categories: [],
|
||||
spaces: [],
|
||||
sizes: [],
|
||||
surfaces: [],
|
||||
brands: [],
|
||||
priceRange: { min: null, max: null }
|
||||
};
|
||||
|
||||
filteredProducts = [...products];
|
||||
document.getElementById('filterCount').style.display = 'none';
|
||||
|
||||
renderProducts();
|
||||
}
|
||||
|
||||
function viewProduct(productId) {
|
||||
window.location.href = `product-detail.html?id=${productId}`;
|
||||
}
|
||||
|
||||
function toggleFavorite(productId, event) {
|
||||
event.stopPropagation();
|
||||
const btn = event.currentTarget;
|
||||
const icon = btn.querySelector('i');
|
||||
|
||||
btn.classList.toggle('active');
|
||||
if (btn.classList.contains('active')) {
|
||||
icon.classList.remove('far');
|
||||
icon.classList.add('fas');
|
||||
} else {
|
||||
icon.classList.remove('fas');
|
||||
icon.classList.add('far');
|
||||
}
|
||||
}
|
||||
|
||||
function openInfoModal() {
|
||||
document.getElementById('infoModal').style.display = 'flex';
|
||||
}
|
||||
|
||||
function closeInfoModal() {
|
||||
document.getElementById('infoModal').style.display = 'none';
|
||||
}
|
||||
|
||||
function formatPrice(price) {
|
||||
return new Intl.NumberFormat('vi-VN', {
|
||||
style: 'currency',
|
||||
currency: 'VND'
|
||||
}).format(price);
|
||||
}
|
||||
|
||||
// Search functionality
|
||||
document.getElementById('searchInput').addEventListener('input', function(e) {
|
||||
const searchTerm = e.target.value.toLowerCase();
|
||||
|
||||
filteredProducts = products.filter(product => {
|
||||
const matchesSearch = product.name.toLowerCase().includes(searchTerm) ||
|
||||
product.code.toLowerCase().includes(searchTerm);
|
||||
|
||||
if (!matchesSearch) return false;
|
||||
|
||||
// Apply other filters too
|
||||
if (activeFilters.categories.length && !activeFilters.categories.includes(product.category)) return false;
|
||||
if (activeFilters.spaces.length && !product.space.some(s => activeFilters.spaces.includes(s))) return false;
|
||||
|
||||
return true;
|
||||
});
|
||||
|
||||
renderProducts();
|
||||
});
|
||||
|
||||
// Close modal when clicking outside
|
||||
document.addEventListener('click', function(e) {
|
||||
if (e.target.classList.contains('modal-overlay')) {
|
||||
e.target.style.display = 'none';
|
||||
}
|
||||
});
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user