Autosave: 20260224-125306

This commit is contained in:
Flatlogic Bot 2026-02-24 12:53:06 +00:00
parent 2a7531af42
commit 90c77f9a44
3 changed files with 295 additions and 281 deletions

View File

@ -359,7 +359,7 @@ function printThermalReceipt() {
const left = (screen.width - width) / 2; const left = (screen.width - width) / 2;
const top = (screen.height - height) / 2; const top = (screen.height - height) / 2;
const win = window.open('', 'Receipt', `width=${width},height=${height},top=${top},left=${left}`); const win = window.open('', '_blank', `width=${width},height=${height},top=${top},left=${left}`);
if (!win) { if (!win) {
alert('Please allow popups for this website to print thermal receipts.'); alert('Please allow popups for this website to print thermal receipts.');
@ -456,7 +456,7 @@ function printThermalReceipt() {
.rtl { direction: rtl; unicode-bidi: embed; } .rtl { direction: rtl; unicode-bidi: embed; }
@media print { @media print {
body { width: 80mm; padding: 5mm; } body { width: 80mm; padding: 5mm; }
@page { margin: 0; } @page { size: 80mm auto; margin: 0; }
} }
</style> </style>
</head> </head>

View File

@ -864,7 +864,7 @@ document.addEventListener('DOMContentLoaded', () => {
const left = (screen.width - width) / 2; const left = (screen.width - width) / 2;
const top = (screen.height - height) / 2; const top = (screen.height - height) / 2;
const win = window.open('', 'Receipt', `width=${width},height=${height},top=${top},left=${left}`); const win = window.open('', '_blank', `width=${width},height=${height},top=${top},left=${left}`);
if (!win) { if (!win) {
alert('Please allow popups for this website to print receipts.'); alert('Please allow popups for this website to print receipts.');
@ -965,8 +965,8 @@ document.addEventListener('DOMContentLoaded', () => {
.order-info-row { display: flex; justify-content: space-between; margin-bottom: 2px; } .order-info-row { display: flex; justify-content: space-between; margin-bottom: 2px; }
.rtl { direction: rtl; unicode-bidi: embed; } .rtl { direction: rtl; unicode-bidi: embed; }
@media print { @media print {
body { width: 80mm; padding: 5mm; } @page { size: 80mm auto; margin: 0; }
@page { margin: 0; } body { width: 80mm; margin: 0; padding: 5mm; }
} }
</style> </style>
</head> </head>

554
pos.php
View File

@ -98,155 +98,135 @@ if (!$loyalty_settings) {
.search-dropdown { position: absolute; width: 100%; z-index: 1000; max-height: 200px; overflow-y: auto; display: none; } .search-dropdown { position: absolute; width: 100%; z-index: 1000; max-height: 200px; overflow-y: auto; display: none; }
.payment-btn { height: 70px; font-size: 1.05rem; font-weight: bold; } .payment-btn { height: 70px; font-size: 1.05rem; font-weight: bold; }
.btn-lg { font-size: 1.1rem; padding: 0.75rem 1rem; } .btn-lg { font-size: 1.1rem; padding: 0.75rem 1rem; }
.btn-sm { font-size: 0.85rem; }
.navbar-brand { font-size: 1.15rem; } /* Print Styles */
.card-title { font-size: 0.9rem; } @media print {
.no-print { display: none !important; }
.print-only { display: block !important; }
body { overflow: visible !important; height: auto !important; }
}
.print-only { display: none; }
</style> </style>
</head> </head>
<body> <body>
<!-- Navbar --> <!-- Print Container for QR codes, etc. -->
<nav class="navbar navbar-expand-lg navbar-light bg-white border-bottom shadow-sm" style="height: 60px;"> <div class="print-only" id="print-section"></div>
<div class="container-fluid">
<a href="pos.php" class="navbar-brand d-flex align-items-center gap-2">
<?php if (!empty($settings['logo_url'])): ?>
<img src="<?= htmlspecialchars($settings['logo_url']) ?>" alt="Logo" style="height: 32px; width: auto;">
<?php endif; ?>
<span class="fw-bold d-none d-md-block"><?= htmlspecialchars($settings['company_name']) ?></span>
</a>
<div class="d-flex align-items-center gap-2"> <div class="container-fluid p-0 no-print">
<?php if (has_permission('kitchen_view')): ?> <!-- Header/Navbar -->
<a href="kitchen.php" class="btn btn-sm btn-outline-secondary">Kitchen View</a> <nav class="navbar navbar-expand-lg border-bottom px-3 py-2 bg-white sticky-top">
<?php endif; ?> <div class="container-fluid p-0">
<a class="navbar-brand fw-bold d-flex align-items-center" href="pos.php">
<?php if (!empty($settings['logo_url'])): ?>
<img src="<?= htmlspecialchars($settings['logo_url']) ?>" alt="Logo" height="30" class="me-2">
<?php endif; ?>
<span><?= htmlspecialchars($settings['company_name']) ?></span>
<span class="badge bg-primary ms-2 fs-6 fw-normal"><?= htmlspecialchars($current_outlet_name) ?></span>
</a>
<?php if (has_permission('pos_add')): ?> <div class="ms-auto d-flex align-items-center gap-3">
<button class="btn btn-sm btn-outline-danger" id="recall-bill-btn"><i class="bi bi-clock-history"></i> Recall Bill</button> <!-- Outlet Selector in Header -->
<?php endif; ?> <div class="dropdown me-2">
<button class="btn btn-outline-secondary btn-sm dropdown-toggle rounded-pill px-3" type="button" data-bs-toggle="dropdown">
<button class="btn btn-sm btn-outline-warning" onclick="showRatingQR()"> <i class="bi bi-shop me-1"></i> Switch Outlet
<i class="bi bi-qr-code"></i> Rating QR
</button>
<div id="current-table-display" class="badge bg-light text-dark border px-3 py-2" style="display: none; font-size: 0.9rem;">
Table <?= htmlspecialchars((string)$table_id) ?>
</div>
<div class="dropdown">
<button class="btn btn-sm btn-outline-dark dropdown-toggle" type="button" data-bs-toggle="dropdown">
<i class="bi bi-person-circle"></i> <?= htmlspecialchars($currentUser['username']) ?>
</button> </button>
<ul class="dropdown-menu dropdown-menu-end"> <ul class="dropdown-menu dropdown-menu-end shadow border-0 mt-2">
<li><a class="dropdown-item" href="admin/"><i class="bi bi-shield-lock"></i> Admin Panel</a></li> <?php foreach ($outlets as $o): ?>
<li><hr class="dropdown-divider"></li> <li>
<li><a class="dropdown-item text-danger" href="logout.php"><i class="bi bi-box-arrow-right"></i> Logout</a></li> <a class="dropdown-item <?= $o['id'] == $outlet_id ? 'active' : '' ?>" href="?outlet_id=<?= $o['id'] ?>">
<?= htmlspecialchars($o['name']) ?>
</a>
</li>
<?php endforeach; ?>
</ul> </ul>
</div> </div>
</div>
</div>
</nav>
<div class="container-fluid p-0"> <a href="kitchen.php" class="btn btn-outline-primary btn-sm rounded-pill px-3">
<div class="row g-0"> <i class="bi bi-fire me-1"></i> Kitchen
</a>
<a href="admin/orders.php" class="btn btn-outline-secondary btn-sm rounded-pill px-3">
<i class="bi bi-receipt me-1"></i> Current Orders
</a>
<button class="btn btn-outline-warning btn-sm rounded-pill px-3" onclick="openRecallOrderModal()">
<i class="bi bi-arrow-counterclockwise me-1"></i> Recall Bill
</button>
<button class="btn btn-outline-info btn-sm rounded-pill px-3" onclick="showRatingQR()">
<i class="bi bi-qr-code me-1"></i> Rating QR
</button>
<!-- Left Sidebar: Categories --> <div class="vr mx-2 h-25"></div>
<div class="col-md-2 d-none d-md-block category-sidebar scrollable-y p-3 border-end">
<h6 class="text-uppercase text-muted small fw-bold mb-3 ms-1">Categories</h6> <div class="dropdown">
<button class="category-btn active mb-1" onclick="filterCategory('all', this)"> <button class="btn btn-light btn-sm rounded-circle p-1 border" type="button" data-bs-toggle="dropdown">
<i class="bi bi-grid me-2"></i> All Items <img src="<?= !empty($currentUser['profile_pic']) ? htmlspecialchars($currentUser['profile_pic']) : 'https://ui-avatars.com/api/?name=' . urlencode($currentUser['username']) ?>" alt="User" width="30" height="30" class="rounded-circle">
</button>
<?php foreach ($categories as $category): ?>
<button class="category-btn mb-1" onclick="filterCategory(<?= $category['id'] ?>, this)">
<div class="d-flex align-items-center">
<?php if (!empty($category['image_url'])): ?>
<img src="<?= htmlspecialchars($category['image_url']) ?>" style="width: 24px; height: 24px; border-radius: 4px; object-fit: cover;" class="me-2">
<?php else: ?>
<i class="bi bi-tag me-2"></i>
<?php endif; ?>
<div>
<div class="category-name"><?= htmlspecialchars($category['name']) ?></div>
<?php if (!empty($category['name_ar'])): ?>
<div class="small opacity-75" dir="rtl" style="font-size: 0.75rem;"><?= htmlspecialchars($category['name_ar']) ?></div>
<?php endif; ?>
</div>
</div>
</button> </button>
<ul class="dropdown-menu dropdown-menu-end shadow border-0 mt-2">
<li class="px-3 py-2 border-bottom">
<div class="fw-bold small"><?= htmlspecialchars($currentUser['username']) ?></div>
<div class="text-muted" style="font-size: 0.7rem;">Logged in as <?= htmlspecialchars($currentUser['group_name'] ?? 'User') ?></div>
</li>
<?php if (has_permission('dashboard_view')): ?>
<li><a class="dropdown-item py-2" href="admin/index.php"><i class="bi bi-speedometer2 me-2"></i> Dashboard</a></li>
<?php endif; ?>
<li><a class="dropdown-item py-2 text-danger" href="logout.php"><i class="bi bi-box-arrow-right me-2"></i> Logout</a></li>
</ul>
</div>
</div>
</div>
</nav>
<div class="row g-0">
<!-- Left Sidebar: Categories -->
<div class="col-md-1 col-3 category-sidebar border-end scrollable-y p-2">
<button class="category-btn active mb-2" data-category="all">
<i class="bi bi-grid d-block fs-4 mb-1"></i>
<span style="font-size: 0.75rem;">All Items</span>
</button>
<?php foreach ($categories as $cat): ?>
<button class="category-btn mb-2" data-category="<?= $cat['id'] ?>">
<?php if (!empty($cat['image_url'])): ?>
<img src="<?= htmlspecialchars($cat['image_url']) ?>" alt="<?= htmlspecialchars($cat['name']) ?>" class="rounded d-block mb-1 mx-auto" style="width: 32px; height: 32px; object-fit: cover;">
<?php else: ?>
<i class="bi bi-tag d-block fs-4 mb-1"></i>
<?php endif; ?>
<span class="d-block text-truncate text-center" style="font-size: 0.75rem;"><?= htmlspecialchars($cat['name']) ?></span>
</button>
<?php endforeach; ?> <?php endforeach; ?>
</div> </div>
<!-- Middle: Products --> <!-- Center Area: Product Grid -->
<div class="col-md-7 col-12 product-area scrollable-y p-4 bg-light"> <div class="col-md-8 col-9 product-area d-flex flex-column">
<!-- Mobile Category Select (Visible only on small screens) --> <!-- Search Bar -->
<div class="d-md-none mb-3"> <div class="p-3 border-bottom bg-light">
<select class="form-select" onchange="filterCategory(this.value)"> <div class="position-relative">
<option value="all">All Categories</option> <span class="position-absolute top-50 start-0 translate-middle-y ms-3 text-muted">
<?php foreach ($categories as $cat): ?> <i class="bi bi-search"></i>
<option value="<?= $cat['id'] ?>"><?= htmlspecialchars($cat['name']) ?> <?= !empty($cat['name_ar']) ? '(' . $cat['name_ar'] . ')' : '' ?></option> </span>
<?php endforeach; ?> <input type="text" id="product-search" class="form-control form-control-lg ps-5 border-0 shadow-sm rounded-pill" placeholder="Search products by name or SKU...">
</select> </div>
</div> </div>
<!-- Product Search Bar & Outlet Selector --> <!-- Grid Container -->
<div class="mb-3 row g-2"> <div class="flex-grow-1 scrollable-y p-3">
<div class="col-md-4 col-12"> <div class="row g-3" id="product-grid">
<select class="form-select shadow-sm" id="outlet-select" onchange="const url = new URL(window.location); url.searchParams.set('outlet_id', this.value); window.location = url;"> <?php foreach ($all_products as $product): ?>
<?php if (empty($outlets)): ?> <?php $has_variants = !empty($variants_by_product[$product['id']]); ?>
<option value="1">Main Outlet</option> <div class="col-xl-3 col-lg-4 col-md-6 col-6 product-item"
<?php else: ?> data-category="<?= $product['category_id'] ?>"
<?php foreach ($outlets as $outlet): ?> data-name="<?= strtolower($product['name']) ?>"
<option value="<?= $outlet['id'] ?>" <?= $outlet_id == $outlet['id'] ? 'selected' : '' ?>> data-sku="<?= strtolower($product['sku'] ?? '') ?>"
<?= htmlspecialchars($outlet['name']) ?> onclick='handleProductClick(<?= json_encode($product) ?>, <?= json_encode($variants_by_product[$product['id']] ?? []) ?>)'>
</option> <div class="card h-100 border-0 shadow-sm product-card rounded-4 overflow-hidden">
<?php endforeach; ?> <?php if (!empty($product['image_url'])): ?>
<?php endif; ?> <img src="<?= htmlspecialchars($product['image_url']) ?>" class="card-img-top" alt="<?= htmlspecialchars($product['name']) ?>" style="height: 120px; object-fit: cover;">
</select> <?php else: ?>
</div> <div class="bg-light d-flex align-items-center justify-content-center" style="height: 120px;">
<div class="col-md-8 col-12"> <i class="bi bi-image text-muted opacity-25 fs-1"></i>
<div class="input-group shadow-sm"> </div>
<span class="input-group-text bg-white border-end-0"><i class="bi bi-search text-muted"></i></span> <?php endif; ?>
<input type="text" id="product-search-input" class="form-control border-start-0 ps-0" placeholder="Search products..." autocomplete="off"> <div class="card-body p-2 text-center">
</div> <h6 class="card-title fw-bold mb-1 text-truncate" style="font-size: 0.9rem;"><?= htmlspecialchars($product['name']) ?></h6>
</div> <div class="text-primary fw-bold mb-1" style="font-size: 1rem;"><?= format_currency((float)$product['price']) ?></div>
</div>
<div class="row row-cols-2 row-cols-lg-5 g-3" id="products-container">
<?php foreach ($all_products as $product):
$has_variants = !empty($variants_by_product[$product['id']]);
$effective_price = get_product_price($product);
$is_promo = $effective_price < $product['price'];
$stock = intval($product['stock_quantity'] ?? 0);
?>
<div class="col product-item" data-category-id="<?= $product['category_id'] ?>">
<div class="card h-100 border-0 shadow-sm product-card add-to-cart"
data-id="<?= $product['id'] ?>"
data-name="<?= htmlspecialchars($product['name']) ?>"
data-name-ar="<?= htmlspecialchars($product['name_ar'] ?? '') ?>"
data-price="<?= $effective_price ?>"
data-has-variants="<?= $has_variants ? 'true' : 'false' ?>">
<div class="position-relative">
<img src="https://picsum.photos/seed/<?= $product['id'] ?>/300/200" class="card-img-top object-fit-cover" alt="..." style="height: 120px;">
<div class="position-absolute bottom-0 end-0 m-2">
<?php if ($is_promo): ?>
<span class="badge bg-danger rounded-pill shadow-sm"><?= format_currency($effective_price) ?></span>
<span class="badge bg-dark rounded-pill opacity-75 text-decoration-line-through x-small" style="font-size: 0.7rem;"><?= format_currency($product['price']) ?></span>
<?php else: ?>
<span class="badge bg-dark rounded-pill"><?= format_currency($product['price']) ?></span>
<?php endif; ?>
</div>
<?php if ($is_promo): ?>
<div class="position-absolute top-0 start-0 m-2">
<span class="badge bg-warning text-dark fw-bold rounded-pill">SALE</span>
</div>
<?php endif; ?>
<!-- Stock Indicator -->
<div class="position-absolute top-0 end-0 m-2">
<span class="badge <?= $stock <= 5 ? 'bg-danger' : 'bg-success' ?> opacity-75" style="font-size: 0.7rem;">
Stock: <?= $stock ?>
</span>
</div>
</div>
<div class="card-body p-2">
<h6 class="card-title fw-bold small mb-1 text-truncate"><?= htmlspecialchars($product['name']) ?></h6>
<?php if (!empty($product['name_ar'])): ?> <?php if (!empty($product['name_ar'])): ?>
<div class="text-primary small fw-semibold text-truncate mb-1" dir="rtl" style="font-size: 0.8rem;"><?= htmlspecialchars($product['name_ar']) ?></div> <div class="text-primary small fw-semibold text-truncate mb-1" dir="rtl" style="font-size: 0.8rem;"><?= htmlspecialchars($product['name_ar']) ?></div>
<?php endif; ?> <?php endif; ?>
@ -377,162 +357,165 @@ if (!$loyalty_settings) {
</div> </div>
</div> </div>
<!-- Toast Container --> <!-- Modal components wrapped in no-print -->
<div class="toast-container position-fixed bottom-0 start-50 translate-middle-x p-3" id="toast-container" style="z-index: 1060;"></div> <div class="no-print">
<!-- Toast Container -->
<div class="toast-container position-fixed bottom-0 start-50 translate-middle-x p-3" id="toast-container" style="z-index: 1060;"></div>
<!-- Recall Order Modal --> <!-- Recall Order Modal -->
<div class="modal fade" id="recallOrderModal" tabindex="-1" aria-hidden="true"> <div class="modal fade" id="recallOrderModal" tabindex="-1" aria-hidden="true">
<div class="modal-dialog modal-lg modal-dialog-centered"> <div class="modal-dialog modal-lg modal-dialog-centered">
<div class="modal-content"> <div class="modal-content">
<div class="modal-header"> <div class="modal-header">
<h5 class="modal-title fw-bold">Recall Unpaid Bill</h5> <h5 class="modal-title fw-bold">Recall Unpaid Bill</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button> <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div> </div>
<div class="modal-body bg-light"> <div class="modal-body bg-light">
<div id="recall-orders-list" class="list-group"> <div id="recall-orders-list" class="list-group">
<!-- Orders injected via JS --> <!-- Orders injected via JS -->
</div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div>
<!-- Table Selection Modal --> <!-- Table Selection Modal -->
<div class="modal fade" id="tableSelectionModal" tabindex="-1" aria-hidden="true" data-bs-backdrop="static"> <div class="modal fade" id="tableSelectionModal" tabindex="-1" aria-hidden="true" data-bs-backdrop="static">
<div class="modal-dialog modal-lg modal-dialog-centered"> <div class="modal-dialog modal-lg modal-dialog-centered">
<div class="modal-content"> <div class="modal-content">
<div class="modal-header"> <div class="modal-header">
<h5 class="modal-title fw-bold" id="tableSelectionModalLabel">Select Table</h5> <h5 class="modal-title fw-bold" id="tableSelectionModalLabel">Select Table</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close" id="close-table-modal" style="display:none;"></button> <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close" id="close-table-modal" style="display:none;"></button>
</div>
<div class="modal-body bg-light">
<div id="table-list-container" class="row g-3"></div>
</div>
</div>
</div>
</div>
<!-- Variant Selection Modal -->
<div class="modal fade" id="variantSelectionModal" tabindex="-1" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="variantModalTitle">Select Option</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<div id="variant-list" class="list-group">
<!-- Variants injected by JS -->
</div>
</div>
</div>
</div>
</div>
<!-- Add Customer Modal -->
<div class="modal fade" id="addCustomerModal" tabindex="-1" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered modal-sm">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title fs-6 fw-bold">Add New Customer</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<div class="mb-3">
<label for="new-customer-name" class="form-label small text-muted">Customer Name</label>
<input type="text" class="form-control form-control-sm" id="new-customer-name" placeholder="Enter name">
</div>
<div class="mb-3">
<label for="new-customer-phone" class="form-label small text-muted">Phone Number</label>
<input type="text" class="form-control form-control-sm" id="new-customer-phone" placeholder="Enter phone">
</div>
<div class="d-grid">
<button type="button" class="btn btn-primary btn-sm" id="save-new-customer">Save Customer</button>
</div>
</div>
</div>
</div>
</div>
<!-- Points History Modal -->
<div class="modal fade" id="pointsHistoryModal" tabindex="-1" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title fw-bold">Points History</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body p-0">
<div class="table-responsive">
<table class="table table-sm table-hover mb-0">
<thead class="table-light">
<tr>
<th class="ps-3">Date</th>
<th>Action</th>
<th class="text-end pe-3">Points</th>
</tr>
</thead>
<tbody id="points-history-body">
<!-- History rows injected via JS -->
</tbody>
</table>
</div> </div>
<div id="points-history-empty" class="text-center py-4 text-muted d-none"> <div class="modal-body bg-light">
<i class="bi bi-calendar-x fs-2"></i> <div id="table-list-container" class="row g-3"></div>
<p class="mt-2">No history found</p>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div>
<!-- Payment Selection Modal --> <!-- Variant Selection Modal -->
<div class="modal fade" id="paymentSelectionModal" tabindex="-1" aria-hidden="true" data-bs-backdrop="static"> <div class="modal fade" id="variantSelectionModal" tabindex="-1" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered"> <div class="modal-dialog modal-dialog-centered">
<div class="modal-content"> <div class="modal-content">
<div class="modal-header"> <div class="modal-header">
<h5 class="modal-title fw-bold">Select Payment Method</h5> <h5 class="modal-title" id="variantModalTitle">Select Option</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button> <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div> </div>
<div class="modal-body"> <div class="modal-body">
<div class="row g-3" id="payment-methods-container"> <div id="variant-list" class="list-group">
<!-- Injected via JS --> <!-- Variants injected by JS -->
</div> </div>
</div>
</div> </div>
</div> </div>
</div> </div>
</div>
<!-- Rating QR Modal --> <!-- Add Customer Modal -->
<div class="modal fade" id="ratingQRModal" tabindex="-1" aria-hidden="true"> <div class="modal fade" id="addCustomerModal" tabindex="-1" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered"> <div class="modal-dialog modal-dialog-centered modal-sm">
<div class="modal-content"> <div class="modal-content">
<div class="modal-header"> <div class="modal-header">
<h5 class="modal-title fw-bold">Rating & Feedback QR</h5> <h5 class="modal-title fs-6 fw-bold">Add New Customer</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button> <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<div class="mb-3">
<label for="new-customer-name" class="form-label small text-muted">Customer Name</label>
<input type="text" class="form-control form-control-sm" id="new-customer-name" placeholder="Enter name">
</div>
<div class="mb-3">
<label for="new-customer-phone" class="form-label small text-muted">Phone Number</label>
<input type="text" class="form-control form-control-sm" id="new-customer-phone" placeholder="Enter phone">
</div>
<div class="d-grid">
<button type="button" class="btn btn-primary btn-sm" id="save-new-customer">Save Customer</button>
</div>
</div>
</div> </div>
<div class="modal-body text-center p-4"> </div>
<p class="text-muted mb-4">Ask your customers to scan this QR code to rate your service and staff.</p> </div>
<div id="rating-qr-container" class="mb-4">
<!-- QR Code will be generated here -->
<div class="bg-light p-4 rounded-4 d-inline-block shadow-sm">
<?php
$protocol = isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? "https" : "http";
$host = $_SERVER['HTTP_HOST'];
$ratingUrl = $protocol . "://" . $host . "/rate.php";
// Using a public QR generator for simplicity <!-- Points History Modal -->
$qrUrl = "https://api.qrserver.com/v1/create-qr-code/?size=250x250&data=" . urlencode($ratingUrl); <div class="modal fade" id="pointsHistoryModal" tabindex="-1" aria-hidden="true">
?> <div class="modal-dialog modal-dialog-centered">
<img src="<?= $qrUrl ?>" alt="Rating QR Code" class="img-fluid" style="width: 200px; height: 200px;"> <div class="modal-content">
</div> <div class="modal-header">
<h5 class="modal-title fw-bold">Points History</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body p-0">
<div class="table-responsive">
<table class="table table-sm table-hover mb-0">
<thead class="table-light">
<tr>
<th class="ps-3">Date</th>
<th>Action</th>
<th class="text-end pe-3">Points</th>
</tr>
</thead>
<tbody id="points-history-body">
<!-- History rows injected via JS -->
</tbody>
</table>
</div> </div>
<div class="alert alert-info small py-2"> <div id="points-history-empty" class="text-center py-4 text-muted d-none">
<i class="bi bi-link-45deg me-1"></i> URL: <a href="<?= $ratingUrl ?>" target="_blank" class="text-decoration-none"><?= $ratingUrl ?></a> <i class="bi bi-calendar-x fs-2"></i>
<p class="mt-2">No history found</p>
</div> </div>
<button class="btn btn-primary w-100 rounded-pill py-2 fw-bold" onclick="window.print()"> </div>
<i class="bi bi-printer me-2"></i> Print QR Code </div>
</button> </div>
</div>
<!-- Payment Selection Modal -->
<div class="modal fade" id="paymentSelectionModal" tabindex="-1" aria-hidden="true" data-bs-backdrop="static">
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title fw-bold">Select Payment Method</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<div class="row g-3" id="payment-methods-container">
<!-- Injected via JS -->
</div>
</div>
</div>
</div>
</div>
<!-- Rating QR Modal -->
<div class="modal fade" id="ratingQRModal" tabindex="-1" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title fw-bold">Rating & Feedback QR</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body text-center p-4">
<p class="text-muted mb-4">Ask your customers to scan this QR code to rate your service and staff.</p>
<div id="rating-qr-container" class="mb-4">
<!-- QR Code will be generated here -->
<div class="bg-light p-4 rounded-4 d-inline-block shadow-sm">
<?php
$protocol = isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? "https" : "http";
$host = $_SERVER['HTTP_HOST'];
$ratingUrl = $protocol . "://" . $host . "/rate.php";
// Using a public QR generator for simplicity
$qrUrl = "https://api.qrserver.com/v1/create-qr-code/?size=250x250&data=" . urlencode($ratingUrl);
?>
<img src="<?= $qrUrl ?>" alt="Rating QR Code" class="img-fluid" style="width: 200px; height: 200px;">
</div>
</div>
<div class="alert alert-info small py-2">
<i class="bi bi-link-45deg me-1"></i> URL: <a href="<?= $ratingUrl ?>" target="_blank" class="text-decoration-none"><?= $ratingUrl ?></a>
</div>
<button class="btn btn-primary w-100 rounded-pill py-2 fw-bold" onclick="printQRCode('<?= $qrUrl ?>', 'Rating & Feedback QR')">
<i class="bi bi-printer me-2"></i> Print QR Code
</button>
</div>
</div> </div>
</div> </div>
</div> </div>
@ -557,6 +540,37 @@ if (!$loyalty_settings) {
const modal = new bootstrap.Modal(document.getElementById('ratingQRModal')); const modal = new bootstrap.Modal(document.getElementById('ratingQRModal'));
modal.show(); modal.show();
} }
function printQRCode(url, title) {
const win = window.open('', '_blank', 'width=600,height=600');
win.document.write(`
<html>
<head>
<title>${title}</title>
<style>
body { text-align: center; padding: 50px; font-family: sans-serif; }
img { width: 300px; height: 300px; margin-bottom: 20px; }
h2 { margin-bottom: 10px; }
@media print {
body { padding: 0; }
}
</style>
</head>
<body>
<h2>${title}</h2>
<img src="${url}" alt="QR Code">
<p>Scan to Rate Us</p>
<script>
window.onload = function() {
window.print();
setTimeout(function() { window.close(); }, 500);
}
<\/script>
</body>
</html>
`);
win.document.close();
}
</script> </script>
</body> </body>
</html> </html>