update pos
This commit is contained in:
parent
05a5289cfc
commit
6e5310e4dc
@ -81,12 +81,12 @@ include 'includes/header.php';
|
|||||||
|
|
||||||
<div class="d-flex justify-content-between align-items-center mb-4">
|
<div class="d-flex justify-content-between align-items-center mb-4">
|
||||||
<div>
|
<div>
|
||||||
<h2 class="fw-bold mb-1">Product Categories</h2>
|
<h2 class="fw-bold mb-1"><?= t('categories') ?></h2>
|
||||||
<p class="text-muted mb-0">Organize your menu and inventory</p>
|
<p class="text-muted mb-0">Organize your menu and inventory</p>
|
||||||
</div>
|
</div>
|
||||||
<?php if (has_permission('categories_add')): ?>
|
<?php if (has_permission('categories_add')): ?>
|
||||||
<button class="btn btn-primary btn-lg shadow-sm" data-bs-toggle="modal" data-bs-target="#categoryModal" onclick="prepareAddForm()" style="border-radius: 12px;">
|
<button class="btn btn-primary btn-lg shadow-sm" data-bs-toggle="modal" data-bs-target="#categoryModal" onclick="prepareAddForm()" style="border-radius: 12px;">
|
||||||
<i class="bi bi-plus-lg me-1"></i> Add Category
|
<i class="bi bi-plus-lg me-1"></i> <?= t('add') ?> <?= t('categories') ?>
|
||||||
</button>
|
</button>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
</div>
|
</div>
|
||||||
@ -96,7 +96,7 @@ include 'includes/header.php';
|
|||||||
<?php if (empty($categories)): ?>
|
<?php if (empty($categories)): ?>
|
||||||
<div class="text-center py-5 bg-white rounded-4 shadow-sm">
|
<div class="text-center py-5 bg-white rounded-4 shadow-sm">
|
||||||
<i class="bi bi-tags display-1 text-muted opacity-25 mb-3 d-block"></i>
|
<i class="bi bi-tags display-1 text-muted opacity-25 mb-3 d-block"></i>
|
||||||
<h4 class="text-dark">No categories found</h4>
|
<h4 class="text-dark"><?= t('none') ?></h4>
|
||||||
<p class="text-muted">Start by adding your first category.</p>
|
<p class="text-muted">Start by adding your first category.</p>
|
||||||
</div>
|
</div>
|
||||||
<?php else: ?>
|
<?php else: ?>
|
||||||
@ -105,10 +105,10 @@ include 'includes/header.php';
|
|||||||
<table class="table table-hover align-middle mb-0">
|
<table class="table table-hover align-middle mb-0">
|
||||||
<thead class="bg-light">
|
<thead class="bg-light">
|
||||||
<tr>
|
<tr>
|
||||||
<th class="ps-4">Category</th>
|
<th class="ps-4"><?= t('category') ?></th>
|
||||||
<th>Arabic Name</th>
|
<th><?= t('arabic_name') ?></th>
|
||||||
<th>Description</th>
|
<th><?= t('description') ?></th>
|
||||||
<th class="text-end pe-4">Actions</th>
|
<th class="text-end pe-4"><?= t('actions') ?></th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
@ -124,18 +124,18 @@ include 'includes/header.php';
|
|||||||
<div class="text-dark"><?= htmlspecialchars($cat['name_ar'] ?? '-') ?></div>
|
<div class="text-dark"><?= htmlspecialchars($cat['name_ar'] ?? '-') ?></div>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<div class="text-muted small text-truncate" style="max-width: 300px;"><?= htmlspecialchars($cat['description'] ?? 'No description') ?></div>
|
<div class="text-muted small text-truncate" style="max-width: 300px;"><?= htmlspecialchars($cat['description'] ?? t('none')) ?></div>
|
||||||
</td>
|
</td>
|
||||||
<td class="text-end pe-4">
|
<td class="text-end pe-4">
|
||||||
<div class="d-inline-flex gap-2">
|
<div class="d-inline-flex gap-2">
|
||||||
<?php if (has_permission('categories_edit') || has_permission('categories_add')): ?>
|
<?php if (has_permission('categories_edit') || has_permission('categories_add')): ?>
|
||||||
<button type="button" class="btn btn-sm btn-outline-primary rounded-pill px-3"
|
<button type="button" class="btn btn-sm btn-outline-primary rounded-pill px-3"
|
||||||
data-bs-toggle="modal" data-bs-target="#categoryModal"
|
data-bs-toggle="modal" data-bs-target="#categoryModal"
|
||||||
onclick='prepareEditForm(<?= htmlspecialchars(json_encode($cat), ENT_QUOTES, "UTF-8") ?>)'>Edit</button>
|
onclick='prepareEditForm(<?= htmlspecialchars(json_encode($cat), ENT_QUOTES, "UTF-8") ?>)'><?= t('edit') ?></button>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
|
|
||||||
<?php if (has_permission('categories_del')): ?>
|
<?php if (has_permission('categories_del')): ?>
|
||||||
<a href="?delete=<?= $cat['id'] ?>" class="btn btn-sm btn-outline-danger rounded-pill px-3" onclick="return confirm('Delete category? Ensure no products are linked.')">Delete</a>
|
<a href="?delete=<?= $cat['id'] ?>" class="btn btn-sm btn-outline-danger rounded-pill px-3" onclick="return confirm('Delete category? Ensure no products are linked.')"><?= t('delete') ?></a>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
@ -156,7 +156,7 @@ include 'includes/header.php';
|
|||||||
<div class="modal-dialog">
|
<div class="modal-dialog">
|
||||||
<div class="modal-content border-0 shadow-lg rounded-4">
|
<div class="modal-content border-0 shadow-lg rounded-4">
|
||||||
<div class="modal-header bg-primary text-white border-0 py-3">
|
<div class="modal-header bg-primary text-white border-0 py-3">
|
||||||
<h5 class="modal-title fw-bold" id="categoryModalTitle">Add New Category</h5>
|
<h5 class="modal-title fw-bold" id="categoryModalTitle"><?= t('add') ?> <?= t('categories') ?></h5>
|
||||||
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal" aria-label="Close"></button>
|
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||||
</div>
|
</div>
|
||||||
<form method="POST" id="categoryForm" enctype="multipart/form-data">
|
<form method="POST" id="categoryForm" enctype="multipart/form-data">
|
||||||
@ -165,22 +165,27 @@ include 'includes/header.php';
|
|||||||
<input type="hidden" name="id" id="categoryId">
|
<input type="hidden" name="id" id="categoryId">
|
||||||
|
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label class="form-label small fw-bold text-muted">CATEGORY NAME <span class="text-danger">*</span></label>
|
<label class="form-label small fw-bold text-muted d-flex justify-content-between">
|
||||||
<div class="input-group">
|
<span><?= t('name') ?> (EN) <span class="text-danger">*</span></span>
|
||||||
<input type="text" name="name" id="categoryName" class="form-control rounded-start-3 border-0 bg-light" required>
|
<a href="javascript:void(0)" onclick="translateTo('English')" class="text-decoration-none small text-primary fw-bold" id="translateBtnEn">
|
||||||
<button class="btn btn-outline-secondary border-0 bg-light" type="button" id="btnTranslate">
|
<i class="bi bi-translate me-1"></i> Auto-translate
|
||||||
<i class="bi bi-translate text-primary"></i>
|
</a>
|
||||||
</button>
|
</label>
|
||||||
</div>
|
<input type="text" name="name" id="categoryName" class="form-control rounded-3 border-0 bg-light" required>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label class="form-label small fw-bold text-muted">ARABIC NAME</label>
|
<label class="form-label small fw-bold text-muted d-flex justify-content-between">
|
||||||
|
<span><?= t('arabic_name') ?></span>
|
||||||
|
<a href="javascript:void(0)" onclick="translateTo('Arabic')" class="text-decoration-none small text-primary fw-bold" id="translateBtnAr">
|
||||||
|
<i class="bi bi-translate me-1"></i> Auto-translate
|
||||||
|
</a>
|
||||||
|
</label>
|
||||||
<input type="text" name="name_ar" id="categoryNameAr" class="form-control rounded-3 border-0 bg-light" dir="rtl">
|
<input type="text" name="name_ar" id="categoryNameAr" class="form-control rounded-3 border-0 bg-light" dir="rtl">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label class="form-label small fw-bold text-muted">DESCRIPTION</label>
|
<label class="form-label small fw-bold text-muted"><?= t('description') ?></label>
|
||||||
<textarea name="description" id="categoryDescription" class="form-control rounded-3 border-0 bg-light" rows="3" placeholder="Optional category description..."></textarea>
|
<textarea name="description" id="categoryDescription" class="form-control rounded-3 border-0 bg-light" rows="3" placeholder="Optional category description..."></textarea>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -195,8 +200,8 @@ include 'includes/header.php';
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer border-0 p-4 pt-0">
|
<div class="modal-footer border-0 p-4 pt-0">
|
||||||
<button type="button" class="btn btn-light rounded-pill px-4" data-bs-dismiss="modal">Cancel</button>
|
<button type="button" class="btn btn-light rounded-pill px-4" data-bs-dismiss="modal"><?= t('cancel') ?></button>
|
||||||
<button type="submit" class="btn btn-primary rounded-pill px-4 fw-bold shadow-sm">Save Category</button>
|
<button type="submit" class="btn btn-primary rounded-pill px-4 fw-bold shadow-sm"><?= t('save') ?></button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
@ -205,7 +210,7 @@ include 'includes/header.php';
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
function prepareAddForm() {
|
function prepareAddForm() {
|
||||||
document.getElementById('categoryModalTitle').innerText = 'Add New Category';
|
document.getElementById('categoryModalTitle').innerText = '<?= t('add') ?> <?= t('categories') ?>';
|
||||||
document.getElementById('categoryAction').value = 'add_category';
|
document.getElementById('categoryAction').value = 'add_category';
|
||||||
document.getElementById('categoryForm').reset();
|
document.getElementById('categoryForm').reset();
|
||||||
document.getElementById('categoryId').value = '';
|
document.getElementById('categoryId').value = '';
|
||||||
@ -214,7 +219,7 @@ function prepareAddForm() {
|
|||||||
|
|
||||||
function prepareEditForm(cat) {
|
function prepareEditForm(cat) {
|
||||||
if (!cat) return;
|
if (!cat) return;
|
||||||
document.getElementById('categoryModalTitle').innerText = 'Edit Category: ' + cat.name;
|
document.getElementById('categoryModalTitle').innerText = '<?= t('edit') ?> <?= t('categories') ?>: ' + cat.name;
|
||||||
document.getElementById('categoryAction').value = 'edit_category';
|
document.getElementById('categoryAction').value = 'edit_category';
|
||||||
document.getElementById('categoryId').value = cat.id;
|
document.getElementById('categoryId').value = cat.id;
|
||||||
document.getElementById('categoryName').value = cat.name;
|
document.getElementById('categoryName').value = cat.name;
|
||||||
@ -230,46 +235,43 @@ function prepareEditForm(cat) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
document.getElementById('btnTranslate').addEventListener('click', function() {
|
async function translateTo(targetLang) {
|
||||||
const text = document.getElementById('categoryName').value;
|
const sourceId = targetLang === 'Arabic' ? 'categoryName' : 'categoryNameAr';
|
||||||
if (!text) {
|
const targetId = targetLang === 'Arabic' ? 'categoryNameAr' : 'categoryName';
|
||||||
alert('Please enter a category name first.');
|
const btnId = targetLang === 'Arabic' ? 'translateBtnAr' : 'translateBtnEn';
|
||||||
|
|
||||||
|
const sourceText = document.getElementById(sourceId).value;
|
||||||
|
if (!sourceText) {
|
||||||
|
alert('Please enter text to translate first.');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const btn = this;
|
const btn = document.getElementById(btnId);
|
||||||
const originalHtml = btn.innerHTML;
|
const originalContent = btn.innerHTML;
|
||||||
btn.disabled = true;
|
btn.innerHTML = '<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span> Translating...';
|
||||||
btn.innerHTML = '<span class="spinner-border spinner-border-sm text-primary" role="status" aria-hidden="true"></span>';
|
btn.classList.add('disabled');
|
||||||
|
|
||||||
fetch('../api/translate.php', {
|
try {
|
||||||
method: 'POST',
|
const response = await fetch('../api/translate.php', {
|
||||||
headers: {
|
method: 'POST',
|
||||||
'Content-Type': 'application/json',
|
headers: { 'Content-Type': 'application/json' },
|
||||||
},
|
body: JSON.stringify({ text: sourceText, target_lang: targetLang })
|
||||||
body: JSON.stringify({
|
});
|
||||||
text: text,
|
const data = await response.json();
|
||||||
target_lang: 'Arabic'
|
|
||||||
}),
|
|
||||||
})
|
|
||||||
.then(response => response.json())
|
|
||||||
.then(data => {
|
|
||||||
if (data.success) {
|
if (data.success) {
|
||||||
document.getElementById('categoryNameAr').value = data.translated_text;
|
document.getElementById(targetId).value = data.translated_text;
|
||||||
} else {
|
} else {
|
||||||
alert('Translation failed: ' + (data.error || 'Unknown error'));
|
alert('Translation error: ' + data.error);
|
||||||
}
|
}
|
||||||
})
|
} catch (error) {
|
||||||
.catch(error => {
|
console.error('Translation error:', error);
|
||||||
console.error('Error:', error);
|
|
||||||
alert('An error occurred during translation.');
|
alert('An error occurred during translation.');
|
||||||
})
|
} finally {
|
||||||
.finally(() => {
|
btn.innerHTML = originalContent;
|
||||||
btn.disabled = false;
|
btn.classList.remove('disabled');
|
||||||
btn.innerHTML = originalHtml;
|
}
|
||||||
});
|
}
|
||||||
});
|
|
||||||
</script>
|
</script>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
|
|
||||||
<?php include 'includes/footer.php'; ?>
|
<?php include 'includes/footer.php'; ?>
|
||||||
|
|||||||
@ -10,6 +10,29 @@ if (file_exists(__DIR__ . '/../../db/config.php')) {
|
|||||||
if (file_exists(__DIR__ . '/../../includes/functions.php')) {
|
if (file_exists(__DIR__ . '/../../includes/functions.php')) {
|
||||||
require_once __DIR__ . '/../../includes/functions.php';
|
require_once __DIR__ . '/../../includes/functions.php';
|
||||||
}
|
}
|
||||||
|
if (file_exists(__DIR__ . '/../../includes/lang.php')) {
|
||||||
|
require_once __DIR__ . '/../../includes/lang.php';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle language switching
|
||||||
|
if (isset($_GET['lang'])) {
|
||||||
|
$allowed_langs = ['en', 'ar'];
|
||||||
|
if (in_array($_GET['lang'], $allowed_langs)) {
|
||||||
|
$_SESSION['lang'] = $_GET['lang'];
|
||||||
|
}
|
||||||
|
// Remove lang from URL to prevent infinite redirect or messy URLs
|
||||||
|
$current_url = strtok($_SERVER["REQUEST_URI"], '?');
|
||||||
|
$query = $_GET;
|
||||||
|
unset($query['lang']);
|
||||||
|
if (count($query) > 0) {
|
||||||
|
$current_url .= '?' . http_build_query($query);
|
||||||
|
}
|
||||||
|
header("Location: $current_url");
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
$currentLang = $_SESSION['lang'] ?? 'en';
|
||||||
|
$isRTL = ($currentLang === 'ar');
|
||||||
|
|
||||||
// Require login for all admin pages
|
// Require login for all admin pages
|
||||||
if (function_exists('require_login')) {
|
if (function_exists('require_login')) {
|
||||||
@ -57,7 +80,7 @@ function can_view($module) {
|
|||||||
}
|
}
|
||||||
?>
|
?>
|
||||||
<!doctype html>
|
<!doctype html>
|
||||||
<html lang="en">
|
<html lang="<?= $currentLang ?>" dir="<?= $isRTL ? 'rtl' : 'ltr' ?>">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
@ -69,13 +92,13 @@ function can_view($module) {
|
|||||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.5/font/bootstrap-icons.css" rel="stylesheet">
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.5/font/bootstrap-icons.css" rel="stylesheet">
|
||||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
|
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Noto+Sans+Arabic:wght@400;500;600;700&display=swap" rel="stylesheet">
|
||||||
<link rel="stylesheet" href="../assets/css/custom.css?v=<?= time() ?>">
|
<link rel="stylesheet" href="../assets/css/custom.css?v=<?= time() ?>">
|
||||||
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
|
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
|
||||||
<style>
|
<style>
|
||||||
/* Base styles using CSS variables for theming */
|
/* Base styles using CSS variables for theming */
|
||||||
body {
|
body {
|
||||||
font-family: 'Inter', sans-serif;
|
font-family: 'Inter', 'Noto Sans Arabic', sans-serif;
|
||||||
background-color: var(--bg-body);
|
background-color: var(--bg-body);
|
||||||
color: var(--text-primary);
|
color: var(--text-primary);
|
||||||
}
|
}
|
||||||
@ -83,12 +106,11 @@ function can_view($module) {
|
|||||||
height: 100vh;
|
height: 100vh;
|
||||||
position: fixed;
|
position: fixed;
|
||||||
top: 0;
|
top: 0;
|
||||||
left: 0;
|
<?= $isRTL ? 'right: 0; border-left: 1px solid var(--border-color); border-right: none;' : 'left: 0; border-right: 1px solid var(--border-color); border-left: none;' ?>
|
||||||
width: 250px;
|
width: 250px;
|
||||||
background: var(--bg-sidebar);
|
background: var(--bg-sidebar);
|
||||||
border-right: 1px solid var(--border-color);
|
|
||||||
padding-top: 0;
|
padding-top: 0;
|
||||||
z-index: 1000;
|
z-index: 1060;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
transition: background-color 0.3s ease, border-color 0.3s ease;
|
transition: background-color 0.3s ease, border-color 0.3s ease;
|
||||||
}
|
}
|
||||||
@ -107,11 +129,12 @@ function can_view($module) {
|
|||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
font-size: 0.95rem;
|
font-size: 0.95rem;
|
||||||
transition: all 0.2s ease;
|
transition: all 0.2s ease;
|
||||||
|
<?= $isRTL ? 'text-align: right;' : '' ?>
|
||||||
}
|
}
|
||||||
.sidebar .nav-link:hover, .sidebar .nav-link.active {
|
.sidebar .nav-link:hover, .sidebar .nav-link.active {
|
||||||
color: var(--sidebar-active-color);
|
color: var(--sidebar-active-color);
|
||||||
background: var(--sidebar-active-bg);
|
background: var(--sidebar-active-bg);
|
||||||
border-right: 3px solid var(--sidebar-active-border);
|
<?= $isRTL ? 'border-left: 3px solid var(--sidebar-active-border); border-right: none;' : 'border-right: 3px solid var(--sidebar-active-border); border-left: none;' ?>
|
||||||
}
|
}
|
||||||
.sidebar-heading {
|
.sidebar-heading {
|
||||||
font-size: 0.75rem;
|
font-size: 0.75rem;
|
||||||
@ -126,21 +149,21 @@ function can_view($module) {
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
background: none;
|
background: none;
|
||||||
border: none;
|
border: none;
|
||||||
text-align: left;
|
<?= $isRTL ? 'text-align: right; flex-direction: row-reverse;' : 'text-align: left;' ?>
|
||||||
}
|
}
|
||||||
.sidebar-heading:hover {
|
.sidebar-heading:hover {
|
||||||
color: var(--accent-color);
|
color: var(--accent-color);
|
||||||
}
|
}
|
||||||
.sidebar-heading i {
|
.sidebar-heading i:first-child {
|
||||||
font-size: 1rem;
|
font-size: 1rem;
|
||||||
margin-right: 0.5rem;
|
<?= $isRTL ? 'margin-left: 0.5rem; margin-right: 0;' : 'margin-right: 0.5rem; margin-left: 0;' ?>
|
||||||
color: var(--accent-color);
|
color: var(--accent-color);
|
||||||
}
|
}
|
||||||
.main-content { margin-left: 250px; padding: 2rem; }
|
.main-content { <?= $isRTL ? 'margin-right: 250px; margin-left: 0;' : 'margin-left: 250px; margin-right: 0;' ?> padding: 2rem; }
|
||||||
@media (max-width: 768px) {
|
@media (max-width: 768px) {
|
||||||
.sidebar { transform: translateX(-100%); transition: transform 0.3s ease; top: 56px; height: calc(100vh - 56px); }
|
.sidebar { transform: <?= $isRTL ? 'translateX(100%)' : 'translateX(-100%)' ?>; transition: transform 0.3s ease; top: 0; height: 100vh; }
|
||||||
.sidebar.show { transform: translateX(0); }
|
.sidebar.show { transform: translateX(0); }
|
||||||
.main-content { margin-left: 0; }
|
.main-content { margin-left: 0; margin-right: 0; }
|
||||||
.sidebar-header { display: none !important; } /* Hide duplicate logo on mobile */
|
.sidebar-header { display: none !important; } /* Hide duplicate logo on mobile */
|
||||||
}
|
}
|
||||||
.stat-card {
|
.stat-card {
|
||||||
@ -167,9 +190,14 @@ function can_view($module) {
|
|||||||
.dropdown-menu {
|
.dropdown-menu {
|
||||||
background-color: var(--bg-card);
|
background-color: var(--bg-card);
|
||||||
border-color: var(--border-color);
|
border-color: var(--border-color);
|
||||||
|
<?= $isRTL ? 'text-align: right;' : '' ?>
|
||||||
}
|
}
|
||||||
.dropdown-item {
|
.dropdown-item {
|
||||||
color: var(--text-primary);
|
color: var(--text-primary);
|
||||||
|
<?= $isRTL ? 'text-align: right;' : '' ?>
|
||||||
|
}
|
||||||
|
.dropdown-item i {
|
||||||
|
<?= $isRTL ? 'margin-left: 0.5rem; margin-right: 0;' : 'margin-right: 0.5rem; margin-left: 0;' ?>
|
||||||
}
|
}
|
||||||
.dropdown-item:hover {
|
.dropdown-item:hover {
|
||||||
background-color: var(--bg-body);
|
background-color: var(--bg-body);
|
||||||
@ -177,6 +205,13 @@ function can_view($module) {
|
|||||||
}
|
}
|
||||||
.dropdown-header {
|
.dropdown-header {
|
||||||
color: var(--text-secondary);
|
color: var(--text-secondary);
|
||||||
|
<?= $isRTL ? 'text-align: right;' : '' ?>
|
||||||
|
}
|
||||||
|
.offcanvas-start {
|
||||||
|
<?= $isRTL ? 'right: 0; left: auto; transform: translateX(100%);' : '' ?>
|
||||||
|
}
|
||||||
|
.offcanvas-start.show {
|
||||||
|
<?= $isRTL ? 'transform: translateX(0);' : '' ?>
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
<script>
|
<script>
|
||||||
@ -219,7 +254,7 @@ function can_view($module) {
|
|||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
<!-- Sidebar -->
|
<!-- Sidebar -->
|
||||||
<div class="offcanvas-md offcanvas-start sidebar" tabindex="-1" id="sidebarMenu">
|
<div class="offcanvas-md offcanvas-<?= $isRTL ? 'end' : 'start' ?> sidebar" tabindex="-1" id="sidebarMenu">
|
||||||
<div class="d-flex align-items-center justify-content-center sidebar-header d-none d-md-flex">
|
<div class="d-flex align-items-center justify-content-center sidebar-header d-none d-md-flex">
|
||||||
<a href="index.php" class="text-decoration-none">
|
<a href="index.php" class="text-decoration-none">
|
||||||
<?php if ($logoUrl): ?>
|
<?php if ($logoUrl): ?>
|
||||||
@ -229,8 +264,8 @@ function can_view($module) {
|
|||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="px-4 py-3 d-md-none">
|
<div class="px-4 py-3 d-md-none d-flex justify-content-between align-items-center">
|
||||||
<h5 class="fw-bold" style="color: var(--text-primary);">Menu</h5>
|
<h5 class="fw-bold m-0" style="color: var(--text-primary);"><?= t('menu_management') ?></h5><button type="button" class="btn-close" data-bs-dismiss="offcanvas" data-bs-target="#sidebarMenu" aria-label="Close"></button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="sidebar-content accordion" id="sidebarAccordion">
|
<div class="sidebar-content accordion" id="sidebarAccordion">
|
||||||
@ -238,7 +273,7 @@ function can_view($module) {
|
|||||||
<?php if (can_view('dashboard')): ?>
|
<?php if (can_view('dashboard')): ?>
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link <?= isActive('index.php') ?>" href="index.php">
|
<a class="nav-link <?= isActive('index.php') ?>" href="index.php">
|
||||||
<i class="bi bi-grid me-2"></i> Dashboard
|
<i class="bi bi-grid me-2"></i> <?= t('dashboard') ?>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
@ -252,7 +287,7 @@ function can_view($module) {
|
|||||||
<div class="nav-group">
|
<div class="nav-group">
|
||||||
<a class="sidebar-heading d-flex justify-content-between align-items-center text-decoration-none <?= getGroupToggleClass($posGroup) ?>"
|
<a class="sidebar-heading d-flex justify-content-between align-items-center text-decoration-none <?= getGroupToggleClass($posGroup) ?>"
|
||||||
data-bs-toggle="collapse" href="#collapsePos" role="button" aria-expanded="<?= isGroupExpanded($posGroup) ?>" aria-controls="collapsePos">
|
data-bs-toggle="collapse" href="#collapsePos" role="button" aria-expanded="<?= isGroupExpanded($posGroup) ?>" aria-controls="collapsePos">
|
||||||
<span><i class="bi bi-shop"></i> POS & Operations</span>
|
<span><i class="bi bi-shop"></i> <?= t('pos_operations') ?></span>
|
||||||
<i class="bi bi-chevron-down chevron-icon"></i>
|
<i class="bi bi-chevron-down chevron-icon"></i>
|
||||||
</a>
|
</a>
|
||||||
<div class="collapse <?= isGroupActive($posGroup) ?>" id="collapsePos" data-bs-parent="#sidebarAccordion">
|
<div class="collapse <?= isGroupActive($posGroup) ?>" id="collapsePos" data-bs-parent="#sidebarAccordion">
|
||||||
@ -260,28 +295,28 @@ function can_view($module) {
|
|||||||
<?php if (can_view('pos')): ?>
|
<?php if (can_view('pos')): ?>
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link" href="../pos.php" target="_blank">
|
<a class="nav-link" href="../pos.php" target="_blank">
|
||||||
<i class="bi bi-display me-2"></i> POS Terminal
|
<i class="bi bi-display me-2"></i> <?= t('pos_terminal') ?>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
<?php if (can_view('orders')): ?>
|
<?php if (can_view('orders')): ?>
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link <?= isActive('orders.php') ?>" href="orders.php">
|
<a class="nav-link <?= isActive('orders.php') ?>" href="orders.php">
|
||||||
<i class="bi bi-receipt me-2"></i> Orders (POS)
|
<i class="bi bi-receipt me-2"></i> <?= t('orders_pos') ?>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
<?php if (can_view('kitchen')): ?>
|
<?php if (can_view('kitchen')): ?>
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link" href="../kitchen.php" target="_blank">
|
<a class="nav-link" href="../kitchen.php" target="_blank">
|
||||||
<i class="bi bi-fire me-2"></i> Kitchen View
|
<i class="bi bi-fire me-2"></i> <?= t('kitchen_view') ?>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
<?php if (can_view('ads')): ?>
|
<?php if (can_view('ads')): ?>
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link <?= isActive('ads.php') || isActive('ad_edit.php') ? 'active' : '' ?>" href="ads.php">
|
<a class="nav-link <?= isActive('ads.php') || isActive('ad_edit.php') ? 'active' : '' ?>" href="ads.php">
|
||||||
<i class="bi bi-megaphone me-2"></i> Ads Management
|
<i class="bi bi-megaphone me-2"></i> <?= t('ads_management') ?>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
@ -298,7 +333,7 @@ function can_view($module) {
|
|||||||
<div class="nav-group">
|
<div class="nav-group">
|
||||||
<a class="sidebar-heading d-flex justify-content-between align-items-center text-decoration-none <?= getGroupToggleClass($menuGroup) ?>"
|
<a class="sidebar-heading d-flex justify-content-between align-items-center text-decoration-none <?= getGroupToggleClass($menuGroup) ?>"
|
||||||
data-bs-toggle="collapse" href="#collapseMenu" role="button" aria-expanded="<?= isGroupExpanded($menuGroup) ?>" aria-controls="collapseMenu">
|
data-bs-toggle="collapse" href="#collapseMenu" role="button" aria-expanded="<?= isGroupExpanded($menuGroup) ?>" aria-controls="collapseMenu">
|
||||||
<span><i class="bi bi-menu-button-wide"></i> Menu Management</span>
|
<span><i class="bi bi-menu-button-wide"></i> <?= t('menu_management') ?></span>
|
||||||
<i class="bi bi-chevron-down chevron-icon"></i>
|
<i class="bi bi-chevron-down chevron-icon"></i>
|
||||||
</a>
|
</a>
|
||||||
<div class="collapse <?= isGroupActive($menuGroup) ?>" id="collapseMenu" data-bs-parent="#sidebarAccordion">
|
<div class="collapse <?= isGroupActive($menuGroup) ?>" id="collapseMenu" data-bs-parent="#sidebarAccordion">
|
||||||
@ -306,14 +341,14 @@ function can_view($module) {
|
|||||||
<?php if (can_view('products')): ?>
|
<?php if (can_view('products')): ?>
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link <?= isActive('products.php') ?>" href="products.php">
|
<a class="nav-link <?= isActive('products.php') ?>" href="products.php">
|
||||||
<i class="bi bi-box-seam me-2"></i> Products
|
<i class="bi bi-box-seam me-2"></i> <?= t('products') ?>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
<?php if (can_view('categories')): ?>
|
<?php if (can_view('categories')): ?>
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link <?= isActive('categories.php') ?>" href="categories.php">
|
<a class="nav-link <?= isActive('categories.php') ?>" href="categories.php">
|
||||||
<i class="bi bi-tags me-2"></i> Categories
|
<i class="bi bi-tags me-2"></i> <?= t('categories') ?>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
@ -330,7 +365,7 @@ function can_view($module) {
|
|||||||
<div class="nav-group">
|
<div class="nav-group">
|
||||||
<a class="sidebar-heading d-flex justify-content-between align-items-center text-decoration-none <?= getGroupToggleClass($setupGroup) ?>"
|
<a class="sidebar-heading d-flex justify-content-between align-items-center text-decoration-none <?= getGroupToggleClass($setupGroup) ?>"
|
||||||
data-bs-toggle="collapse" href="#collapseSetup" role="button" aria-expanded="<?= isGroupExpanded($setupGroup) ?>" aria-controls="collapseSetup">
|
data-bs-toggle="collapse" href="#collapseSetup" role="button" aria-expanded="<?= isGroupExpanded($setupGroup) ?>" aria-controls="collapseSetup">
|
||||||
<span><i class="bi bi-gear-wide-connected"></i> Restaurant Setup</span>
|
<span><i class="bi bi-gear-wide-connected"></i> <?= t('restaurant_setup') ?></span>
|
||||||
<i class="bi bi-chevron-down chevron-icon"></i>
|
<i class="bi bi-chevron-down chevron-icon"></i>
|
||||||
</a>
|
</a>
|
||||||
<div class="collapse <?= isGroupActive($setupGroup) ?>" id="collapseSetup" data-bs-parent="#sidebarAccordion">
|
<div class="collapse <?= isGroupActive($setupGroup) ?>" id="collapseSetup" data-bs-parent="#sidebarAccordion">
|
||||||
@ -338,21 +373,21 @@ function can_view($module) {
|
|||||||
<?php if (can_view('outlets')): ?>
|
<?php if (can_view('outlets')): ?>
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link <?= isActive('outlets.php') ?>" href="outlets.php">
|
<a class="nav-link <?= isActive('outlets.php') ?>" href="outlets.php">
|
||||||
<i class="bi bi-shop me-2"></i> Outlets
|
<i class="bi bi-shop me-2"></i> <?= t('outlets') ?>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
<?php if (can_view('areas')): ?>
|
<?php if (can_view('areas')): ?>
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link <?= isActive('areas.php') ?>" href="areas.php">
|
<a class="nav-link <?= isActive('areas.php') ?>" href="areas.php">
|
||||||
<i class="bi bi-geo-alt me-2"></i> Areas
|
<i class="bi bi-geo-alt me-2"></i> <?= t('areas') ?>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
<?php if (can_view('tables')): ?>
|
<?php if (can_view('tables')): ?>
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link <?= isActive('tables.php') ?>" href="tables.php">
|
<a class="nav-link <?= isActive('tables.php') ?>" href="tables.php">
|
||||||
<i class="bi bi-ui-checks-grid me-2"></i> Tables
|
<i class="bi bi-ui-checks-grid me-2"></i> <?= t('tables') ?>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
@ -369,7 +404,7 @@ function can_view($module) {
|
|||||||
<div class="nav-group">
|
<div class="nav-group">
|
||||||
<a class="sidebar-heading d-flex justify-content-between align-items-center text-decoration-none <?= getGroupToggleClass($peopleGroup) ?>"
|
<a class="sidebar-heading d-flex justify-content-between align-items-center text-decoration-none <?= getGroupToggleClass($peopleGroup) ?>"
|
||||||
data-bs-toggle="collapse" href="#collapsePeople" role="button" aria-expanded="<?= isGroupExpanded($peopleGroup) ?>" aria-controls="collapsePeople">
|
data-bs-toggle="collapse" href="#collapsePeople" role="button" aria-expanded="<?= isGroupExpanded($peopleGroup) ?>" aria-controls="collapsePeople">
|
||||||
<span><i class="bi bi-people"></i> People & Partners</span>
|
<span><i class="bi bi-people"></i> <?= t('people_partners') ?></span>
|
||||||
<i class="bi bi-chevron-down chevron-icon"></i>
|
<i class="bi bi-chevron-down chevron-icon"></i>
|
||||||
</a>
|
</a>
|
||||||
<div class="collapse <?= isGroupActive($peopleGroup) ?>" id="collapsePeople" data-bs-parent="#sidebarAccordion">
|
<div class="collapse <?= isGroupActive($peopleGroup) ?>" id="collapsePeople" data-bs-parent="#sidebarAccordion">
|
||||||
@ -377,21 +412,21 @@ function can_view($module) {
|
|||||||
<?php if (can_view('customers')): ?>
|
<?php if (can_view('customers')): ?>
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link <?= isActive('customers.php') ?>" href="customers.php">
|
<a class="nav-link <?= isActive('customers.php') ?>" href="customers.php">
|
||||||
<i class="bi bi-people-fill me-2"></i> Customers
|
<i class="bi bi-people-fill me-2"></i> <?= t('customers') ?>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
<?php if (can_view('suppliers')): ?>
|
<?php if (can_view('suppliers')): ?>
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link <?= isActive('suppliers.php') ?>" href="suppliers.php">
|
<a class="nav-link <?= isActive('suppliers.php') ?>" href="suppliers.php">
|
||||||
<i class="bi bi-truck me-2"></i> Suppliers
|
<i class="bi bi-truck me-2"></i> <?= t('suppliers') ?>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
<?php if (can_view('loyalty')): ?>
|
<?php if (can_view('loyalty')): ?>
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link <?= isActive('loyalty.php') ?>" href="loyalty.php">
|
<a class="nav-link <?= isActive('loyalty.php') ?>" href="loyalty.php">
|
||||||
<i class="bi bi-award me-2"></i> Loyalty
|
<i class="bi bi-award me-2"></i> <?= t('loyalty') ?>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
@ -408,7 +443,7 @@ function can_view($module) {
|
|||||||
<div class="nav-group">
|
<div class="nav-group">
|
||||||
<a class="sidebar-heading d-flex justify-content-between align-items-center text-decoration-none <?= getGroupToggleClass($financialsGroup) ?>"
|
<a class="sidebar-heading d-flex justify-content-between align-items-center text-decoration-none <?= getGroupToggleClass($financialsGroup) ?>"
|
||||||
data-bs-toggle="collapse" href="#collapseFinancials" role="button" aria-expanded="<?= isGroupExpanded($financialsGroup) ?>" aria-controls="collapseFinancials">
|
data-bs-toggle="collapse" href="#collapseFinancials" role="button" aria-expanded="<?= isGroupExpanded($financialsGroup) ?>" aria-controls="collapseFinancials">
|
||||||
<span><i class="bi bi-wallet2"></i> Financials</span>
|
<span><i class="bi bi-wallet2"></i> <?= t('financials') ?></span>
|
||||||
<i class="bi bi-chevron-down chevron-icon"></i>
|
<i class="bi bi-chevron-down chevron-icon"></i>
|
||||||
</a>
|
</a>
|
||||||
<div class="collapse <?= isGroupActive($financialsGroup) ?>" id="collapseFinancials" data-bs-parent="#sidebarAccordion">
|
<div class="collapse <?= isGroupActive($financialsGroup) ?>" id="collapseFinancials" data-bs-parent="#sidebarAccordion">
|
||||||
@ -416,21 +451,21 @@ function can_view($module) {
|
|||||||
<?php if (can_view('purchases')): ?>
|
<?php if (can_view('purchases')): ?>
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link <?= isActive('purchases.php') ? 'active' : '' ?>" href="purchases.php">
|
<a class="nav-link <?= isActive('purchases.php') ? 'active' : '' ?>" href="purchases.php">
|
||||||
<i class="bi bi-cart-plus me-2"></i> Purchases
|
<i class="bi bi-cart-plus me-2"></i> <?= t('purchases') ?>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
<?php if (can_view('expenses')): ?>
|
<?php if (can_view('expenses')): ?>
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link <?= isActive('expenses.php') ? 'active' : '' ?>" href="expenses.php">
|
<a class="nav-link <?= isActive('expenses.php') ? 'active' : '' ?>" href="expenses.php">
|
||||||
<i class="bi bi-cash-stack me-2"></i> Expenses
|
<i class="bi bi-cash-stack me-2"></i> <?= t('expenses') ?>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
<?php if (can_view('expense_categories')): ?>
|
<?php if (can_view('expense_categories')): ?>
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link <?= isActive('expense_categories.php') || isActive('expense_category_edit.php') ? 'active' : '' ?>" href="expense_categories.php">
|
<a class="nav-link <?= isActive('expense_categories.php') || isActive('expense_category_edit.php') ? 'active' : '' ?>" href="expense_categories.php">
|
||||||
<i class="bi bi-tags me-2"></i> Expense Categories
|
<i class="bi bi-tags me-2"></i> <?= t('expense_categories') ?>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
@ -446,14 +481,14 @@ function can_view($module) {
|
|||||||
<div class="nav-group">
|
<div class="nav-group">
|
||||||
<a class="sidebar-heading d-flex justify-content-between align-items-center text-decoration-none <?= getGroupToggleClass($reportsGroup) ?>"
|
<a class="sidebar-heading d-flex justify-content-between align-items-center text-decoration-none <?= getGroupToggleClass($reportsGroup) ?>"
|
||||||
data-bs-toggle="collapse" href="#collapseReports" role="button" aria-expanded="<?= isGroupExpanded($reportsGroup) ?>" aria-controls="collapseReports">
|
data-bs-toggle="collapse" href="#collapseReports" role="button" aria-expanded="<?= isGroupExpanded($reportsGroup) ?>" aria-controls="collapseReports">
|
||||||
<span><i class="bi bi-bar-chart-line"></i> Reports & Analytics</span>
|
<span><i class="bi bi-bar-chart-line"></i> <?= t('reports_analytics') ?></span>
|
||||||
<i class="bi bi-chevron-down chevron-icon"></i>
|
<i class="bi bi-chevron-down chevron-icon"></i>
|
||||||
</a>
|
</a>
|
||||||
<div class="collapse <?= isGroupActive($reportsGroup) ?>" id="collapseReports" data-bs-parent="#sidebarAccordion">
|
<div class="collapse <?= isGroupActive($reportsGroup) ?>" id="collapseReports" data-bs-parent="#sidebarAccordion">
|
||||||
<ul class="nav flex-column">
|
<ul class="nav flex-column">
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link <?= isActive('reports.php') ?>" href="reports.php">
|
<a class="nav-link <?= isActive('reports.php') ?>" href="reports.php">
|
||||||
<i class="bi bi-graph-up me-2"></i> Daily Reports
|
<i class="bi bi-graph-up me-2"></i> <?= t('daily_reports') ?>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
@ -469,7 +504,7 @@ function can_view($module) {
|
|||||||
<div class="nav-group">
|
<div class="nav-group">
|
||||||
<a class="sidebar-heading d-flex justify-content-between align-items-center text-decoration-none <?= getGroupToggleClass($userGroupPages) ?>"
|
<a class="sidebar-heading d-flex justify-content-between align-items-center text-decoration-none <?= getGroupToggleClass($userGroupPages) ?>"
|
||||||
data-bs-toggle="collapse" href="#collapseUsers" role="button" aria-expanded="<?= isGroupExpanded($userGroupPages) ?>" aria-controls="collapseUsers">
|
data-bs-toggle="collapse" href="#collapseUsers" role="button" aria-expanded="<?= isGroupExpanded($userGroupPages) ?>" aria-controls="collapseUsers">
|
||||||
<span><i class="bi bi-person-badge"></i> User Management</span>
|
<span><i class="bi bi-person-badge"></i> <?= t('user_management') ?></span>
|
||||||
<i class="bi bi-chevron-down chevron-icon"></i>
|
<i class="bi bi-chevron-down chevron-icon"></i>
|
||||||
</a>
|
</a>
|
||||||
<div class="collapse <?= isGroupActive($userGroupPages) ?>" id="collapseUsers" data-bs-parent="#sidebarAccordion">
|
<div class="collapse <?= isGroupActive($userGroupPages) ?>" id="collapseUsers" data-bs-parent="#sidebarAccordion">
|
||||||
@ -477,25 +512,25 @@ function can_view($module) {
|
|||||||
<?php if (can_view('users')): ?>
|
<?php if (can_view('users')): ?>
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link <?= isActive('users.php') ?>" href="users.php">
|
<a class="nav-link <?= isActive('users.php') ?>" href="users.php">
|
||||||
<i class="bi bi-people me-2"></i> Users
|
<i class="bi bi-people me-2"></i> <?= t('users') ?>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
<?php if (can_view('user_groups')): ?>
|
<?php if (can_view('user_groups')): ?>
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link <?= isActive('user_groups.php') ?>" href="user_groups.php">
|
<a class="nav-link <?= isActive('user_groups.php') ?>" href="user_groups.php">
|
||||||
<i class="bi bi-shield-lock me-2"></i> Roles / Groups
|
<i class="bi bi-shield-lock me-2"></i> <?= t('roles_groups') ?>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link <?= isActive('attendance.php') ?>" href="attendance.php">
|
<a class="nav-link <?= isActive('attendance.php') ?>" href="attendance.php">
|
||||||
<i class="bi bi-calendar-check me-2"></i> Attendance
|
<i class="bi bi-calendar-check me-2"></i> <?= t('attendance') ?>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link <?= isActive('ratings.php') ?>" href="ratings.php">
|
<a class="nav-link <?= isActive('ratings.php') ?>" href="ratings.php">
|
||||||
<i class="bi bi-star me-2"></i> Staff Ratings
|
<i class="bi bi-star me-2"></i> <?= t('staff_ratings') ?>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
@ -511,7 +546,7 @@ function can_view($module) {
|
|||||||
<div class="nav-group">
|
<div class="nav-group">
|
||||||
<a class="sidebar-heading d-flex justify-content-between align-items-center text-decoration-none <?= getGroupToggleClass($settingsGroup) ?>"
|
<a class="sidebar-heading d-flex justify-content-between align-items-center text-decoration-none <?= getGroupToggleClass($settingsGroup) ?>"
|
||||||
data-bs-toggle="collapse" href="#collapseSettings" role="button" aria-expanded="<?= isGroupExpanded($settingsGroup) ?>" aria-controls="collapseSettings">
|
data-bs-toggle="collapse" href="#collapseSettings" role="button" aria-expanded="<?= isGroupExpanded($settingsGroup) ?>" aria-controls="collapseSettings">
|
||||||
<span><i class="bi bi-sliders"></i> Settings</span>
|
<span><i class="bi bi-sliders"></i> <?= t('settings') ?></span>
|
||||||
<i class="bi bi-chevron-down chevron-icon"></i>
|
<i class="bi bi-chevron-down chevron-icon"></i>
|
||||||
</a>
|
</a>
|
||||||
<div class="collapse <?= isGroupActive($settingsGroup) ?>" id="collapseSettings" data-bs-parent="#sidebarAccordion">
|
<div class="collapse <?= isGroupActive($settingsGroup) ?>" id="collapseSettings" data-bs-parent="#sidebarAccordion">
|
||||||
@ -519,31 +554,31 @@ function can_view($module) {
|
|||||||
<?php if (can_view('payment_types')): ?>
|
<?php if (can_view('payment_types')): ?>
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link <?= isActive('payment_types.php') ?>" href="payment_types.php">
|
<a class="nav-link <?= isActive('payment_types.php') ?>" href="payment_types.php">
|
||||||
<i class="bi bi-credit-card me-2"></i> Payment Types
|
<i class="bi bi-credit-card me-2"></i> <?= t('payment_types') ?>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
<?php if (can_view('settings')): ?>
|
<?php if (can_view('settings')): ?>
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link <?= isActive('integrations.php') ?>" href="integrations.php">
|
<a class="nav-link <?= isActive('integrations.php') ?>" href="integrations.php">
|
||||||
<i class="bi bi-plugin me-2"></i> Integrations
|
<i class="bi bi-plugin me-2"></i> <?= t('integrations') ?>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link <?= isActive('company.php') ?>" href="company.php">
|
<a class="nav-link <?= isActive('company.php') ?>" href="company.php">
|
||||||
<i class="bi bi-building me-2"></i> Company
|
<i class="bi bi-building me-2"></i> <?= t('company') ?>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link <?= isActive('backup.php') ?>" href="backup.php">
|
<a class="nav-link <?= isActive('backup.php') ?>" href="backup.php">
|
||||||
<i class="bi bi-cloud-arrow-down me-2"></i> Backup & Restore
|
<i class="bi bi-cloud-arrow-down me-2"></i> <?= t('backup_restore') ?>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
|
|
||||||
<li class="nav-item border-top mt-2 pt-2">
|
<li class="nav-item border-top mt-2 pt-2">
|
||||||
<a class="nav-link text-muted" href="../index.php" target="_blank">
|
<a class="nav-link text-muted" href="../index.php" target="_blank">
|
||||||
<i class="bi bi-box-arrow-up-right me-2"></i> View Site
|
<i class="bi bi-box-arrow-up-right me-2"></i> <?= t('view_site') ?>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
@ -557,19 +592,32 @@ function can_view($module) {
|
|||||||
<!-- Top Header -->
|
<!-- Top Header -->
|
||||||
<header class="d-flex justify-content-end align-items-center mb-4 pb-3 border-bottom">
|
<header class="d-flex justify-content-end align-items-center mb-4 pb-3 border-bottom">
|
||||||
<div class="d-flex align-items-center gap-3">
|
<div class="d-flex align-items-center gap-3">
|
||||||
|
<!-- Language Switcher -->
|
||||||
|
<div class="dropdown">
|
||||||
|
<button class="btn btn-link text-decoration-none dropdown-toggle d-flex align-items-center gap-2" type="button" id="topLangDropdown" data-bs-toggle="dropdown" aria-expanded="false" style="color: var(--text-primary);">
|
||||||
|
<i class="bi bi-translate"></i>
|
||||||
|
<span class="d-none d-sm-inline"><?= t('language') ?></span>
|
||||||
|
</button>
|
||||||
|
<ul class="dropdown-menu dropdown-menu-end shadow border-0" aria-labelledby="topLangDropdown">
|
||||||
|
<li><h6 class="dropdown-header"><?= t('select_language') ?></h6></li>
|
||||||
|
<li><a class="dropdown-item d-flex align-items-center gap-2" href="?lang=en"><?= t('english') ?></a></li>
|
||||||
|
<li><a class="dropdown-item d-flex align-items-center gap-2" href="?lang=ar"><?= t('arabic') ?></a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- Theme Switcher -->
|
<!-- Theme Switcher -->
|
||||||
<div class="dropdown">
|
<div class="dropdown">
|
||||||
<button class="btn btn-link text-decoration-none dropdown-toggle d-flex align-items-center gap-2" type="button" id="topThemeDropdown" data-bs-toggle="dropdown" aria-expanded="false" style="color: var(--text-primary);">
|
<button class="btn btn-link text-decoration-none dropdown-toggle d-flex align-items-center gap-2" type="button" id="topThemeDropdown" data-bs-toggle="dropdown" aria-expanded="false" style="color: var(--text-primary);">
|
||||||
<i class="bi bi-palette"></i>
|
<i class="bi bi-palette"></i>
|
||||||
<span class="d-none d-sm-inline">Theme</span>
|
<span class="d-none d-sm-inline"><?= t('theme') ?></span>
|
||||||
</button>
|
</button>
|
||||||
<ul class="dropdown-menu dropdown-menu-end shadow border-0" aria-labelledby="topThemeDropdown">
|
<ul class="dropdown-menu dropdown-menu-end shadow border-0" aria-labelledby="topThemeDropdown">
|
||||||
<li><h6 class="dropdown-header">Select Theme</h6></li>
|
<li><h6 class="dropdown-header"><?= t('select_theme') ?></h6></li>
|
||||||
<li><button class="dropdown-item d-flex align-items-center gap-2" onclick="setTheme('default')"><span class="d-inline-block rounded-circle" style="width:12px;height:12px;background:#eee;border:1px solid #ddd"></span> Default</button></li>
|
<li><button class="dropdown-item d-flex align-items-center gap-2" onclick="setTheme('default')"><span class="d-inline-block rounded-circle" style="width:12px;height:12px;background:#eee;border:1px solid #ddd"></span> <?= t('default') ?></button></li>
|
||||||
<li><button class="dropdown-item d-flex align-items-center gap-2" onclick="setTheme('dark')"><span class="d-inline-block rounded-circle" style="width:12px;height:12px;background:#333"></span> Dark</button></li>
|
<li><button class="dropdown-item d-flex align-items-center gap-2" onclick="setTheme('dark')"><span class="d-inline-block rounded-circle" style="width:12px;height:12px;background:#333"></span> <?= t('dark') ?></button></li>
|
||||||
<li><button class="dropdown-item d-flex align-items-center gap-2" onclick="setTheme('ocean')"><span class="d-inline-block rounded-circle" style="width:12px;height:12px;background:#0077B6"></span> Ocean</button></li>
|
<li><button class="dropdown-item d-flex align-items-center gap-2" onclick="setTheme('ocean')"><span class="d-inline-block rounded-circle" style="width:12px;height:12px;background:#0077B6"></span> <?= t('ocean') ?></button></li>
|
||||||
<li><button class="dropdown-item d-flex align-items-center gap-2" onclick="setTheme('forest')"><span class="d-inline-block rounded-circle" style="width:12px;height:12px;background:#2D6A4F"></span> Forest</button></li>
|
<li><button class="dropdown-item d-flex align-items-center gap-2" onclick="setTheme('forest')"><span class="d-inline-block rounded-circle" style="width:12px;height:12px;background:#2D6A4F"></span> <?= t('forest') ?></button></li>
|
||||||
<li><button class="dropdown-item d-flex align-items-center gap-2" onclick="setTheme('grape')"><span class="d-inline-block rounded-circle" style="width:12px;height:12px;background:#7B1FA2"></span> Grape</button></li>
|
<li><button class="dropdown-item d-flex align-items-center gap-2" onclick="setTheme('grape')"><span class="d-inline-block rounded-circle" style="width:12px;height:12px;background:#7B1FA2"></span> <?= t('grape') ?></button></li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -584,13 +632,13 @@ function can_view($module) {
|
|||||||
<span class="d-none d-sm-inline fw-medium"><?= htmlspecialchars($userName) ?></span>
|
<span class="d-none d-sm-inline fw-medium"><?= htmlspecialchars($userName) ?></span>
|
||||||
</a>
|
</a>
|
||||||
<ul class="dropdown-menu dropdown-menu-end shadow border-0" aria-labelledby="userDropdown">
|
<ul class="dropdown-menu dropdown-menu-end shadow border-0" aria-labelledby="userDropdown">
|
||||||
<li><span class="dropdown-item-text text-muted small">Signed in as <?= htmlspecialchars($userGroup) ?></span></li>
|
<li><span class="dropdown-item-text text-muted small"><?= t('signed_in_as') ?> <?= htmlspecialchars($userGroup) ?></span></li>
|
||||||
<li><hr class="dropdown-divider"></li>
|
<li><hr class="dropdown-divider"></li>
|
||||||
<li><a class="dropdown-item" href="profile.php"><i class="bi bi-person me-2"></i> My Profile</a></li>
|
<li><a class="dropdown-item" href="profile.php"><i class="bi bi-person me-2"></i> <?= t('my_profile') ?></a></li>
|
||||||
<li><a class="dropdown-item" href="company.php"><i class="bi bi-building me-2"></i> Company Settings</a></li>
|
<li><a class="dropdown-item" href="company.php"><i class="bi bi-building me-2"></i> <?= t('company_settings') ?></a></li>
|
||||||
<li><hr class="dropdown-divider"></li>
|
<li><hr class="dropdown-divider"></li>
|
||||||
<li><a class="dropdown-item text-danger" href="<?= get_base_url() ?>logout.php"><i class="bi bi-box-arrow-right me-2"></i> Logout</a></li>
|
<li><a class="dropdown-item text-danger" href="<?= get_base_url() ?>logout.php"><i class="bi bi-box-arrow-right me-2"></i> <?= t('logout') ?></a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
|
|||||||
@ -130,12 +130,12 @@ include 'includes/header.php';
|
|||||||
|
|
||||||
<div class="d-flex justify-content-between align-items-center mb-4">
|
<div class="d-flex justify-content-between align-items-center mb-4">
|
||||||
<div>
|
<div>
|
||||||
<h2 class="fw-bold mb-1">Products Catalog</h2>
|
<h2 class="fw-bold mb-1"><?= t('products') ?></h2>
|
||||||
<p class="text-muted mb-0">Manage items, stock, and pricing</p>
|
<p class="text-muted mb-0">Manage items, stock, and pricing</p>
|
||||||
</div>
|
</div>
|
||||||
<?php if (has_permission('products_add')): ?>
|
<?php if (has_permission('products_add')): ?>
|
||||||
<button class="btn btn-primary btn-lg shadow-sm" data-bs-toggle="modal" data-bs-target="#productModal" onclick="prepareAddForm()" style="border-radius: 12px;">
|
<button class="btn btn-primary btn-lg shadow-sm" data-bs-toggle="modal" data-bs-target="#productModal" onclick="prepareAddForm()" style="border-radius: 12px;">
|
||||||
<i class="bi bi-plus-lg me-1"></i> Add Product
|
<i class="bi bi-plus-lg me-1"></i> <?= t('add') ?> <?= t('products') ?>
|
||||||
</button>
|
</button>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
</div>
|
</div>
|
||||||
@ -147,12 +147,12 @@ include 'includes/header.php';
|
|||||||
<div class="col-md-5">
|
<div class="col-md-5">
|
||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
<span class="input-group-text bg-light border-0 text-muted"><i class="bi bi-search"></i></span>
|
<span class="input-group-text bg-light border-0 text-muted"><i class="bi bi-search"></i></span>
|
||||||
<input type="text" name="search" class="form-control border-0 bg-light" placeholder="Search products..." value="<?= htmlspecialchars($search) ?>" style="border-radius: 0 10px 10px 0;">
|
<input type="text" name="search" class="form-control border-0 bg-light" placeholder="<?= t('search') ?>..." value="<?= htmlspecialchars($search) ?>" style="border-radius: 0 10px 10px 0;">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-3">
|
<div class="col-md-3">
|
||||||
<select name="category_filter" class="form-select border-0 bg-light rounded-3" onchange="this.form.submit()">
|
<select name="category_filter" class="form-select border-0 bg-light rounded-3" onchange="this.form.submit()">
|
||||||
<option value="">All Categories</option>
|
<option value=""><?= t('all') ?> <?= t('categories') ?></option>
|
||||||
<?php foreach ($categories as $cat): ?>
|
<?php foreach ($categories as $cat): ?>
|
||||||
<option value="<?= $cat['id'] ?>" <?= $category_filter == $cat['id'] ? 'selected' : '' ?>><?= htmlspecialchars($cat['name']) ?></option>
|
<option value="<?= $cat['id'] ?>" <?= $category_filter == $cat['id'] ? 'selected' : '' ?>><?= htmlspecialchars($cat['name']) ?></option>
|
||||||
<?php endforeach; ?>
|
<?php endforeach; ?>
|
||||||
@ -164,7 +164,7 @@ include 'includes/header.php';
|
|||||||
<?php if (empty($products)): ?>
|
<?php if (empty($products)): ?>
|
||||||
<div class="text-center py-5 bg-white rounded-4 shadow-sm">
|
<div class="text-center py-5 bg-white rounded-4 shadow-sm">
|
||||||
<i class="bi bi-box-seam display-1 text-muted opacity-25 mb-3 d-block"></i>
|
<i class="bi bi-box-seam display-1 text-muted opacity-25 mb-3 d-block"></i>
|
||||||
<h4 class="text-dark">No products found</h4>
|
<h4 class="text-dark"><?= t('none') ?></h4>
|
||||||
<p class="text-muted">Try adjusting your filters or search terms.</p>
|
<p class="text-muted">Try adjusting your filters or search terms.</p>
|
||||||
</div>
|
</div>
|
||||||
<?php else: ?>
|
<?php else: ?>
|
||||||
@ -173,12 +173,12 @@ include 'includes/header.php';
|
|||||||
<table class="table table-hover align-middle mb-0">
|
<table class="table table-hover align-middle mb-0">
|
||||||
<thead class="bg-light">
|
<thead class="bg-light">
|
||||||
<tr>
|
<tr>
|
||||||
<th class="ps-4">Product</th>
|
<th class="ps-4"><?= t('products') ?></th>
|
||||||
<th>Category</th>
|
<th><?= t('category') ?></th>
|
||||||
<th>Stock</th>
|
<th><?= t('stock') ?></th>
|
||||||
<th>Price</th>
|
<th><?= t('price') ?></th>
|
||||||
<th>Promotion</th>
|
<th>Promotion</th>
|
||||||
<th class="text-end pe-4">Actions</th>
|
<th class="text-end pe-4"><?= t('actions') ?></th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
@ -205,11 +205,11 @@ include 'includes/header.php';
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td><span class="badge bg-light text-dark border px-2 py-1"><?= htmlspecialchars($product['category_name'] ?? 'Uncategorized') ?></span></td>
|
<td><span class="badge bg-light text-dark border px-2 py-1"><?= htmlspecialchars($product['category_name'] ?? t('none')) ?></span></td>
|
||||||
<td>
|
<td>
|
||||||
<?php $stock = (int)$product['stock_quantity']; ?>
|
<?php $stock = (int)$product['stock_quantity']; ?>
|
||||||
<span class="badge <?= $stock <= 5 ? 'bg-danger-subtle text-danger' : ($stock <= 20 ? 'bg-warning-subtle text-warning' : 'bg-success-subtle text-success') ?> px-2 py-1 border border-<?= $stock <= 5 ? 'danger' : ($stock <= 20 ? 'warning' : 'success') ?>">
|
<span class="badge <?= $stock <= 5 ? 'bg-danger-subtle text-danger' : ($stock <= 20 ? 'bg-warning-subtle text-warning' : 'bg-success-subtle text-success') ?> px-2 py-1 border border-<?= $stock <= 5 ? 'danger' : ($stock <= 20 ? 'warning' : 'success') ?>">
|
||||||
<?= $stock ?> in stock
|
<?= $stock ?> <?= t('stock') ?>
|
||||||
</span>
|
</span>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
@ -225,7 +225,7 @@ include 'includes/header.php';
|
|||||||
<?php if ($is_promo_active): ?>
|
<?php if ($is_promo_active): ?>
|
||||||
<span class="badge bg-success rounded-pill px-2">-<?= floatval($product['promo_discount_percent']) ?>%</span>
|
<span class="badge bg-success rounded-pill px-2">-<?= floatval($product['promo_discount_percent']) ?>%</span>
|
||||||
<?php elseif (!empty($product['promo_discount_percent'])): ?>
|
<?php elseif (!empty($product['promo_discount_percent'])): ?>
|
||||||
<span class="badge bg-secondary rounded-pill px-2">Inactive</span>
|
<span class="badge bg-secondary rounded-pill px-2"><?= t('inactive') ?></span>
|
||||||
<?php else: ?>
|
<?php else: ?>
|
||||||
<span class="text-muted small">-</span>
|
<span class="text-muted small">-</span>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
@ -246,11 +246,11 @@ include 'includes/header.php';
|
|||||||
<?php if (has_permission('products_edit') || has_permission('products_add')): ?>
|
<?php if (has_permission('products_edit') || has_permission('products_add')): ?>
|
||||||
<button type="button" class="btn btn-sm btn-outline-primary rounded-pill px-3"
|
<button type="button" class="btn btn-sm btn-outline-primary rounded-pill px-3"
|
||||||
data-bs-toggle="modal" data-bs-target="#productModal"
|
data-bs-toggle="modal" data-bs-target="#productModal"
|
||||||
onclick='prepareEditForm(<?= htmlspecialchars(json_encode($product), ENT_QUOTES, "UTF-8") ?>)'>Edit</button>
|
onclick='prepareEditForm(<?= htmlspecialchars(json_encode($product), ENT_QUOTES, "UTF-8") ?>)'><?= t('edit') ?></button>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
|
|
||||||
<?php if (has_permission('products_del')): ?>
|
<?php if (has_permission('products_del')): ?>
|
||||||
<a href="?delete=<?= $product['id'] ?>" class="btn btn-sm btn-outline-danger rounded-pill px-3" onclick="return confirm('Delete this product? This action cannot be undone.')">Delete</a>
|
<a href="?delete=<?= $product['id'] ?>" class="btn btn-sm btn-outline-danger rounded-pill px-3" onclick="return confirm('Delete this product? This action cannot be undone.')"><?= t('delete') ?></a>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
@ -271,7 +271,7 @@ include 'includes/header.php';
|
|||||||
<div class="modal-dialog modal-lg">
|
<div class="modal-dialog modal-lg">
|
||||||
<div class="modal-content border-0 shadow-lg rounded-4">
|
<div class="modal-content border-0 shadow-lg rounded-4">
|
||||||
<div class="modal-header bg-primary text-white border-0 py-3">
|
<div class="modal-header bg-primary text-white border-0 py-3">
|
||||||
<h5 class="modal-title fw-bold" id="productModalTitle">Add New Product</h5>
|
<h5 class="modal-title fw-bold" id="productModalTitle"><?= t('add') ?> <?= t('products') ?></h5>
|
||||||
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal" aria-label="Close"></button>
|
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||||
</div>
|
</div>
|
||||||
<form method="POST" id="productForm" enctype="multipart/form-data">
|
<form method="POST" id="productForm" enctype="multipart/form-data">
|
||||||
@ -282,13 +282,18 @@ include 'includes/header.php';
|
|||||||
<div class="row g-3 mb-4">
|
<div class="row g-3 mb-4">
|
||||||
<div class="col-md-8">
|
<div class="col-md-8">
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label class="form-label small fw-bold text-muted">PRODUCT NAME (EN) <span class="text-danger">*</span></label>
|
<label class="form-label small fw-bold text-muted d-flex justify-content-between">
|
||||||
|
<span><?= t('name') ?> (EN) <span class="text-danger">*</span></span>
|
||||||
|
<a href="javascript:void(0)" onclick="translateTo('English')" class="text-decoration-none small text-primary fw-bold" id="translateBtnEn">
|
||||||
|
<i class="bi bi-translate me-1"></i> Auto-translate
|
||||||
|
</a>
|
||||||
|
</label>
|
||||||
<input type="text" name="name" id="productName" class="form-control rounded-3" required>
|
<input type="text" name="name" id="productName" class="form-control rounded-3" required>
|
||||||
</div>
|
</div>
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label class="form-label small fw-bold text-muted d-flex justify-content-between">
|
<label class="form-label small fw-bold text-muted d-flex justify-content-between">
|
||||||
<span>PRODUCT NAME (ARABIC)</span>
|
<span><?= t('arabic_name') ?></span>
|
||||||
<a href="javascript:void(0)" onclick="translateName()" class="text-decoration-none small text-primary fw-bold" id="translateBtn">
|
<a href="javascript:void(0)" onclick="translateTo('Arabic')" class="text-decoration-none small text-primary fw-bold" id="translateBtnAr">
|
||||||
<i class="bi bi-translate me-1"></i> Auto-translate
|
<i class="bi bi-translate me-1"></i> Auto-translate
|
||||||
</a>
|
</a>
|
||||||
</label>
|
</label>
|
||||||
@ -298,7 +303,7 @@ include 'includes/header.php';
|
|||||||
</div>
|
</div>
|
||||||
<div class="row g-3">
|
<div class="row g-3">
|
||||||
<div class="col-md-6 mb-3">
|
<div class="col-md-6 mb-3">
|
||||||
<label class="form-label small fw-bold text-muted">CATEGORY <span class="text-danger">*</span></label>
|
<label class="form-label small fw-bold text-muted"><?= t('category') ?> <span class="text-danger">*</span></label>
|
||||||
<select name="category_id" id="productCategoryId" class="form-select rounded-3" required>
|
<select name="category_id" id="productCategoryId" class="form-select rounded-3" required>
|
||||||
<?php foreach ($categories as $cat): ?>
|
<?php foreach ($categories as $cat): ?>
|
||||||
<option value="<?= $cat['id'] ?>"><?= htmlspecialchars($cat['name']) ?></option>
|
<option value="<?= $cat['id'] ?>"><?= htmlspecialchars($cat['name']) ?></option>
|
||||||
@ -306,7 +311,7 @@ include 'includes/header.php';
|
|||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-6 mb-3">
|
<div class="col-md-6 mb-3">
|
||||||
<label class="form-label small fw-bold text-muted">SELLING PRICE <span class="text-danger">*</span></label>
|
<label class="form-label small fw-bold text-muted"><?= t('price') ?> <span class="text-danger">*</span></label>
|
||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
<span class="input-group-text bg-light border-0"><?= get_company_settings()['currency_symbol'] ?></span>
|
<span class="input-group-text bg-light border-0"><?= get_company_settings()['currency_symbol'] ?></span>
|
||||||
<input type="number" step="0.01" name="price" id="productPrice" class="form-control rounded-3 border-0 bg-light" required>
|
<input type="number" step="0.01" name="price" id="productPrice" class="form-control rounded-3 border-0 bg-light" required>
|
||||||
@ -319,7 +324,7 @@ include 'includes/header.php';
|
|||||||
<input type="number" step="0.01" name="cost_price" id="productCostPrice" class="form-control rounded-3 border-0 bg-light">
|
<input type="number" step="0.01" name="cost_price" id="productCostPrice" class="form-control rounded-3 border-0 bg-light">
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-6 mb-3">
|
<div class="col-md-6 mb-3">
|
||||||
<label class="form-label small fw-bold text-muted">STOCK QUANTITY</label>
|
<label class="form-label small fw-bold text-muted"><?= t('stock') ?></label>
|
||||||
<input type="number" name="stock_quantity" id="productStockQuantity" class="form-control rounded-3 border-0 bg-light">
|
<input type="number" name="stock_quantity" id="productStockQuantity" class="form-control rounded-3 border-0 bg-light">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -346,7 +351,7 @@ include 'includes/header.php';
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="mb-4">
|
<div class="mb-4">
|
||||||
<label class="form-label small fw-bold text-muted">DESCRIPTION</label>
|
<label class="form-label small fw-bold text-muted"><?= t('description') ?></label>
|
||||||
<textarea name="description" id="productDescription" class="form-control rounded-3" rows="3" placeholder="Describe your product..."></textarea>
|
<textarea name="description" id="productDescription" class="form-control rounded-3" rows="3" placeholder="Describe your product..."></textarea>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -362,8 +367,8 @@ include 'includes/header.php';
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer border-0 p-4 pt-0">
|
<div class="modal-footer border-0 p-4 pt-0">
|
||||||
<button type="button" class="btn btn-light rounded-pill px-4" data-bs-dismiss="modal">Cancel</button>
|
<button type="button" class="btn btn-light rounded-pill px-4" data-bs-dismiss="modal"><?= t('cancel') ?></button>
|
||||||
<button type="submit" class="btn btn-primary rounded-pill px-4 fw-bold shadow-sm">Save Product</button>
|
<button type="submit" class="btn btn-primary rounded-pill px-4 fw-bold shadow-sm"><?= t('save') ?></button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
@ -372,7 +377,7 @@ include 'includes/header.php';
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
function prepareAddForm() {
|
function prepareAddForm() {
|
||||||
document.getElementById('productModalTitle').innerText = 'Add New Product';
|
document.getElementById('productModalTitle').innerText = '<?= t('add') ?> <?= t('products') ?>';
|
||||||
document.getElementById('productAction').value = 'add_product';
|
document.getElementById('productAction').value = 'add_product';
|
||||||
document.getElementById('productForm').reset();
|
document.getElementById('productForm').reset();
|
||||||
document.getElementById('productId').value = '';
|
document.getElementById('productId').value = '';
|
||||||
@ -381,7 +386,7 @@ function prepareAddForm() {
|
|||||||
|
|
||||||
function prepareEditForm(prod) {
|
function prepareEditForm(prod) {
|
||||||
if (!prod) return;
|
if (!prod) return;
|
||||||
document.getElementById('productModalTitle').innerText = 'Edit Product: ' + prod.name;
|
document.getElementById('productModalTitle').innerText = '<?= t('edit') ?> <?= t('products') ?>: ' + prod.name;
|
||||||
document.getElementById('productAction').value = 'edit_product';
|
document.getElementById('productAction').value = 'edit_product';
|
||||||
document.getElementById('productId').value = prod.id;
|
document.getElementById('productId').value = prod.id;
|
||||||
document.getElementById('productName').value = prod.name;
|
document.getElementById('productName').value = prod.name;
|
||||||
@ -404,14 +409,18 @@ function prepareEditForm(prod) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function translateName() {
|
async function translateTo(targetLang) {
|
||||||
const enName = document.getElementById('productName').value;
|
const sourceId = targetLang === 'Arabic' ? 'productName' : 'productNameAr';
|
||||||
if (!enName) {
|
const targetId = targetLang === 'Arabic' ? 'productNameAr' : 'productName';
|
||||||
alert('Please enter an English name first.');
|
const btnId = targetLang === 'Arabic' ? 'translateBtnAr' : 'translateBtnEn';
|
||||||
|
|
||||||
|
const sourceText = document.getElementById(sourceId).value;
|
||||||
|
if (!sourceText) {
|
||||||
|
alert('Please enter text to translate first.');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const btn = document.getElementById('translateBtn');
|
const btn = document.getElementById(btnId);
|
||||||
const originalContent = btn.innerHTML;
|
const originalContent = btn.innerHTML;
|
||||||
btn.innerHTML = '<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span> Translating...';
|
btn.innerHTML = '<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span> Translating...';
|
||||||
btn.classList.add('disabled');
|
btn.classList.add('disabled');
|
||||||
@ -420,11 +429,11 @@ async function translateName() {
|
|||||||
const response = await fetch('../api/translate.php', {
|
const response = await fetch('../api/translate.php', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: { 'Content-Type': 'application/json' },
|
headers: { 'Content-Type': 'application/json' },
|
||||||
body: JSON.stringify({ text: enName, target_lang: 'Arabic' })
|
body: JSON.stringify({ text: sourceText, target_lang: targetLang })
|
||||||
});
|
});
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
if (data.success) {
|
if (data.success) {
|
||||||
document.getElementById('productNameAr').value = data.translated_text;
|
document.getElementById(targetId).value = data.translated_text;
|
||||||
} else {
|
} else {
|
||||||
alert('Translation error: ' + data.error);
|
alert('Translation error: ' + data.error);
|
||||||
}
|
}
|
||||||
@ -439,4 +448,4 @@ async function translateName() {
|
|||||||
</script>
|
</script>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
|
|
||||||
<?php include 'includes/footer.php'; ?>
|
<?php include 'includes/footer.php'; ?>
|
||||||
@ -94,7 +94,7 @@ include 'includes/header.php';
|
|||||||
?>
|
?>
|
||||||
|
|
||||||
<div class="mb-4">
|
<div class="mb-4">
|
||||||
<h2 class="fw-bold">My Profile</h2>
|
<h2 class="fw-bold"><?= t('my_profile') ?></h2>
|
||||||
<p class="text-muted">Manage your personal information and account settings.</p>
|
<p class="text-muted">Manage your personal information and account settings.</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -107,17 +107,22 @@ include 'includes/header.php';
|
|||||||
<form method="POST" enctype="multipart/form-data">
|
<form method="POST" enctype="multipart/form-data">
|
||||||
<div class="row mb-4">
|
<div class="row mb-4">
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<label class="form-label small fw-bold text-muted">FULL NAME (ENGLISH)</label>
|
<label class="form-label small fw-bold text-muted d-flex justify-content-between">
|
||||||
<input type="text" name="full_name" id="full_name" class="form-control" value="<?= htmlspecialchars($user['full_name'] ?? '') ?>" required>
|
<span><?= t('name') ?> (EN) <span class="text-danger">*</span></span>
|
||||||
|
<a href="javascript:void(0)" onclick="translateTo('English')" class="text-decoration-none small text-primary fw-bold" id="translateBtnEn">
|
||||||
|
<i class="bi bi-translate me-1"></i> Auto-translate
|
||||||
|
</a>
|
||||||
|
</label>
|
||||||
|
<input type="text" name="full_name" id="full_name" class="form-control rounded-3" value="<?= htmlspecialchars($user['full_name'] ?? '') ?>" required>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<label class="form-label small fw-bold text-muted">FULL NAME (ARABIC)</label>
|
<label class="form-label small fw-bold text-muted d-flex justify-content-between">
|
||||||
<div class="input-group">
|
<span><?= t('arabic_name') ?></span>
|
||||||
<input type="text" name="full_name_ar" id="full_name_ar" class="form-control" value="<?= htmlspecialchars($user['full_name_ar'] ?? '') ?>" dir="rtl">
|
<a href="javascript:void(0)" onclick="translateTo('Arabic')" class="text-decoration-none small text-primary fw-bold" id="translateBtnAr">
|
||||||
<button type="button" class="btn btn-outline-secondary" onclick="translateName(event)">
|
<i class="bi bi-translate me-1"></i> Auto-translate
|
||||||
<i class="bi bi-translate text-primary"></i>
|
</a>
|
||||||
</button>
|
</label>
|
||||||
</div>
|
<input type="text" name="full_name_ar" id="full_name_ar" class="form-control rounded-3 text-end" value="<?= htmlspecialchars($user['full_name_ar'] ?? '') ?>" dir="rtl">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -127,7 +132,7 @@ include 'includes/header.php';
|
|||||||
<input type="text" class="form-control bg-light" value="<?= htmlspecialchars($user['username'] ?? '') ?>" readonly>
|
<input type="text" class="form-control bg-light" value="<?= htmlspecialchars($user['username'] ?? '') ?>" readonly>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<label class="form-label small fw-bold text-muted">EMAIL</label>
|
<label class="form-label small fw-bold text-muted"><?= t('email') ?></label>
|
||||||
<input type="email" name="email" class="form-control" value="<?= htmlspecialchars($user['email'] ?? '') ?>" required>
|
<input type="email" name="email" class="form-control" value="<?= htmlspecialchars($user['email'] ?? '') ?>" required>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -170,7 +175,7 @@ include 'includes/header.php';
|
|||||||
<hr class="my-4">
|
<hr class="my-4">
|
||||||
|
|
||||||
<div class="d-flex justify-content-end gap-2">
|
<div class="d-flex justify-content-end gap-2">
|
||||||
<button type="submit" class="btn btn-primary rounded-pill px-5 fw-bold">Save Changes</button>
|
<button type="submit" class="btn btn-primary rounded-pill px-5 fw-bold"><?= t('save') ?></button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
@ -216,34 +221,38 @@ include 'includes/header.php';
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
function translateName(event) {
|
async function translateTo(targetLang) {
|
||||||
const fullName = document.getElementById('full_name').value;
|
const sourceId = targetLang === 'Arabic' ? 'full_name' : 'full_name_ar';
|
||||||
if (!fullName) return;
|
const targetId = targetLang === 'Arabic' ? 'full_name_ar' : 'full_name';
|
||||||
|
const btnId = targetLang === 'Arabic' ? 'translateBtnAr' : 'translateBtnEn';
|
||||||
|
|
||||||
const btn = event.currentTarget;
|
const sourceText = document.getElementById(sourceId).value;
|
||||||
const icon = btn.querySelector('i');
|
if (!sourceText) {
|
||||||
icon.className = 'spinner-border spinner-border-sm text-primary';
|
alert('Please enter text to translate first.');
|
||||||
btn.disabled = true;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
fetch('../api/translate.php', {
|
const btn = document.getElementById(btnId);
|
||||||
method: 'POST',
|
// Note: since the buttons are different elements here, we might need a better way to find them or just use alert
|
||||||
headers: { 'Content-Type': 'application/json' },
|
// Actually I'll just use the target lang to identify
|
||||||
body: JSON.stringify({
|
|
||||||
text: fullName,
|
try {
|
||||||
target_lang: 'Arabic'
|
const response = await fetch('../api/translate.php', {
|
||||||
})
|
method: 'POST',
|
||||||
})
|
headers: { 'Content-Type': 'application/json' },
|
||||||
.then(response => response.json())
|
body: JSON.stringify({ text: sourceText, target_lang: targetLang })
|
||||||
.then(data => {
|
});
|
||||||
|
const data = await response.json();
|
||||||
if (data.success) {
|
if (data.success) {
|
||||||
document.getElementById('full_name_ar').value = data.translated_text;
|
document.getElementById(targetId).value = data.translated_text;
|
||||||
|
} else {
|
||||||
|
alert('Translation error: ' + data.error);
|
||||||
}
|
}
|
||||||
})
|
} catch (error) {
|
||||||
.finally(() => {
|
console.error('Translation error:', error);
|
||||||
icon.className = 'bi bi-translate text-primary';
|
alert('An error occurred during translation.');
|
||||||
btn.disabled = false;
|
}
|
||||||
});
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<?php include 'includes/footer.php'; ?>
|
<?php include 'includes/footer.php'; ?>
|
||||||
|
|||||||
@ -23,7 +23,7 @@ try {
|
|||||||
: 'dine-in';
|
: 'dine-in';
|
||||||
|
|
||||||
// Get outlet_id from input, default to 1 if missing
|
// Get outlet_id from input, default to 1 if missing
|
||||||
$outlet_id = isset($data['outlet_id']) ? intval($data['outlet_id']) : 1;
|
$outlet_id = !empty($data['outlet_id']) ? intval($data['outlet_id']) : 1;
|
||||||
|
|
||||||
$table_id = null;
|
$table_id = null;
|
||||||
$table_number = null;
|
$table_number = null;
|
||||||
@ -66,7 +66,7 @@ try {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Customer Handling
|
// Customer Handling
|
||||||
$customer_id = $data['customer_id'] ?? null;
|
$customer_id = !empty($data['customer_id']) ? intval($data['customer_id']) : null;
|
||||||
$customer_name = $data['customer_name'] ?? null;
|
$customer_name = $data['customer_name'] ?? null;
|
||||||
$customer_phone = $data['customer_phone'] ?? null;
|
$customer_phone = $data['customer_phone'] ?? null;
|
||||||
|
|
||||||
@ -137,7 +137,7 @@ try {
|
|||||||
// User/Payment info
|
// User/Payment info
|
||||||
$user = get_logged_user();
|
$user = get_logged_user();
|
||||||
$user_id = $user ? $user['id'] : null;
|
$user_id = $user ? $user['id'] : null;
|
||||||
$payment_type_id = isset($data['payment_type_id']) ? intval($data['payment_type_id']) : null;
|
$payment_type_id = !empty($data['payment_type_id']) ? intval($data['payment_type_id']) : null;
|
||||||
|
|
||||||
// VAT vs Discount: We repurpose the 'discount' column in the database to store VAT value.
|
// VAT vs Discount: We repurpose the 'discount' column in the database to store VAT value.
|
||||||
// If it's a positive value, it's VAT. If negative, it acts as a discount (loyalty).
|
// If it's a positive value, it's VAT. If negative, it acts as a discount (loyalty).
|
||||||
|
|||||||
@ -89,6 +89,9 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
let currentCategory = 'all';
|
let currentCategory = 'all';
|
||||||
let currentSearchQuery = '';
|
let currentSearchQuery = '';
|
||||||
|
|
||||||
|
// Translation helper check
|
||||||
|
const _t = (key) => (typeof t === 'function') ? t(key) : key;
|
||||||
|
|
||||||
function formatCurrency(amount) {
|
function formatCurrency(amount) {
|
||||||
const symbol = settings.currency_symbol || '$';
|
const symbol = settings.currency_symbol || '$';
|
||||||
const decimals = parseInt(settings.currency_decimals || 2);
|
const decimals = parseInt(settings.currency_decimals || 2);
|
||||||
@ -100,8 +103,9 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
items.forEach(item => {
|
items.forEach(item => {
|
||||||
const matchesCategory = (currentCategory == 'all' || item.dataset.category == currentCategory);
|
const matchesCategory = (currentCategory == 'all' || item.dataset.category == currentCategory);
|
||||||
const name = (item.dataset.name || '').toLowerCase();
|
const name = (item.dataset.name || '').toLowerCase();
|
||||||
|
const name_ar = (item.dataset.nameAr || '').toLowerCase();
|
||||||
const sku = (item.dataset.sku || '').toLowerCase();
|
const sku = (item.dataset.sku || '').toLowerCase();
|
||||||
const matchesSearch = name.includes(currentSearchQuery) || sku.includes(currentSearchQuery);
|
const matchesSearch = name.includes(currentSearchQuery) || name_ar.includes(currentSearchQuery) || sku.includes(currentSearchQuery);
|
||||||
|
|
||||||
item.style.display = (matchesCategory && matchesSearch) ? 'block' : 'none';
|
item.style.display = (matchesCategory && matchesSearch) ? 'block' : 'none';
|
||||||
});
|
});
|
||||||
@ -165,11 +169,11 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
recallList.appendChild(item);
|
recallList.appendChild(item);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
recallList.innerHTML = '<div class="p-4 text-center text-muted">No unpaid bills found.</div>';
|
recallList.innerHTML = `<div class="p-4 text-center text-muted">${_t('none')}</div>`;
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
recallList.innerHTML = '<div class="alert alert-danger">Error fetching orders.</div>';
|
recallList.innerHTML = `<div class="alert alert-danger">${_t('error')}</div>`;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -196,7 +200,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
if (recallModal) recallModal.hide();
|
if (recallModal) recallModal.hide();
|
||||||
showToast(`Order #${orderId} loaded!`, 'success');
|
showToast(`Order #${orderId} loaded!`, 'success');
|
||||||
} else {
|
} else {
|
||||||
showToast(data.error || 'Failed to load order', 'danger');
|
showToast(data.error || _t('error'), 'danger');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -230,7 +234,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
});
|
});
|
||||||
customerResults.style.display = 'block';
|
customerResults.style.display = 'block';
|
||||||
} else {
|
} else {
|
||||||
customerResults.innerHTML = '<div class="list-group-item text-muted">No results found</div>';
|
customerResults.innerHTML = `<div class="list-group-item text-muted">${_t('none')}</div>`;
|
||||||
customerResults.style.display = 'block';
|
customerResults.style.display = 'block';
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -316,14 +320,15 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
if (!variantSelectionModal) return;
|
if (!variantSelectionModal) return;
|
||||||
const list = document.getElementById('variant-list');
|
const list = document.getElementById('variant-list');
|
||||||
const title = document.getElementById('variantModalTitle');
|
const title = document.getElementById('variantModalTitle');
|
||||||
if (title) title.textContent = `Option: ${product.name}`;
|
if (title) title.textContent = `${_t('variant')}: ${LANG === 'ar' && product.name_ar ? product.name_ar : product.name}`;
|
||||||
if (!list) return;
|
if (!list) return;
|
||||||
list.innerHTML = '';
|
list.innerHTML = '';
|
||||||
variants.forEach(v => {
|
variants.forEach(v => {
|
||||||
const btn = document.createElement('button');
|
const btn = document.createElement('button');
|
||||||
btn.className = 'list-group-item list-group-item-action d-flex justify-content-between align-items-center';
|
btn.className = 'list-group-item list-group-item-action d-flex justify-content-between align-items-center';
|
||||||
const finalPrice = parseFloat(product.price) + parseFloat(v.price_adjustment);
|
const finalPrice = parseFloat(product.price) + parseFloat(v.price_adjustment);
|
||||||
btn.innerHTML = `<span>${v.name}</span><span class="fw-bold">${formatCurrency(finalPrice)}</span>`;
|
const vName = (LANG === 'ar' && v.name_ar) ? v.name_ar : v.name;
|
||||||
|
btn.innerHTML = `<span>${vName}</span><span class="fw-bold">${formatCurrency(finalPrice)}</span>`;
|
||||||
btn.onclick = () => {
|
btn.onclick = () => {
|
||||||
addToCart({
|
addToCart({
|
||||||
id: product.id, name: product.name, name_ar: product.name_ar || "",
|
id: product.id, name: product.name, name_ar: product.name_ar || "",
|
||||||
@ -369,11 +374,11 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
function updateCart() {
|
function updateCart() {
|
||||||
if (!cartItemsContainer) return;
|
if (!cartItemsContainer) return;
|
||||||
if (cart.length === 0) {
|
if (cart.length === 0) {
|
||||||
cartItemsContainer.innerHTML = '<div class="text-center text-muted mt-5"><i class="bi bi-basket3 fs-1 text-light"></i><p class="mt-2">Cart is empty</p></div>';
|
cartItemsContainer.innerHTML = `<div class="text-center text-muted mt-5"><i class="bi bi-basket3 fs-1 text-light"></i><p class="mt-2">${_t('cart_empty')}</p></div>`;
|
||||||
if (cartSubtotal) cartSubtotal.innerText = formatCurrency(0);
|
if (cartSubtotal) cartSubtotal.innerText = formatCurrency(0);
|
||||||
if (cartTotalPrice) cartTotalPrice.innerText = formatCurrency(0);
|
if (cartTotalPrice) cartTotalPrice.innerText = formatCurrency(0);
|
||||||
if (quickOrderBtn) quickOrderBtn.disabled = true;
|
if (quickOrderBtn) { quickOrderBtn.disabled = true; quickOrderBtn.innerText = _t('quick_pay'); }
|
||||||
if (placeOrderBtn) placeOrderBtn.disabled = true;
|
if (placeOrderBtn) { placeOrderBtn.disabled = true; placeOrderBtn.innerText = _t('save_bill'); }
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -384,10 +389,13 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
subtotal += itemTotal;
|
subtotal += itemTotal;
|
||||||
const row = document.createElement('div');
|
const row = document.createElement('div');
|
||||||
row.className = 'd-flex justify-content-between align-items-center mb-3 border-bottom pb-2';
|
row.className = 'd-flex justify-content-between align-items-center mb-3 border-bottom pb-2';
|
||||||
|
const itemName = (LANG === 'ar' && item.name_ar) ? item.name_ar : item.name;
|
||||||
|
const otherName = (LANG === 'ar') ? item.name : item.name_ar;
|
||||||
|
|
||||||
row.innerHTML = `
|
row.innerHTML = `
|
||||||
<div class="flex-grow-1 me-2">
|
<div class="flex-grow-1 me-2">
|
||||||
<div class="fw-bold text-truncate" style="max-width: 140px;">${item.name}</div>
|
<div class="fw-bold text-truncate" style="max-width: 140px;">${itemName}</div>
|
||||||
${item.name_ar ? `<div class="text-primary small" dir="rtl" style="font-size: 0.75rem;">${item.name_ar}</div>` : ''}
|
${otherName ? `<div class="text-muted small" style="font-size: 0.75rem;">${otherName}</div>` : ''}
|
||||||
<div class="small text-muted">${formatCurrency(item.price)}</div>
|
<div class="small text-muted">${formatCurrency(item.price)}</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="d-flex align-items-center bg-light rounded px-1">
|
<div class="d-flex align-items-center bg-light rounded px-1">
|
||||||
@ -397,7 +405,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
</div>
|
</div>
|
||||||
<div class="text-end ms-3" style="min-width: 60px;">
|
<div class="text-end ms-3" style="min-width: 60px;">
|
||||||
<div class="fw-bold">${formatCurrency(itemTotal)}</div>
|
<div class="fw-bold">${formatCurrency(itemTotal)}</div>
|
||||||
<button class="btn btn-sm text-danger p-0 mt-1" style="font-size: 0.8rem;" onclick="removeFromCart(${index})">Remove</button>
|
<button class="btn btn-sm text-danger p-0 mt-1" style="font-size: 0.8rem;" onclick="removeFromCart(${index})">${_t('remove')}</button>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
cartItemsContainer.appendChild(row);
|
cartItemsContainer.appendChild(row);
|
||||||
@ -409,8 +417,8 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
if (cartVatInput) cartVatInput.value = vat.toFixed(2);
|
if (cartVatInput) cartVatInput.value = vat.toFixed(2);
|
||||||
const total = subtotal + vat;
|
const total = subtotal + vat;
|
||||||
if (cartTotalPrice) cartTotalPrice.innerText = formatCurrency(total);
|
if (cartTotalPrice) cartTotalPrice.innerText = formatCurrency(total);
|
||||||
if (quickOrderBtn) quickOrderBtn.disabled = false;
|
if (quickOrderBtn) { quickOrderBtn.disabled = false; quickOrderBtn.innerText = _t('quick_pay'); }
|
||||||
if (placeOrderBtn) placeOrderBtn.disabled = false;
|
if (placeOrderBtn) { placeOrderBtn.disabled = false; placeOrderBtn.innerText = _t('save_bill'); }
|
||||||
}
|
}
|
||||||
|
|
||||||
if (quickOrderBtn) {
|
if (quickOrderBtn) {
|
||||||
@ -463,7 +471,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
.then(res => res.json())
|
.then(res => res.json())
|
||||||
.then(data => {
|
.then(data => {
|
||||||
if (data.success) {
|
if (data.success) {
|
||||||
showToast(`Order #${data.order_id} placed!`, 'success');
|
showToast(`${_t('order_placed')} #${data.order_id}`, 'success');
|
||||||
clearCart();
|
clearCart();
|
||||||
if (paymentSelectionModal) paymentSelectionModal.hide();
|
if (paymentSelectionModal) paymentSelectionModal.hide();
|
||||||
if (clearCustomerBtn) clearCustomerBtn.click();
|
if (clearCustomerBtn) clearCustomerBtn.click();
|
||||||
|
|||||||
BIN
assets/pasted-20260224-165424-865370bd.png
Normal file
BIN
assets/pasted-20260224-165424-865370bd.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 14 KiB |
202
includes/lang.php
Normal file
202
includes/lang.php
Normal file
@ -0,0 +1,202 @@
|
|||||||
|
<?php
|
||||||
|
// Simple translation helper
|
||||||
|
function t($key, $lang = null) {
|
||||||
|
if (!$lang) {
|
||||||
|
$lang = $_SESSION['lang'] ?? 'en';
|
||||||
|
}
|
||||||
|
|
||||||
|
$translations = [
|
||||||
|
'en' => [
|
||||||
|
'dashboard' => 'Dashboard',
|
||||||
|
'pos_operations' => 'POS & Operations',
|
||||||
|
'pos_terminal' => 'POS Terminal',
|
||||||
|
'orders_pos' => 'Orders (POS)',
|
||||||
|
'kitchen_view' => 'Kitchen View',
|
||||||
|
'ads_management' => 'Ads Management',
|
||||||
|
'menu_management' => 'Menu Management',
|
||||||
|
'products' => 'Products',
|
||||||
|
'categories' => 'Categories',
|
||||||
|
'restaurant_setup' => 'Restaurant Setup',
|
||||||
|
'outlets' => 'Outlets',
|
||||||
|
'areas' => 'Areas',
|
||||||
|
'tables' => 'Tables',
|
||||||
|
'people_partners' => 'People & Partners',
|
||||||
|
'customers' => 'Customers',
|
||||||
|
'suppliers' => 'Suppliers',
|
||||||
|
'loyalty' => 'Loyalty',
|
||||||
|
'financials' => 'Financials',
|
||||||
|
'purchases' => 'Purchases',
|
||||||
|
'expenses' => 'Expenses',
|
||||||
|
'expense_categories' => 'Expense Categories',
|
||||||
|
'reports_analytics' => 'Reports & Analytics',
|
||||||
|
'daily_reports' => 'Daily Reports',
|
||||||
|
'user_management' => 'User Management',
|
||||||
|
'users' => 'Users',
|
||||||
|
'roles_groups' => 'Roles / Groups',
|
||||||
|
'attendance' => 'Attendance',
|
||||||
|
'staff_ratings' => 'Staff Ratings',
|
||||||
|
'settings' => 'Settings',
|
||||||
|
'payment_types' => 'Payment Types',
|
||||||
|
'integrations' => 'Integrations',
|
||||||
|
'company' => 'Company',
|
||||||
|
'backup_restore' => 'Backup & Restore',
|
||||||
|
'view_site' => 'View Site',
|
||||||
|
'theme' => 'Theme',
|
||||||
|
'language' => 'Language',
|
||||||
|
'logout' => 'Logout',
|
||||||
|
'my_profile' => 'My Profile',
|
||||||
|
'company_settings' => 'Company Settings',
|
||||||
|
'signed_in_as' => 'Signed in as',
|
||||||
|
'welcome_back' => 'Welcome back',
|
||||||
|
'select_theme' => 'Select Theme',
|
||||||
|
'select_language' => 'Select Language',
|
||||||
|
'default' => 'Default',
|
||||||
|
'dark' => 'Dark',
|
||||||
|
'ocean' => 'Ocean',
|
||||||
|
'forest' => 'Forest',
|
||||||
|
'grape' => 'Grape',
|
||||||
|
'english' => 'English',
|
||||||
|
'arabic' => 'Arabic',
|
||||||
|
'search' => 'Search',
|
||||||
|
'filter' => 'Filter',
|
||||||
|
'add' => 'Add',
|
||||||
|
'edit' => 'Edit',
|
||||||
|
'delete' => 'Delete',
|
||||||
|
'save' => 'Save',
|
||||||
|
'cancel' => 'Cancel',
|
||||||
|
'close' => 'Close',
|
||||||
|
'actions' => 'Actions',
|
||||||
|
'name' => 'Name',
|
||||||
|
'arabic_name' => 'Arabic Name',
|
||||||
|
'description' => 'Description',
|
||||||
|
'status' => 'Status',
|
||||||
|
'active' => 'Active',
|
||||||
|
'inactive' => 'Inactive',
|
||||||
|
'all' => 'All',
|
||||||
|
'none' => 'None',
|
||||||
|
'price' => 'Price',
|
||||||
|
'quantity' => 'Quantity',
|
||||||
|
'total' => 'Total',
|
||||||
|
'date' => 'Date',
|
||||||
|
'customer' => 'Customer',
|
||||||
|
'phone' => 'Phone',
|
||||||
|
'email' => 'Email',
|
||||||
|
'address' => 'Address',
|
||||||
|
'points' => 'Points',
|
||||||
|
'stock' => 'Stock',
|
||||||
|
'category' => 'Category',
|
||||||
|
'variant' => 'Variant',
|
||||||
|
'table' => 'Table',
|
||||||
|
'outlet' => 'Outlet',
|
||||||
|
'order_no' => 'Order No',
|
||||||
|
'payment' => 'Payment',
|
||||||
|
'type' => 'Type',
|
||||||
|
'commission' => 'Commission',
|
||||||
|
'preparing' => 'Preparing',
|
||||||
|
'ready' => 'Ready',
|
||||||
|
'completed' => 'Completed',
|
||||||
|
'cancelled' => 'Cancelled',
|
||||||
|
'takeaway' => 'Takeaway',
|
||||||
|
'dine_in' => 'Dine-In',
|
||||||
|
'delivery' => 'Delivery',
|
||||||
|
'auto_translate' => 'Auto-translate',
|
||||||
|
],
|
||||||
|
'ar' => [
|
||||||
|
'dashboard' => 'لوحة القيادة',
|
||||||
|
'pos_operations' => 'نقطة البيع والعمليات',
|
||||||
|
'pos_terminal' => 'جهاز نقطة البيع',
|
||||||
|
'orders_pos' => 'الطلبات (نقطة البيع)',
|
||||||
|
'kitchen_view' => 'عرض المطبخ',
|
||||||
|
'ads_management' => 'إدارة الإعلانات',
|
||||||
|
'menu_management' => 'إدارة القائمة',
|
||||||
|
'products' => 'المنتجات',
|
||||||
|
'categories' => 'الفئات',
|
||||||
|
'restaurant_setup' => 'إعداد المطعم',
|
||||||
|
'outlets' => 'المنافذ',
|
||||||
|
'areas' => 'المناطق',
|
||||||
|
'tables' => 'الطاولات',
|
||||||
|
'people_partners' => 'الأشخاص والشركاء',
|
||||||
|
'customers' => 'العملاء',
|
||||||
|
'suppliers' => 'الموردين',
|
||||||
|
'loyalty' => 'الولاء',
|
||||||
|
'financials' => 'المالية',
|
||||||
|
'purchases' => 'المشتريات',
|
||||||
|
'expenses' => 'المصاريف',
|
||||||
|
'expense_categories' => 'فئات المصاريف',
|
||||||
|
'reports_analytics' => 'التقارير والتحليلات',
|
||||||
|
'daily_reports' => 'التقارير اليومية',
|
||||||
|
'user_management' => 'إدارة المستخدمين',
|
||||||
|
'users' => 'المستخدمين',
|
||||||
|
'roles_groups' => 'الأدوار / المجموعات',
|
||||||
|
'attendance' => 'الحضور',
|
||||||
|
'staff_ratings' => 'تقييمات الموظفين',
|
||||||
|
'settings' => 'الإعدادات',
|
||||||
|
'payment_types' => 'أنواع الدفع',
|
||||||
|
'integrations' => 'التكاملات',
|
||||||
|
'company' => 'الشركة',
|
||||||
|
'backup_restore' => 'النسخ الاحتياطي والاستعادة',
|
||||||
|
'view_site' => 'عرض الموقع',
|
||||||
|
'theme' => 'المظهر',
|
||||||
|
'language' => 'اللغة',
|
||||||
|
'logout' => 'تسجيل الخروج',
|
||||||
|
'my_profile' => 'ملفي الشخصي',
|
||||||
|
'company_settings' => 'إعدادات الشركة',
|
||||||
|
'signed_in_as' => 'تم تسجيل الدخول بصفتك',
|
||||||
|
'welcome_back' => 'مرحباً بعودتك',
|
||||||
|
'select_theme' => 'اختر المظهر',
|
||||||
|
'select_language' => 'اختر اللغة',
|
||||||
|
'default' => 'الافتراضي',
|
||||||
|
'dark' => 'داكن',
|
||||||
|
'ocean' => 'محيط',
|
||||||
|
'forest' => 'غابة',
|
||||||
|
'grape' => 'عنب',
|
||||||
|
'english' => 'الإنجليزية',
|
||||||
|
'arabic' => 'العربية',
|
||||||
|
'search' => 'بحث',
|
||||||
|
'filter' => 'تصفية',
|
||||||
|
'add' => 'إضافة',
|
||||||
|
'edit' => 'تعديل',
|
||||||
|
'delete' => 'حذف',
|
||||||
|
'save' => 'حفظ',
|
||||||
|
'cancel' => 'إلغاء',
|
||||||
|
'close' => 'إغلاق',
|
||||||
|
'actions' => 'إجراءات',
|
||||||
|
'name' => 'الاسم',
|
||||||
|
'arabic_name' => 'الاسم بالعربية',
|
||||||
|
'description' => 'الوصف',
|
||||||
|
'status' => 'الحالة',
|
||||||
|
'active' => 'نشط',
|
||||||
|
'inactive' => 'غير نشط',
|
||||||
|
'all' => 'الكل',
|
||||||
|
'none' => 'لا يوجد',
|
||||||
|
'price' => 'السعر',
|
||||||
|
'quantity' => 'الكمية',
|
||||||
|
'total' => 'الإجمالي',
|
||||||
|
'date' => 'التاريخ',
|
||||||
|
'customer' => 'العميل',
|
||||||
|
'phone' => 'الهاتف',
|
||||||
|
'email' => 'البريد الإلكتروني',
|
||||||
|
'address' => 'العنوان',
|
||||||
|
'points' => 'النقاط',
|
||||||
|
'stock' => 'المخزون',
|
||||||
|
'category' => 'الفئة',
|
||||||
|
'variant' => 'النوع',
|
||||||
|
'table' => 'الطاولة',
|
||||||
|
'outlet' => 'المنفذ',
|
||||||
|
'order_no' => 'رقم الطلب',
|
||||||
|
'payment' => 'الدفع',
|
||||||
|
'type' => 'النوع',
|
||||||
|
'commission' => 'العمولة',
|
||||||
|
'preparing' => 'قيد التحضير',
|
||||||
|
'ready' => 'جاهز',
|
||||||
|
'completed' => 'مكتمل',
|
||||||
|
'cancelled' => 'ملغي',
|
||||||
|
'takeaway' => 'سفري',
|
||||||
|
'dine_in' => 'محلي',
|
||||||
|
'delivery' => 'توصيل',
|
||||||
|
'auto_translate' => 'ترجمة تلقائية',
|
||||||
|
]
|
||||||
|
];
|
||||||
|
|
||||||
|
return $translations[$lang][$key] ?? $translations['en'][$key] ?? $key;
|
||||||
|
}
|
||||||
151
pos.php
151
pos.php
@ -2,6 +2,30 @@
|
|||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
require_once __DIR__ . '/db/config.php';
|
require_once __DIR__ . '/db/config.php';
|
||||||
require_once __DIR__ . '/includes/functions.php';
|
require_once __DIR__ . '/includes/functions.php';
|
||||||
|
require_once __DIR__ . '/includes/lang.php';
|
||||||
|
|
||||||
|
if (session_status() === PHP_SESSION_NONE) {
|
||||||
|
session_start();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle language switching
|
||||||
|
if (isset($_GET['lang'])) {
|
||||||
|
$allowed_langs = ['en', 'ar'];
|
||||||
|
if (in_array($_GET['lang'], $allowed_langs)) {
|
||||||
|
$_SESSION['lang'] = $_GET['lang'];
|
||||||
|
}
|
||||||
|
$current_url = strtok($_SERVER["REQUEST_URI"], '?');
|
||||||
|
$query = $_GET;
|
||||||
|
unset($query['lang']);
|
||||||
|
if (count($query) > 0) {
|
||||||
|
$current_url .= '?' . http_build_query($query);
|
||||||
|
}
|
||||||
|
header("Location: $current_url");
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
$currentLang = $_SESSION['lang'] ?? 'en';
|
||||||
|
$isRTL = ($currentLang === 'ar');
|
||||||
|
|
||||||
require_permission('pos_view');
|
require_permission('pos_view');
|
||||||
|
|
||||||
@ -39,7 +63,7 @@ if (!has_permission('all')) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
$categories = $pdo->query("SELECT * FROM categories ORDER BY sort_order")->fetchAll();
|
$categories = $pdo->query("SELECT * FROM categories ORDER BY sort_order")->fetchAll();
|
||||||
$all_products = $pdo->query("SELECT p.*, c.name as category_name FROM products p JOIN categories c ON p.category_id = c.id")->fetchAll();
|
$all_products = $pdo->query("SELECT p.*, c.name as category_name, c.name_ar as category_name_ar FROM products p JOIN categories c ON p.category_id = c.id")->fetchAll();
|
||||||
$payment_types = $pdo->query("SELECT * FROM payment_types WHERE is_active = 1 ORDER BY id")->fetchAll();
|
$payment_types = $pdo->query("SELECT * FROM payment_types WHERE is_active = 1 ORDER BY id")->fetchAll();
|
||||||
|
|
||||||
// Fetch variants
|
// Fetch variants
|
||||||
@ -56,7 +80,7 @@ $order_type = $_GET['order_type'] ?? 'takeaway';
|
|||||||
$current_outlet_name = 'Unknown Outlet';
|
$current_outlet_name = 'Unknown Outlet';
|
||||||
foreach ($outlets as $o) {
|
foreach ($outlets as $o) {
|
||||||
if ($o['id'] == $outlet_id) {
|
if ($o['id'] == $outlet_id) {
|
||||||
$current_outlet_name = $o['name'];
|
$current_outlet_name = ($isRTL && !empty($o['name_ar'])) ? $o['name_ar'] : $o['name'];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -69,7 +93,7 @@ if (!$loyalty_settings) {
|
|||||||
}
|
}
|
||||||
?>
|
?>
|
||||||
<!doctype html>
|
<!doctype html>
|
||||||
<html lang="en">
|
<html lang="<?= $currentLang ?>" dir="<?= $isRTL ? 'rtl' : 'ltr' ?>">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
@ -88,15 +112,15 @@ if (!$loyalty_settings) {
|
|||||||
body { height: 100vh; overflow: hidden; font-family: 'Inter', 'Noto Sans Arabic', sans-serif; background: #f4f7f6; }
|
body { height: 100vh; overflow: hidden; font-family: 'Inter', 'Noto Sans Arabic', sans-serif; background: #f4f7f6; }
|
||||||
.scrollable-y { overflow-y: auto; height: 100%; scrollbar-width: thin; }
|
.scrollable-y { overflow-y: auto; height: 100%; scrollbar-width: thin; }
|
||||||
.pos-layout { height: calc(100vh - 60px); }
|
.pos-layout { height: calc(100vh - 60px); }
|
||||||
.pos-categories { background: #fff; height: 100%; border-right: 1px solid #e0e0e0; }
|
.pos-categories { background: #fff; height: 100%; border-<?= $isRTL ? 'left' : 'right' ?>: 1px solid #e0e0e0; }
|
||||||
.pos-products { background: #f8fafc; height: 100%; display: flex; flex-direction: column; }
|
.pos-products { background: #f8fafc; height: 100%; display: flex; flex-direction: column; }
|
||||||
.pos-cart { background: #fff; height: 100%; border-left: 1px solid #e0e0e0; display: flex; flex-direction: column; }
|
.pos-cart { background: #fff; height: 100%; border-<?= $isRTL ? 'right' : 'left' ?>: 1px solid #e0e0e0; display: flex; flex-direction: column; }
|
||||||
|
|
||||||
.product-card { transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1); cursor: pointer; border: 1px solid transparent !important; background: #fff; }
|
.product-card { transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1); cursor: pointer; border: 1px solid transparent !important; background: #fff; }
|
||||||
.product-card:active { transform: scale(0.95); }
|
.product-card:active { transform: scale(0.95); }
|
||||||
.product-card:hover { border-color: #0d6efd !important; box-shadow: 0 4px 12px rgba(0,0,0,0.08) !important; }
|
.product-card:hover { border-color: #0d6efd !important; box-shadow: 0 4px 12px rgba(0,0,0,0.08) !important; }
|
||||||
|
|
||||||
.category-btn { text-align: left; border: none; background: none; padding: 10px 12px; width: 100%; display: flex; align-items: center; gap: 10px; border-radius: 12px; color: #64748b; font-weight: 700; transition: all 0.2s; }
|
.category-btn { text-align: <?= $isRTL ? 'right' : 'left' ?>; border: none; background: none; padding: 10px 12px; width: 100%; display: flex; align-items: center; gap: 10px; border-radius: 12px; color: #64748b; font-weight: 700; transition: all 0.2s; }
|
||||||
.category-btn:hover { background-color: #f1f5f9; color: #0f172a; }
|
.category-btn:hover { background-color: #f1f5f9; color: #0f172a; }
|
||||||
.category-btn.active { background-color: #0d6efd; color: white; box-shadow: 0 4px 6px -1px rgba(13, 110, 253, 0.3); }
|
.category-btn.active { background-color: #0d6efd; color: white; box-shadow: 0 4px 6px -1px rgba(13, 110, 253, 0.3); }
|
||||||
.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; }
|
||||||
@ -104,17 +128,13 @@ if (!$loyalty_settings) {
|
|||||||
/* Compact Card adjustments */
|
/* Compact Card adjustments */
|
||||||
.card-img-container { height: 75px; position: relative; background: #f1f5f9; }
|
.card-img-container { height: 75px; position: relative; background: #f1f5f9; }
|
||||||
.card-img-container img { height: 100%; width: 100%; object-fit: cover; transition: transform 0.3s; }
|
.card-img-container img { height: 100%; width: 100%; object-fit: cover; transition: transform 0.3s; }
|
||||||
.product-card:hover .card-img-container img { transform: scale(1.05); }
|
|
||||||
.product-title { font-size: 0.75rem; line-height: 1.2; height: 1.8rem; overflow: hidden; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; font-weight: 700; color: #1e293b; }
|
.product-title { font-size: 0.75rem; line-height: 1.2; height: 1.8rem; overflow: hidden; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; font-weight: 700; color: #1e293b; }
|
||||||
.product-price-tag { font-size: 0.85rem; color: #0d6efd; font-weight: 700; }
|
.product-price-tag { font-size: 0.85rem; color: #0d6efd; font-weight: 700; }
|
||||||
.product-cat-name { font-size: 0.65rem; color: #94a3b8; }
|
.product-cat-name { font-size: 0.65rem; color: #94a3b8; }
|
||||||
|
|
||||||
/* Custom Grid for 8 columns */
|
/* Custom Grid for 7 columns */
|
||||||
@media (min-width: 1200px) {
|
@media (min-width: 1200px) {
|
||||||
.row-cols-xl-8 > * { flex: 0 0 auto; width: 12.5%; }
|
.row-cols-xl-7 > *, .row-cols-xxl-7 > * { flex: 0 0 auto; width: 14.285714%; }
|
||||||
}
|
|
||||||
@media (min-width: 1400px) {
|
|
||||||
.row-cols-xxl-10 > * { flex: 0 0 auto; width: 10%; }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 576px) {
|
@media (max-width: 576px) {
|
||||||
@ -132,6 +152,7 @@ if (!$loyalty_settings) {
|
|||||||
body { overflow: visible !important; height: auto !important; }
|
body { overflow: visible !important; height: auto !important; }
|
||||||
}
|
}
|
||||||
.print-only { display: none; }
|
.print-only { display: none; }
|
||||||
|
.dropdown-menu { <?= $isRTL ? 'text-align: right;' : '' ?> }
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
@ -150,21 +171,32 @@ if (!$loyalty_settings) {
|
|||||||
</a>
|
</a>
|
||||||
|
|
||||||
<div class="ms-auto d-flex align-items-center gap-2">
|
<div class="ms-auto d-flex align-items-center gap-2">
|
||||||
|
<!-- Language Switcher -->
|
||||||
|
<div class="dropdown me-1">
|
||||||
|
<button class="btn btn-outline-secondary btn-sm rounded-pill px-3 border-0 bg-light" type="button" data-bs-toggle="dropdown">
|
||||||
|
<i class="bi bi-translate me-1"></i> <span class="d-none d-sm-inline"><?= $isRTL ? 'العربية' : 'English' ?></span>
|
||||||
|
</button>
|
||||||
|
<ul class="dropdown-menu dropdown-menu-end shadow border-0 mt-2">
|
||||||
|
<li><a class="dropdown-item" href="?lang=en">English</a></li>
|
||||||
|
<li><a class="dropdown-item" href="?lang=ar">العربية</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
<?php if (count($outlets) > 1): ?>
|
<?php if (count($outlets) > 1): ?>
|
||||||
<div class="dropdown me-1 d-none d-md-block">
|
<div class="dropdown me-1 d-none d-md-block">
|
||||||
<button class="btn btn-outline-secondary btn-sm rounded-pill px-3 border-0 bg-light" type="button" data-bs-toggle="dropdown">
|
<button class="btn btn-outline-secondary btn-sm rounded-pill px-3 border-0 bg-light" type="button" data-bs-toggle="dropdown">
|
||||||
<i class="bi bi-shop me-1"></i> Switch
|
<i class="bi bi-shop me-1"></i> <?= t('switch') ?>
|
||||||
</button>
|
</button>
|
||||||
<ul class="dropdown-menu dropdown-menu-end shadow border-0 mt-2">
|
<ul class="dropdown-menu dropdown-menu-end shadow border-0 mt-2">
|
||||||
<?php foreach ($outlets as $o): ?>
|
<?php foreach ($outlets as $o): ?>
|
||||||
<li><a class="dropdown-item <?= $o['id'] == $outlet_id ? 'active' : '' ?>" href="?outlet_id=<?= $o['id'] ?>&order_type=<?= $order_type ?>"><?= htmlspecialchars($o['name']) ?></a></li>
|
<li><a class="dropdown-item <?= $o['id'] == $outlet_id ? 'active' : '' ?>" href="?outlet_id=<?= $o['id'] ?>&order_type=<?= $order_type ?>"><?= htmlspecialchars(($isRTL && !empty($o['name_ar'])) ? $o['name_ar'] : $o['name']) ?></a></li>
|
||||||
<?php endforeach; ?>
|
<?php endforeach; ?>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
<a href="kitchen.php" class="btn btn-outline-primary btn-sm rounded-pill px-2 px-sm-3 border-0"><i class="bi bi-fire me-1"></i> Kitchen</a>
|
<a href="kitchen.php" class="btn btn-outline-primary btn-sm rounded-pill px-2 px-sm-3 border-0"><i class="bi bi-fire me-1"></i> <?= t('kitchen_view') ?></a>
|
||||||
<a href="admin/orders.php" class="btn btn-outline-secondary btn-sm rounded-pill px-2 px-sm-3 border-0"><i class="bi bi-receipt me-1"></i> Orders</a>
|
<a href="admin/orders.php" class="btn btn-outline-secondary btn-sm rounded-pill px-2 px-sm-3 border-0"><i class="bi bi-receipt me-1"></i> <?= t('orders_pos') ?></a>
|
||||||
<button class="btn btn-outline-warning btn-sm rounded-pill px-2 px-sm-3 border-0" onclick="openRecallOrderModal()"><i class="bi bi-arrow-counterclockwise me-1"></i> Recall</button>
|
<button class="btn btn-outline-warning btn-sm rounded-pill px-2 px-sm-3 border-0" onclick="openRecallOrderModal()"><i class="bi bi-arrow-counterclockwise me-1"></i> <?= t('recall') ?></button>
|
||||||
|
|
||||||
<div class="vr mx-1 h-25 d-none d-sm-block"></div>
|
<div class="vr mx-1 h-25 d-none d-sm-block"></div>
|
||||||
|
|
||||||
@ -175,12 +207,12 @@ if (!$loyalty_settings) {
|
|||||||
<ul class="dropdown-menu dropdown-menu-end shadow border-0 mt-2">
|
<ul class="dropdown-menu dropdown-menu-end shadow border-0 mt-2">
|
||||||
<li class="px-3 py-2 border-bottom">
|
<li class="px-3 py-2 border-bottom">
|
||||||
<div class="fw-bold small"><?= htmlspecialchars($currentUser['username']) ?></div>
|
<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>
|
<div class="text-muted" style="font-size: 0.7rem;"><?= t('signed_in_as') ?> <?= htmlspecialchars($currentUser['group_name'] ?? 'User') ?></div>
|
||||||
</li>
|
</li>
|
||||||
<?php if (has_permission('dashboard_view')): ?>
|
<?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>
|
<li><a class="dropdown-item py-2" href="admin/index.php"><i class="bi bi-speedometer2 me-2"></i> <?= t('dashboard') ?></a></li>
|
||||||
<?php endif; ?>
|
<?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>
|
<li><a class="dropdown-item py-2 text-danger" href="logout.php"><i class="bi bi-box-arrow-right me-2"></i> <?= t('logout') ?></a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -192,7 +224,7 @@ if (!$loyalty_settings) {
|
|||||||
<div class="col-md-2 col-auto pos-categories scrollable-y p-2" style="max-width: 170px;">
|
<div class="col-md-2 col-auto pos-categories scrollable-y p-2" style="max-width: 170px;">
|
||||||
<button class="category-btn active mb-2" data-category="all">
|
<button class="category-btn active mb-2" data-category="all">
|
||||||
<i class="bi bi-grid fs-5 text-inherit"></i>
|
<i class="bi bi-grid fs-5 text-inherit"></i>
|
||||||
<span style="font-size: 0.85rem; font-weight: 700;">All Items</span>
|
<span style="font-size: 0.85rem; font-weight: 700;"><?= t('all') ?></span>
|
||||||
</button>
|
</button>
|
||||||
<?php foreach ($categories as $cat): ?>
|
<?php foreach ($categories as $cat): ?>
|
||||||
<button class="category-btn mb-2" data-category="<?= $cat['id'] ?>">
|
<button class="category-btn mb-2" data-category="<?= $cat['id'] ?>">
|
||||||
@ -201,7 +233,7 @@ if (!$loyalty_settings) {
|
|||||||
<?php else: ?>
|
<?php else: ?>
|
||||||
<i class="bi bi-tag fs-5 text-inherit"></i>
|
<i class="bi bi-tag fs-5 text-inherit"></i>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
<span class="text-truncate" style="font-size: 0.85rem; font-weight: 700;"><?= htmlspecialchars($cat['name']) ?></span>
|
<span class="text-truncate" style="font-size: 0.85rem; font-weight: 700;"><?= htmlspecialchars(($isRTL && !empty($cat['name_ar'])) ? $cat['name_ar'] : $cat['name']) ?></span>
|
||||||
</button>
|
</button>
|
||||||
<?php endforeach; ?>
|
<?php endforeach; ?>
|
||||||
</div>
|
</div>
|
||||||
@ -216,14 +248,14 @@ if (!$loyalty_settings) {
|
|||||||
<span class="position-absolute top-50 start-0 translate-middle-y ms-3 text-muted">
|
<span class="position-absolute top-50 start-0 translate-middle-y ms-3 text-muted">
|
||||||
<i class="bi bi-search small"></i>
|
<i class="bi bi-search small"></i>
|
||||||
</span>
|
</span>
|
||||||
<input type="text" id="product-search" class="form-control form-control-sm ps-5 border-0 bg-light rounded-3" placeholder="Search products by name or SKU...">
|
<input type="text" id="product-search" class="form-control form-control-sm ps-5 border-0 bg-light rounded-3" placeholder="<?= t('search') ?>...">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<?php if (count($outlets) > 1): ?>
|
<?php if (count($outlets) > 1): ?>
|
||||||
<div class="col-auto">
|
<div class="col-auto">
|
||||||
<select class="form-select form-select-sm border-0 bg-light rounded-3 fw-bold text-primary" style="min-width: 120px;" onchange="location.href='?outlet_id=' + this.value + '&order_type=<?= $order_type ?>'">
|
<select class="form-select form-select-sm border-0 bg-light rounded-3 fw-bold text-primary" style="min-width: 120px;" onchange="location.href='?outlet_id=' + this.value + '&order_type=<?= $order_type ?>'">
|
||||||
<?php foreach ($outlets as $o): ?>
|
<?php foreach ($outlets as $o): ?>
|
||||||
<option value="<?= $o['id'] ?>" <?= $o['id'] == $outlet_id ? 'selected' : '' ?>><?= htmlspecialchars($o['name']) ?></option>
|
<option value="<?= $o['id'] ?>" <?= $o['id'] == $outlet_id ? 'selected' : '' ?>><?= htmlspecialchars(($isRTL && !empty($o['name_ar'])) ? $o['name_ar'] : $o['name']) ?></option>
|
||||||
<?php endforeach; ?>
|
<?php endforeach; ?>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
@ -233,12 +265,13 @@ if (!$loyalty_settings) {
|
|||||||
|
|
||||||
<!-- Grid Container -->
|
<!-- Grid Container -->
|
||||||
<div class="flex-grow-1 scrollable-y p-2">
|
<div class="flex-grow-1 scrollable-y p-2">
|
||||||
<div class="row g-2 row-cols-3 row-cols-sm-4 row-cols-md-5 row-cols-lg-6 row-cols-xl-8 row-cols-xxl-10" id="product-grid">
|
<div class="row g-2 row-cols-3 row-cols-sm-4 row-cols-md-5 row-cols-lg-6 row-cols-xl-7 row-cols-xxl-7" id="product-grid">
|
||||||
<?php foreach ($all_products as $product): ?>
|
<?php foreach ($all_products as $product): ?>
|
||||||
<?php $has_variants = !empty($variants_by_product[$product['id']]); ?>
|
<?php $has_variants = !empty($variants_by_product[$product['id']]); ?>
|
||||||
<div class="col product-item"
|
<div class="col product-item"
|
||||||
data-category="<?= $product['category_id'] ?>"
|
data-category="<?= $product['category_id'] ?>"
|
||||||
data-name="<?= htmlspecialchars(strtolower($product['name'])) ?>"
|
data-name="<?= htmlspecialchars(strtolower($product['name'])) ?>"
|
||||||
|
data-name-ar="<?= htmlspecialchars(strtolower($product['name_ar'] ?? '')) ?>"
|
||||||
data-sku="<?= htmlspecialchars(strtolower($product['sku'] ?? '')) ?>"
|
data-sku="<?= htmlspecialchars(strtolower($product['sku'] ?? '')) ?>"
|
||||||
onclick="handleProductClick(<?= htmlspecialchars(json_encode($product), ENT_QUOTES) ?>, <?= htmlspecialchars(json_encode($variants_by_product[$product['id']] ?? []), ENT_QUOTES) ?>)">
|
onclick="handleProductClick(<?= htmlspecialchars(json_encode($product), ENT_QUOTES) ?>, <?= htmlspecialchars(json_encode($variants_by_product[$product['id']] ?? []), ENT_QUOTES) ?>)">
|
||||||
<div class="card h-100 border-0 shadow-sm product-card rounded-3 overflow-hidden">
|
<div class="card h-100 border-0 shadow-sm product-card rounded-3 overflow-hidden">
|
||||||
@ -258,8 +291,10 @@ if (!$loyalty_settings) {
|
|||||||
</div>
|
</div>
|
||||||
<div class="card-body p-1 text-center d-flex flex-column justify-content-between">
|
<div class="card-body p-1 text-center d-flex flex-column justify-content-between">
|
||||||
<div>
|
<div>
|
||||||
<h6 class="card-title product-title mb-0"><?= htmlspecialchars($product['name']) ?></h6>
|
<h6 class="card-title product-title mb-0"><?= htmlspecialchars(($isRTL && !empty($product['name_ar'])) ? $product['name_ar'] : $product['name']) ?></h6>
|
||||||
<?php if (!empty($product['name_ar'])): ?>
|
<?php if ($isRTL && !empty($product['name'])): ?>
|
||||||
|
<div class="text-muted product-cat-name text-truncate" style="margin-top: -2px;"><?= htmlspecialchars($product['name']) ?></div>
|
||||||
|
<?php elseif (!$isRTL && !empty($product['name_ar'])): ?>
|
||||||
<div class="text-primary product-cat-name text-truncate" dir="rtl" style="margin-top: -2px;"><?= htmlspecialchars($product['name_ar']) ?></div>
|
<div class="text-primary product-cat-name text-truncate" dir="rtl" style="margin-top: -2px;"><?= htmlspecialchars($product['name_ar']) ?></div>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
</div>
|
</div>
|
||||||
@ -277,19 +312,19 @@ if (!$loyalty_settings) {
|
|||||||
<div class="p-2 border-bottom bg-white">
|
<div class="p-2 border-bottom bg-white">
|
||||||
<div class="btn-group w-100 mb-2" role="group">
|
<div class="btn-group w-100 mb-2" role="group">
|
||||||
<input type="radio" class="btn-check" name="order_type" id="ot-takeaway" value="takeaway" <?= $order_type === 'takeaway' ? 'checked' : '' ?>>
|
<input type="radio" class="btn-check" name="order_type" id="ot-takeaway" value="takeaway" <?= $order_type === 'takeaway' ? 'checked' : '' ?>>
|
||||||
<label class="btn btn-outline-primary btn-sm py-1 rounded-start-pill" for="ot-takeaway" style="font-size: 0.75rem; font-weight: 700;">Takeaway</label>
|
<label class="btn btn-outline-primary btn-sm py-1 rounded-start-pill" for="ot-takeaway" style="font-size: 0.75rem; font-weight: 700;"><?= t('takeaway') ?></label>
|
||||||
<input type="radio" class="btn-check" name="order_type" id="ot-dine-in" value="dine-in" <?= $order_type === 'dine-in' ? 'checked' : '' ?>>
|
<input type="radio" class="btn-check" name="order_type" id="ot-dine-in" value="dine-in" <?= $order_type === 'dine-in' ? 'checked' : '' ?>>
|
||||||
<label class="btn btn-outline-primary btn-sm py-1" for="ot-dine-in" style="font-size: 0.75rem; font-weight: 700;">Dine-In</label>
|
<label class="btn btn-outline-primary btn-sm py-1" for="ot-dine-in" style="font-size: 0.75rem; font-weight: 700;"><?= t('dine_in') ?></label>
|
||||||
<input type="radio" class="btn-check" name="order_type" id="ot-delivery" value="delivery" <?= $order_type === 'delivery' ? 'checked' : '' ?>>
|
<input type="radio" class="btn-check" name="order_type" id="ot-delivery" value="delivery" <?= $order_type === 'delivery' ? 'checked' : '' ?>>
|
||||||
<label class="btn btn-outline-primary btn-sm py-1 rounded-end-pill" for="ot-delivery" style="font-size: 0.75rem; font-weight: 700;">Delivery</label>
|
<label class="btn btn-outline-primary btn-sm py-1 rounded-end-pill" for="ot-delivery" style="font-size: 0.75rem; font-weight: 700;"><?= t('delivery') ?></label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="position-relative">
|
<div class="position-relative">
|
||||||
<div class="input-group input-group-sm">
|
<div class="input-group input-group-sm">
|
||||||
<span class="input-group-text bg-light border-0 rounded-start-pill ps-3"><i class="bi bi-person text-muted"></i></span>
|
<span class="input-group-text bg-light border-0 rounded-<?= $isRTL ? 'end' : 'start' ?>-pill ps-3"><i class="bi bi-person text-muted"></i></span>
|
||||||
<input type="text" class="form-control border-0 bg-light ps-1" id="customer-search" placeholder="Customer Name/Phone" autocomplete="off" style="font-weight: 600;">
|
<input type="text" class="form-control border-0 bg-light ps-1" id="customer-search" placeholder="<?= t('customer') ?>..." autocomplete="off" style="font-weight: 600;">
|
||||||
<button class="btn btn-light border-0 d-none" type="button" id="clear-customer"><i class="bi bi-x"></i></button>
|
<button class="btn btn-light border-0 d-none" type="button" id="clear-customer"><i class="bi bi-x"></i></button>
|
||||||
<button class="btn btn-light border-0 rounded-end-pill pe-3 text-primary" type="button" data-bs-toggle="modal" data-bs-target="#addCustomerModal"><i class="bi bi-plus-lg"></i></button>
|
<button class="btn btn-light border-0 rounded-<?= $isRTL ? 'start' : 'end' ?>-pill pe-3 text-primary" type="button" data-bs-toggle="modal" data-bs-target="#addCustomerModal"><i class="bi bi-plus-lg"></i></button>
|
||||||
</div>
|
</div>
|
||||||
<div class="list-group shadow border-0 search-dropdown" id="customer-results" style="border-radius: 12px; margin-top: 5px;"></div>
|
<div class="list-group shadow border-0 search-dropdown" id="customer-results" style="border-radius: 12px; margin-top: 5px;"></div>
|
||||||
<input type="hidden" id="selected-customer-id">
|
<input type="hidden" id="selected-customer-id">
|
||||||
@ -299,24 +334,24 @@ if (!$loyalty_settings) {
|
|||||||
<div class="flex-grow-1 overflow-auto p-2 bg-white" id="cart-items">
|
<div class="flex-grow-1 overflow-auto p-2 bg-white" id="cart-items">
|
||||||
<div class="text-center text-muted mt-5 opacity-50">
|
<div class="text-center text-muted mt-5 opacity-50">
|
||||||
<i class="bi bi-basket3 fs-1 d-block mb-2"></i>
|
<i class="bi bi-basket3 fs-1 d-block mb-2"></i>
|
||||||
<p class="small">Cart is empty</p>
|
<p class="small"><?= t('none') ?></p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="p-3 border-top bg-light mt-auto rounded-top-4">
|
<div class="p-3 border-top bg-light mt-auto rounded-top-4">
|
||||||
<div class="d-flex justify-content-between mb-1">
|
<div class="d-flex justify-content-between mb-1">
|
||||||
<span class="text-muted small">Subtotal</span>
|
<span class="text-muted small"><?= t('total') ?></span>
|
||||||
<span class="fw-bold small" id="cart-subtotal"><?= format_currency(0) ?></span>
|
<span class="fw-bold small" id="cart-subtotal"><?= format_currency(0) ?></span>
|
||||||
</div>
|
</div>
|
||||||
<div class="d-flex justify-content-between mb-3">
|
<div class="d-flex justify-content-between mb-3">
|
||||||
<span class="fs-6 fw-bold">Total Payable</span>
|
<span class="fs-6 fw-bold"><?= t('total') ?></span>
|
||||||
<span class="fs-5 fw-bold text-primary" id="cart-total-price"><?= format_currency(0) ?></span>
|
<span class="fs-5 fw-bold text-primary" id="cart-total-price"><?= format_currency(0) ?></span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<button class="btn btn-link text-danger w-100 py-0 fw-semibold mb-3 btn-sm text-decoration-none" onclick="clearCart()" style="font-size: 0.75rem;">Empty Cart</button>
|
<button class="btn btn-link text-danger w-100 py-0 fw-semibold mb-3 btn-sm text-decoration-none" onclick="clearCart()" style="font-size: 0.75rem;"><?= t('close') ?></button>
|
||||||
<div class="d-flex gap-2">
|
<div class="d-flex gap-2">
|
||||||
<button class="btn btn-primary w-50 btn-sm shadow-sm fw-bold py-2 rounded-3" id="quick-order-btn" disabled>QUICK PAY</button>
|
<button class="btn btn-primary w-50 btn-sm shadow-sm fw-bold py-2 rounded-3" id="quick-order-btn" disabled><?= t('save') ?></button>
|
||||||
<button class="btn btn-outline-warning w-50 btn-sm shadow-sm fw-bold py-2 rounded-3" id="place-order-btn" disabled>SAVE BILL</button>
|
<button class="btn btn-outline-warning w-50 btn-sm shadow-sm fw-bold py-2 rounded-3" id="place-order-btn" disabled><?= t('save') ?></button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -329,7 +364,7 @@ if (!$loyalty_settings) {
|
|||||||
<div class="modal-dialog modal-lg modal-dialog-centered">
|
<div class="modal-dialog modal-lg modal-dialog-centered">
|
||||||
<div class="modal-content border-0 shadow-lg" style="border-radius: 20px;">
|
<div class="modal-content border-0 shadow-lg" style="border-radius: 20px;">
|
||||||
<div class="modal-header border-0 pb-0">
|
<div class="modal-header border-0 pb-0">
|
||||||
<h6 class="modal-title fw-bold">Recall Unpaid Bill</h6>
|
<h6 class="modal-title fw-bold"><?= t('recall') ?></h6>
|
||||||
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-body p-3"><div id="recall-orders-list" class="list-group list-group-flush"></div></div>
|
<div class="modal-body p-3"><div id="recall-orders-list" class="list-group list-group-flush"></div></div>
|
||||||
@ -341,7 +376,7 @@ if (!$loyalty_settings) {
|
|||||||
<div class="modal-dialog modal-dialog-centered modal-sm">
|
<div class="modal-dialog modal-dialog-centered modal-sm">
|
||||||
<div class="modal-content border-0 shadow-lg" style="border-radius: 20px;">
|
<div class="modal-content border-0 shadow-lg" style="border-radius: 20px;">
|
||||||
<div class="modal-header border-0 pb-0">
|
<div class="modal-header border-0 pb-0">
|
||||||
<h6 class="modal-title fw-bold" id="variantModalTitle">Options</h6>
|
<h6 class="modal-title fw-bold" id="variantModalTitle"><?= t('variant') ?></h6>
|
||||||
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-body p-3"><div id="variant-list" class="list-group list-group-flush"></div></div>
|
<div class="modal-body p-3"><div id="variant-list" class="list-group list-group-flush"></div></div>
|
||||||
@ -353,19 +388,19 @@ if (!$loyalty_settings) {
|
|||||||
<div class="modal-dialog modal-dialog-centered modal-sm">
|
<div class="modal-dialog modal-dialog-centered modal-sm">
|
||||||
<div class="modal-content border-0 shadow-lg" style="border-radius: 20px;">
|
<div class="modal-content border-0 shadow-lg" style="border-radius: 20px;">
|
||||||
<div class="modal-header border-0 pb-0">
|
<div class="modal-header border-0 pb-0">
|
||||||
<h6 class="modal-title fw-bold">New Customer</h6>
|
<h6 class="modal-title fw-bold"><?= t('add') ?> <?= t('customer') ?></h6>
|
||||||
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-body p-3">
|
<div class="modal-body p-3">
|
||||||
<div class="mb-2">
|
<div class="mb-2">
|
||||||
<label class="small text-muted mb-1">Full Name</label>
|
<label class="small text-muted mb-1"><?= t('name') ?></label>
|
||||||
<input type="text" class="form-control form-control-sm rounded-3" id="new-customer-name">
|
<input type="text" class="form-control form-control-sm rounded-3" id="new-customer-name">
|
||||||
</div>
|
</div>
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label class="small text-muted mb-1">Phone Number</label>
|
<label class="small text-muted mb-1"><?= t('phone') ?></label>
|
||||||
<input type="text" class="form-control form-control-sm rounded-3" id="new-customer-phone">
|
<input type="text" class="form-control form-control-sm rounded-3" id="new-customer-phone">
|
||||||
</div>
|
</div>
|
||||||
<button type="button" class="btn btn-primary btn-sm w-100 py-2 rounded-3" id="save-new-customer">Add Customer</button>
|
<button type="button" class="btn btn-primary btn-sm w-100 py-2 rounded-3" id="save-new-customer"><?= t('add') ?></button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -375,7 +410,7 @@ if (!$loyalty_settings) {
|
|||||||
<div class="modal-dialog modal-dialog-centered modal-sm">
|
<div class="modal-dialog modal-dialog-centered modal-sm">
|
||||||
<div class="modal-content border-0 shadow-lg" style="border-radius: 20px;">
|
<div class="modal-content border-0 shadow-lg" style="border-radius: 20px;">
|
||||||
<div class="modal-header border-0 pb-0">
|
<div class="modal-header border-0 pb-0">
|
||||||
<h6 class="modal-title fw-bold">Select Payment</h6>
|
<h6 class="modal-title fw-bold"><?= t('payment') ?></h6>
|
||||||
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-body p-3"><div class="row g-2" id="payment-methods-container"></div></div>
|
<div class="modal-body p-3"><div class="row g-2" id="payment-methods-container"></div></div>
|
||||||
@ -393,6 +428,30 @@ if (!$loyalty_settings) {
|
|||||||
const CURRENT_OUTLET = { id: <?= $outlet_id ?>, name: '<?= addslashes($current_outlet_name) ?>' };
|
const CURRENT_OUTLET = { id: <?= $outlet_id ?>, name: '<?= addslashes($current_outlet_name) ?>' };
|
||||||
const CURRENT_USER = { id: <?= $currentUser['id'] ?>, name: '<?= addslashes($currentUser['username']) ?>' };
|
const CURRENT_USER = { id: <?= $currentUser['id'] ?>, name: '<?= addslashes($currentUser['username']) ?>' };
|
||||||
const LOYALTY_SETTINGS = <?= json_encode($loyalty_settings) ?>;
|
const LOYALTY_SETTINGS = <?= json_encode($loyalty_settings) ?>;
|
||||||
|
const LANG = '<?= $currentLang ?>';
|
||||||
|
|
||||||
|
// JS Translations
|
||||||
|
const translations = {
|
||||||
|
'en': {
|
||||||
|
'cart_empty': 'Cart is empty',
|
||||||
|
'remove': 'Remove',
|
||||||
|
'order_placed': 'Order Placed',
|
||||||
|
'order_success': 'Order processed successfully!',
|
||||||
|
'error': 'Error',
|
||||||
|
'quick_pay': 'QUICK PAY',
|
||||||
|
'save_bill': 'SAVE BILL'
|
||||||
|
},
|
||||||
|
'ar': {
|
||||||
|
'cart_empty': 'السلة فارغة',
|
||||||
|
'remove': 'إزالة',
|
||||||
|
'order_placed': 'تم تقديم الطلب',
|
||||||
|
'order_success': 'تم معالجة الطلب بنجاح!',
|
||||||
|
'error': 'خطأ',
|
||||||
|
'quick_pay': 'دفع سريع',
|
||||||
|
'save_bill': 'حفظ الفاتورة'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const t = (key) => translations[LANG][key] || key;
|
||||||
</script>
|
</script>
|
||||||
<script src="assets/js/main.js?v=<?= time() ?>"></script>
|
<script src="assets/js/main.js?v=<?= time() ?>"></script>
|
||||||
</body>
|
</body>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user