update normal sale
This commit is contained in:
parent
b6bf7b7b5e
commit
2f1d29f034
5
cookies_login.txt
Normal file
5
cookies_login.txt
Normal file
@ -0,0 +1,5 @@
|
||||
# Netscape HTTP Cookie File
|
||||
# https://curl.se/docs/http-cookies.html
|
||||
# This file was generated by libcurl! Edit at your own risk.
|
||||
|
||||
127.0.0.1 FALSE / FALSE 0 PHPSESSID 3lfjkalu291jmcfc01kbpt4umj
|
||||
5
cookies_login_owner.txt
Normal file
5
cookies_login_owner.txt
Normal file
@ -0,0 +1,5 @@
|
||||
# Netscape HTTP Cookie File
|
||||
# https://curl.se/docs/http-cookies.html
|
||||
# This file was generated by libcurl! Edit at your own risk.
|
||||
|
||||
127.0.0.1 FALSE / FALSE 0 PHPSESSID 43km9i3a7704fr6prmt70vau78
|
||||
@ -9,7 +9,7 @@ require_once __DIR__ . '/../db/config.php';
|
||||
|
||||
// Auto-migrate newly added columns
|
||||
try {
|
||||
$flagFile = sys_get_temp_dir() . '/.migrated_avatar_col_' . md5(__DIR__);
|
||||
$flagFile = sys_get_temp_dir() . '/.schema_migrated_v2_' . md5(__DIR__);
|
||||
if (!file_exists($flagFile)) {
|
||||
$pdo = db();
|
||||
$stmt = $pdo->query("SHOW COLUMNS FROM users LIKE 'avatar'");
|
||||
@ -28,6 +28,10 @@ try {
|
||||
if ($stmt4->rowCount() === 0) {
|
||||
$pdo->exec("ALTER TABLE sales_orders ADD COLUMN payment_status varchar(20) NOT NULL DEFAULT 'paid'");
|
||||
}
|
||||
$stmt5 = $pdo->query("SHOW COLUMNS FROM sales_orders LIKE 'vat_amount'");
|
||||
if ($stmt5->rowCount() === 0) {
|
||||
$pdo->exec("ALTER TABLE sales_orders ADD COLUMN vat_amount decimal(10,3) NOT NULL DEFAULT 0.000 AFTER subtotal");
|
||||
}
|
||||
@file_put_contents($flagFile, '1');
|
||||
}
|
||||
} catch (\Throwable $e) {}
|
||||
@ -340,6 +344,7 @@ function ensure_sales_table(): void
|
||||
items_json LONGTEXT NOT NULL,
|
||||
item_count INT UNSIGNED NOT NULL DEFAULT 0,
|
||||
subtotal DECIMAL(10,2) NOT NULL DEFAULT 0,
|
||||
vat_amount DECIMAL(10,3) NOT NULL DEFAULT 0.000,
|
||||
total_amount DECIMAL(10,2) NOT NULL DEFAULT 0,
|
||||
status VARCHAR(20) NOT NULL DEFAULT 'completed',
|
||||
notes TEXT DEFAULT NULL,
|
||||
|
||||
179
shop.php
179
shop.php
@ -70,6 +70,32 @@ body { background-color: #f8f9fa; }
|
||||
-ms-overflow-style: none;
|
||||
scrollbar-width: none;
|
||||
}
|
||||
.shop-pagination-wrap {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 12px;
|
||||
}
|
||||
.shop-pagination-status {
|
||||
color: #6c757d;
|
||||
font-weight: 600;
|
||||
}
|
||||
.shop-pagination .page-link {
|
||||
border-radius: 999px !important;
|
||||
margin: 0 4px;
|
||||
border: 0;
|
||||
box-shadow: 0 3px 10px rgba(0,0,0,0.06);
|
||||
color: #0d6efd;
|
||||
}
|
||||
.shop-pagination .page-item.active .page-link {
|
||||
background: #0d6efd;
|
||||
color: #fff;
|
||||
}
|
||||
.shop-pagination .page-item.disabled .page-link {
|
||||
color: #adb5bd;
|
||||
box-shadow: none;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="container py-5">
|
||||
@ -86,7 +112,7 @@ body { background-color: #f8f9fa; }
|
||||
|
||||
<?php if (!empty($catalog)): ?>
|
||||
<!-- Search and Filter -->
|
||||
<div class="row mb-5">
|
||||
<div class="row mb-4">
|
||||
<div class="col-md-6 mb-3 mb-md-0">
|
||||
<div class="input-group input-group-lg shadow-sm rounded-pill overflow-hidden">
|
||||
<span class="input-group-text bg-white border-0 ps-4"><i class="bi bi-search text-muted"></i></span>
|
||||
@ -102,6 +128,14 @@ body { background-color: #f8f9fa; }
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="shop-pagination-wrap bg-white p-3 rounded-4 shadow-sm mb-4">
|
||||
<div class="shop-pagination-status" id="paginationStatus">
|
||||
<?= h(tr('جارٍ تحميل المنتجات...', 'Loading products...')) ?>
|
||||
</div>
|
||||
<nav aria-label="<?= h(tr('تنقل الصفحات', 'Product pagination')) ?>">
|
||||
<ul class="pagination pagination-sm mb-0 shop-pagination" id="paginationTop"></ul>
|
||||
</nav>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if (empty($catalog)): ?>
|
||||
@ -146,6 +180,13 @@ body { background-color: #f8f9fa; }
|
||||
<i class="bi bi-search display-1 text-muted opacity-50 mb-3 d-block"></i>
|
||||
<h3 class="text-muted"><?= h(tr('لم يتم العثور على نتائج', 'No results found')) ?></h3>
|
||||
</div>
|
||||
|
||||
<div class="shop-pagination-wrap bg-white p-3 rounded-4 shadow-sm mt-4" id="paginationFooter">
|
||||
<div class="shop-pagination-status" id="paginationStatusBottom"></div>
|
||||
<nav aria-label="<?= h(tr('تنقل الصفحات', 'Product pagination')) ?>">
|
||||
<ul class="pagination pagination-sm mb-0 shop-pagination" id="paginationBottom"></ul>
|
||||
</nav>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
@ -362,69 +403,149 @@ async function submitOrder() {
|
||||
}
|
||||
}
|
||||
|
||||
// Filtering Logic
|
||||
// Filtering + Pagination Logic
|
||||
let currentCategory = 'all';
|
||||
let currentPage = 1;
|
||||
const itemsPerPage = 24;
|
||||
|
||||
function setCategoryFilter(cat, btn) {
|
||||
currentCategory = cat;
|
||||
|
||||
// Update active button state
|
||||
currentPage = 1;
|
||||
|
||||
document.querySelectorAll('#categoryFilters button').forEach(b => {
|
||||
b.classList.remove('btn-primary', 'active');
|
||||
b.classList.add('btn-light', 'text-dark');
|
||||
});
|
||||
btn.classList.remove('btn-light', 'text-dark');
|
||||
btn.classList.add('btn-primary', 'active');
|
||||
|
||||
|
||||
filterProducts();
|
||||
}
|
||||
|
||||
function filterProducts() {
|
||||
function getFilteredItems() {
|
||||
const searchInput = document.getElementById('searchInput');
|
||||
if (!searchInput) return;
|
||||
|
||||
const searchVal = searchInput.value.toLowerCase();
|
||||
let totalVisible = 0;
|
||||
|
||||
const searchVal = searchInput ? searchInput.value.toLowerCase().trim() : '';
|
||||
|
||||
return Array.from(document.querySelectorAll('.product-item')).filter(item => {
|
||||
const itemName = (item.getAttribute('data-name') || '').toLowerCase();
|
||||
const itemCategory = item.closest('.category-row')?.getAttribute('data-category') || '';
|
||||
const matchesSearch = itemName.includes(searchVal);
|
||||
const matchesCategory = currentCategory === 'all' || currentCategory === itemCategory;
|
||||
return matchesSearch && matchesCategory;
|
||||
});
|
||||
}
|
||||
|
||||
function renderPagination(totalItems) {
|
||||
const top = document.getElementById('paginationTop');
|
||||
const bottom = document.getElementById('paginationBottom');
|
||||
const statusTop = document.getElementById('paginationStatus');
|
||||
const statusBottom = document.getElementById('paginationStatusBottom');
|
||||
const footerWrap = document.getElementById('paginationFooter');
|
||||
|
||||
if (!top || !bottom || !statusTop || !statusBottom) return;
|
||||
|
||||
const totalPages = Math.max(1, Math.ceil(totalItems / itemsPerPage));
|
||||
if (currentPage > totalPages) currentPage = totalPages;
|
||||
|
||||
if (totalItems === 0) {
|
||||
statusTop.textContent = <?= json_encode(tr('0 منتج', '0 products')) ?>;
|
||||
statusBottom.textContent = statusTop.textContent;
|
||||
top.innerHTML = '';
|
||||
bottom.innerHTML = '';
|
||||
if (footerWrap) footerWrap.style.display = 'none';
|
||||
return;
|
||||
}
|
||||
|
||||
const start = ((currentPage - 1) * itemsPerPage) + 1;
|
||||
const end = Math.min(totalItems, currentPage * itemsPerPage);
|
||||
const statusText = `<?= h(tr('عرض', 'Showing')) ?> ${start}-${end} <?= h(tr('من', 'of')) ?> ${totalItems}`;
|
||||
statusTop.textContent = statusText;
|
||||
statusBottom.textContent = statusText;
|
||||
if (footerWrap) footerWrap.style.display = '';
|
||||
|
||||
if (totalPages <= 1) {
|
||||
top.innerHTML = '';
|
||||
bottom.innerHTML = '';
|
||||
return;
|
||||
}
|
||||
|
||||
const pages = [];
|
||||
pages.push(1);
|
||||
for (let p = Math.max(2, currentPage - 1); p <= Math.min(totalPages - 1, currentPage + 1); p++) {
|
||||
pages.push(p);
|
||||
}
|
||||
if (totalPages > 1) pages.push(totalPages);
|
||||
|
||||
const uniquePages = [...new Set(pages)].sort((a, b) => a - b);
|
||||
const parts = [];
|
||||
|
||||
const addControl = (label, page, disabled = false, active = false) => {
|
||||
parts.push(`<li class="page-item${disabled ? ' disabled' : ''}${active ? ' active' : ''}"><button class="page-link" type="button" ${disabled ? 'disabled' : ''} onclick="goToPage(${page})">${label}</button></li>`);
|
||||
};
|
||||
|
||||
addControl('‹', Math.max(1, currentPage - 1), currentPage === 1);
|
||||
|
||||
let lastPage = 0;
|
||||
uniquePages.forEach(page => {
|
||||
if (lastPage && page > lastPage + 1) {
|
||||
parts.push('<li class="page-item disabled"><span class="page-link">…</span></li>');
|
||||
}
|
||||
addControl(page, page, false, page === currentPage);
|
||||
lastPage = page;
|
||||
});
|
||||
|
||||
addControl('›', Math.min(totalPages, currentPage + 1), currentPage === totalPages);
|
||||
|
||||
const html = parts.join('');
|
||||
top.innerHTML = html;
|
||||
bottom.innerHTML = html;
|
||||
}
|
||||
|
||||
function goToPage(page) {
|
||||
currentPage = page;
|
||||
filterProducts(false);
|
||||
window.scrollTo({ top: 0, behavior: 'smooth' });
|
||||
}
|
||||
|
||||
function filterProducts(resetPage = true) {
|
||||
if (resetPage) currentPage = 1;
|
||||
|
||||
const filteredItems = getFilteredItems();
|
||||
const totalVisible = filteredItems.length;
|
||||
const startIndex = (currentPage - 1) * itemsPerPage;
|
||||
const endIndex = startIndex + itemsPerPage;
|
||||
const visibleOnPage = new Set(filteredItems.slice(startIndex, endIndex));
|
||||
|
||||
document.querySelectorAll('.category-row').forEach(row => {
|
||||
const catName = row.getAttribute('data-category');
|
||||
let hasVisibleItems = false;
|
||||
|
||||
|
||||
row.querySelectorAll('.product-item').forEach(item => {
|
||||
const itemName = item.getAttribute('data-name');
|
||||
const matchesSearch = itemName.includes(searchVal);
|
||||
const matchesCategory = currentCategory === 'all' || currentCategory === catName;
|
||||
|
||||
if (matchesSearch && matchesCategory) {
|
||||
if (visibleOnPage.has(item)) {
|
||||
item.style.display = '';
|
||||
hasVisibleItems = true;
|
||||
totalVisible++;
|
||||
} else {
|
||||
item.style.display = 'none';
|
||||
}
|
||||
});
|
||||
|
||||
// Hide category title if no items visible
|
||||
|
||||
const title = row.previousElementSibling;
|
||||
if (title && title.classList.contains('category-title')) {
|
||||
if (hasVisibleItems) {
|
||||
title.style.display = '';
|
||||
row.style.display = '';
|
||||
} else {
|
||||
title.style.display = 'none';
|
||||
row.style.display = 'none';
|
||||
}
|
||||
title.style.display = hasVisibleItems ? '' : 'none';
|
||||
row.style.display = hasVisibleItems ? '' : 'none';
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
const noResultsMsg = document.getElementById('noResultsMsg');
|
||||
if (noResultsMsg) {
|
||||
noResultsMsg.style.display = totalVisible === 0 ? 'block' : 'none';
|
||||
}
|
||||
|
||||
renderPagination(totalVisible);
|
||||
}
|
||||
|
||||
// init
|
||||
updateCartBadge();
|
||||
filterProducts();
|
||||
</script>
|
||||
|
||||
<?php require __DIR__ . '/includes/footer.php'; ?>
|
||||
Loading…
x
Reference in New Issue
Block a user