adding services
This commit is contained in:
parent
874d750960
commit
ab23c4540e
BIN
assets/images/items/item_69a567f77a8364.03372918.jpeg
Normal file
BIN
assets/images/items/item_69a567f77a8364.03372918.jpeg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.2 KiB |
211
items.php
211
items.php
@ -162,13 +162,12 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action'])) {
|
||||
} elseif ($_POST['action'] === 'update_price') {
|
||||
$item_id = $_POST['item_id'];
|
||||
$service_id = $_POST['service_id'];
|
||||
$variant_id = $_POST['variant_id'] ?: null;
|
||||
$price = $_POST['price'];
|
||||
|
||||
$stmt = db()->prepare("INSERT INTO prices (branch_id, item_id, variant_id, service_id, price)
|
||||
VALUES (?, ?, ?, ?, ?)
|
||||
$stmt = db()->prepare("INSERT INTO prices (branch_id, item_id, service_id, price)
|
||||
VALUES (?, ?, ?, ?)
|
||||
ON DUPLICATE KEY UPDATE price = ?");
|
||||
$stmt->execute([$branch_id, $item_id, $variant_id, $service_id, $price, $price]);
|
||||
$stmt->execute([$branch_id, $item_id, $service_id, $price, $price]);
|
||||
|
||||
if (isset($_POST['ajax'])) {
|
||||
header('Content-Type: application/json');
|
||||
@ -178,35 +177,6 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action'])) {
|
||||
|
||||
header('Location: items.php?success=price_updated');
|
||||
exit;
|
||||
} elseif ($_POST['action'] === 'add_variant') {
|
||||
$item_id = $_POST['item_id'];
|
||||
$name_en = $_POST['variant_name_en'];
|
||||
$name_ar = $_POST['variant_name_ar'];
|
||||
$stmt = db()->prepare("INSERT INTO item_variants (item_id, name_en, name_ar) VALUES (?, ?, ?)");
|
||||
$stmt->execute([$item_id, $name_en, $name_ar]);
|
||||
header('Location: items.php?success=variant_added');
|
||||
exit;
|
||||
} elseif ($_POST['action'] === 'edit_variant') {
|
||||
$id = $_POST['id'];
|
||||
$name_en = $_POST['name_en'];
|
||||
$name_ar = $_POST['name_ar'];
|
||||
$stmt = db()->prepare("UPDATE item_variants SET name_en = ?, name_ar = ? WHERE id = ?");
|
||||
$stmt->execute([$name_en, $name_ar, $id]);
|
||||
|
||||
if (isset($_POST['ajax'])) {
|
||||
header('Content-Type: application/json');
|
||||
echo json_encode(['success' => true]);
|
||||
exit;
|
||||
}
|
||||
|
||||
header('Location: items.php?success=variant_updated');
|
||||
exit;
|
||||
} elseif ($_POST['action'] === 'delete_variant') {
|
||||
$id = $_POST['id'];
|
||||
$stmt = db()->prepare("DELETE FROM item_variants WHERE id = ?");
|
||||
$stmt->execute([$id]);
|
||||
header('Location: items.php?success=variant_deleted');
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
@ -226,14 +196,7 @@ $stmt->execute([$branch_id]);
|
||||
$prices_raw = $stmt->fetchAll();
|
||||
$prices = [];
|
||||
foreach ($prices_raw as $p) {
|
||||
$v_key = $p['variant_id'] ?: 'default';
|
||||
$prices[$p['item_id']][$v_key][$p['service_id']] = $p['price'];
|
||||
}
|
||||
|
||||
$item_variants = db()->query("SELECT * FROM item_variants ORDER BY name_en ASC")->fetchAll();
|
||||
$variants_by_item = [];
|
||||
foreach ($item_variants as $v) {
|
||||
$variants_by_item[$v['item_id']][] = $v;
|
||||
$prices[$p['item_id']][$p['service_id']] = $p['price'];
|
||||
}
|
||||
?>
|
||||
|
||||
@ -268,7 +231,7 @@ foreach ($item_variants as $v) {
|
||||
<th class="ps-4 py-3"><?= __('item') ?></th>
|
||||
<th class="py-3"><?= __('category') ?></th>
|
||||
<th class="py-3"><?= __('vat_percent') ?></th>
|
||||
<th class="py-3"><?= __('variants_prices') ?? 'Pricing & Services' ?></th>
|
||||
<th class="py-3"><?= __('pricing_services') ?? 'Pricing & Services' ?></th>
|
||||
<th class="pe-4 py-3 text-end"><?= __('actions') ?></th>
|
||||
</tr>
|
||||
</thead>
|
||||
@ -302,7 +265,7 @@ foreach ($item_variants as $v) {
|
||||
<td><?= number_format($item['vat_percent'], 2) ?>%</td>
|
||||
<td>
|
||||
<button class="btn btn-sm btn-outline-info px-3" style="border-radius: 8px;" data-bs-toggle="modal" data-bs-target="#pricingModal<?= $item['id'] ?>">
|
||||
<i class="bi bi-currency-dollar me-1"></i> <?= count($variants_by_item[$item['id']] ?? []) ?> <?= __('variants') ?> / <?= count($services) ?> <?= __('services') ?>
|
||||
<i class="bi bi-currency-dollar me-1"></i> <?= count($services) ?> <?= __('services') ?>
|
||||
</button>
|
||||
</td>
|
||||
<td class="pe-4 text-end">
|
||||
@ -324,10 +287,10 @@ foreach ($item_variants as $v) {
|
||||
<div class="d-flex">
|
||||
<i class="bi bi-info-circle-fill me-3 fs-4"></i>
|
||||
<div>
|
||||
<h6 class="fw-bold mb-1">How to use Variants & Services?</h6>
|
||||
<h6 class="fw-bold mb-1">How to manage Services?</h6>
|
||||
<p class="mb-0 small">
|
||||
<strong>Services:</strong> General actions like "Wash Only", "Urgent Wash", "Iron Only". Add them once and set prices for each item.<br>
|
||||
<strong>Variants:</strong> Specific garment types or materials like "Silk Dress", "Wool Suit", or "Large Carpet". Use them if an item has different versions with unique pricing.
|
||||
<strong>Services:</strong> Actions like "Wash Only", "Urgent Wash", "Iron Only". Add them using the <strong>Services</strong> button at the top, then set prices for each item in the table above.<br>
|
||||
<em>Simplified:</em> We removed "Variants" to make it easier. Now you just define your services and set their prices for each item.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
@ -535,64 +498,35 @@ foreach ($item_variants as $v) {
|
||||
<!-- Pricing Modals -->
|
||||
<?php foreach($items as $item): ?>
|
||||
<div class="modal fade pricing-modal" id="pricingModal<?= $item['id'] ?>" tabindex="-1">
|
||||
<div class="modal-dialog modal-xl modal-dialog-centered">
|
||||
<div class="modal-dialog modal-lg modal-dialog-centered">
|
||||
<div class="modal-content" style="border-radius: 25px;">
|
||||
<div class="modal-header border-0 p-4">
|
||||
<div>
|
||||
<h5 class="modal-title fw-bold m-0"><?= __('pricing_management') ?></h5>
|
||||
<h5 class="modal-title fw-bold m-0"><?= __('service_pricing') ?? 'Service Pricing' ?></h5>
|
||||
<p class="text-muted m-0 small"><?= $lang === 'ar' ? $item['name_ar'] : $item['name_en'] ?></p>
|
||||
</div>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
||||
</div>
|
||||
<div class="modal-body p-4 pt-0">
|
||||
<!-- Add Variant Form -->
|
||||
<div class="bg-light p-3 mb-4 d-flex align-items-end" style="border-radius: 15px;">
|
||||
<form method="POST" class="row g-2 w-100">
|
||||
<input type="hidden" name="action" value="add_variant">
|
||||
<input type="hidden" name="item_id" value="<?= $item['id'] ?>">
|
||||
<div class="col-md-4">
|
||||
<label class="form-label small fw-bold mb-1"><?= __('variant_name_en') ?? 'Variant Name (e.g. Silk, Long, Small)' ?></label>
|
||||
<input type="text" name="variant_name_en" class="form-control form-control-sm" required style="border-radius: 8px;">
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<label class="form-label small fw-bold mb-1"><?= __('variant_name_ar') ?? 'Variant Name (AR)' ?></label>
|
||||
<input type="text" name="variant_name_ar" class="form-control form-control-sm" style="border-radius: 8px;">
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<button type="submit" class="btn btn-sm btn-primary w-100 py-2 fw-bold" style="border-radius: 8px;">
|
||||
<i class="bi bi-plus-lg me-1"></i> <?= __('add_variant') ?>
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div class="table-responsive">
|
||||
<table class="table table-hover align-middle">
|
||||
<thead class="bg-light">
|
||||
<tr class="small text-muted">
|
||||
<th style="min-width: 200px;"><?= __('variant') ?></th>
|
||||
<?php foreach($services as $s): ?>
|
||||
<th class="text-center"><?= $lang === 'ar' ? $s['name_ar'] : $s['name_en'] ?></th>
|
||||
<?php endforeach; ?>
|
||||
<th class="text-end"><?= __('actions') ?></th>
|
||||
<th style="min-width: 200px;"><?= __('service') ?></th>
|
||||
<th class="text-center"><?= __('price') ?> (SAR)</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<!-- Default Variant -->
|
||||
<tr>
|
||||
<td class="fw-bold">
|
||||
<div class="d-flex align-items-center">
|
||||
<i class="bi bi-star-fill text-warning me-2"></i>
|
||||
<?= __('default') ?>
|
||||
</div>
|
||||
</td>
|
||||
<?php foreach($services as $service): ?>
|
||||
<?php foreach($services as $service): ?>
|
||||
<tr>
|
||||
<td class="fw-bold">
|
||||
<?= $lang === 'ar' ? $service['name_ar'] : $service['name_en'] ?>
|
||||
</td>
|
||||
<td class="text-center">
|
||||
<div class="input-group input-group-sm justify-content-center mx-auto" style="width: 120px; position: relative;">
|
||||
<div class="input-group input-group-sm justify-content-center mx-auto" style="width: 150px; position: relative;">
|
||||
<input type="number" step="0.01" class="form-control text-center price-input"
|
||||
value="<?= $prices[$item['id']]['default'][$service['id']] ?? 0.00 ?>"
|
||||
value="<?= $prices[$item['id']][$service['id']] ?? 0.00 ?>"
|
||||
data-item-id="<?= $item['id'] ?>"
|
||||
data-variant-id=""
|
||||
data-service-id="<?= $service['id'] ?>"
|
||||
style="border-radius: 8px;">
|
||||
<span class="input-group-text bg-transparent border-0 d-none success-indicator" style="position: absolute; right: -25px; top: 5px;">
|
||||
@ -600,64 +534,13 @@ foreach ($item_variants as $v) {
|
||||
</span>
|
||||
</div>
|
||||
</td>
|
||||
<?php endforeach; ?>
|
||||
<td class="text-end"></td>
|
||||
</tr>
|
||||
<!-- Custom Variants -->
|
||||
<?php if(isset($variants_by_item[$item['id']])): ?>
|
||||
<?php foreach($variants_by_item[$item['id']] as $variant): ?>
|
||||
<tr>
|
||||
<td>
|
||||
<div class="row g-1 position-relative">
|
||||
<div class="col-6">
|
||||
<input type="text" class="form-control form-control-sm variant-name-input"
|
||||
value="<?= $variant['name_en'] ?>"
|
||||
data-variant-id="<?= $variant['id'] ?>"
|
||||
data-field="name_en"
|
||||
placeholder="EN"
|
||||
style="border-radius: 6px;">
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<input type="text" class="form-control form-control-sm variant-name-input"
|
||||
value="<?= $variant['name_ar'] ?>"
|
||||
data-variant-id="<?= $variant['id'] ?>"
|
||||
data-field="name_ar"
|
||||
placeholder="AR"
|
||||
style="border-radius: 6px; text-align: right;">
|
||||
</div>
|
||||
<span class="success-indicator d-none" style="position: absolute; right: -20px; top: 8px;">
|
||||
<i class="bi bi-check-lg text-success"></i>
|
||||
</span>
|
||||
</div>
|
||||
</td>
|
||||
<?php foreach($services as $service): ?>
|
||||
<td class="text-center">
|
||||
<div class="input-group input-group-sm justify-content-center mx-auto" style="width: 120px; position: relative;">
|
||||
<input type="number" step="0.01" class="form-control text-center price-input"
|
||||
value="<?= $prices[$item['id']][$variant['id']][$service['id']] ?? 0.00 ?>"
|
||||
data-item-id="<?= $item['id'] ?>"
|
||||
data-variant-id="<?= $variant['id'] ?>"
|
||||
data-service-id="<?= $service['id'] ?>"
|
||||
style="border-radius: 8px;">
|
||||
<span class="input-group-text bg-transparent border-0 d-none success-indicator" style="position: absolute; right: -25px; top: 5px;">
|
||||
<i class="bi bi-check-lg text-success"></i>
|
||||
</span>
|
||||
</div>
|
||||
</td>
|
||||
<?php endforeach; ?>
|
||||
<td class="text-end">
|
||||
<button type="button" class="btn btn-sm btn-light text-danger" onclick="confirmDeleteVariant(<?= $variant['id'] ?>)" style="border-radius: 8px;">
|
||||
<i class="bi bi-trash"></i>
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
<?php endif; ?>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="alert alert-info py-2 small mt-3 mb-0" style="border-radius: 10px;">
|
||||
<i class="bi bi-info-circle me-2"></i> Prices and variant names are saved automatically as you type.
|
||||
<i class="bi bi-info-circle me-2"></i> Prices are saved automatically as you type.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -673,7 +556,7 @@ foreach ($item_variants as $v) {
|
||||
|
||||
<style>
|
||||
.bg-soft-primary { background-color: rgba(13, 110, 253, 0.1); }
|
||||
.price-input:focus, .variant-name-input:focus {
|
||||
.price-input:focus {
|
||||
border-color: #0d6efd;
|
||||
box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.1);
|
||||
}
|
||||
@ -761,15 +644,7 @@ function confirmDelete(type, id) {
|
||||
}
|
||||
}
|
||||
|
||||
function confirmDeleteVariant(id) {
|
||||
if (confirm("<?= __('are_you_sure') ?>")) {
|
||||
document.getElementById('deleteAction').value = 'delete_variant';
|
||||
document.getElementById('deleteId').value = id;
|
||||
document.getElementById('deleteForm').submit();
|
||||
}
|
||||
}
|
||||
|
||||
// AJAX logic for prices and variants
|
||||
// AJAX logic for prices
|
||||
document.querySelectorAll('.price-input').forEach(input => {
|
||||
let timeout = null;
|
||||
input.addEventListener('input', function() {
|
||||
@ -780,7 +655,6 @@ document.querySelectorAll('.price-input').forEach(input => {
|
||||
formData.append('action', 'update_price');
|
||||
formData.append('ajax', '1');
|
||||
formData.append('item_id', self.dataset.itemId);
|
||||
formData.append('variant_id', self.dataset.variantId);
|
||||
formData.append('service_id', self.dataset.serviceId);
|
||||
formData.append('price', self.value);
|
||||
|
||||
@ -800,41 +674,8 @@ document.querySelectorAll('.price-input').forEach(input => {
|
||||
});
|
||||
});
|
||||
|
||||
document.querySelectorAll('.variant-name-input').forEach(input => {
|
||||
let timeout = null;
|
||||
input.addEventListener('input', function() {
|
||||
clearTimeout(timeout);
|
||||
const self = this;
|
||||
timeout = setTimeout(async () => {
|
||||
const row = self.closest('tr');
|
||||
const enInput = row.querySelector('[data-field="name_en"]');
|
||||
const arInput = row.querySelector('[data-field="name_ar"]');
|
||||
|
||||
const formData = new FormData();
|
||||
formData.append('action', 'edit_variant');
|
||||
formData.append('ajax', '1');
|
||||
formData.append('id', self.dataset.variantId);
|
||||
formData.append('name_en', enInput.value);
|
||||
formData.append('name_ar', arInput.value);
|
||||
|
||||
try {
|
||||
const response = await fetch('items.php', {
|
||||
method: 'POST',
|
||||
body: formData
|
||||
});
|
||||
const data = await response.json();
|
||||
if (data.success) {
|
||||
showIndicator(self);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error updating variant:', error);
|
||||
}
|
||||
}, 500);
|
||||
});
|
||||
});
|
||||
|
||||
function showIndicator(input) {
|
||||
const indicator = input.parentElement.querySelector('.success-indicator') || input.closest('td').querySelector('.success-indicator');
|
||||
const indicator = input.parentElement.querySelector('.success-indicator');
|
||||
if (indicator) {
|
||||
indicator.classList.remove('d-none');
|
||||
setTimeout(() => {
|
||||
|
||||
@ -53,12 +53,10 @@ $title = 'order_details';
|
||||
require_once __DIR__ . '/includes/header.php';
|
||||
|
||||
$stmt = db()->prepare("SELECT oi.*, i.name_en as item_en, i.name_ar as item_ar,
|
||||
s.name_en as service_en, s.name_ar as service_ar,
|
||||
v.name_en as variant_en, v.name_ar as variant_ar
|
||||
s.name_en as service_en, s.name_ar as service_ar
|
||||
FROM order_items oi
|
||||
JOIN items i ON oi.item_id = i.id
|
||||
JOIN services s ON oi.service_id = s.id
|
||||
LEFT JOIN item_variants v ON oi.variant_id = v.id
|
||||
WHERE oi.order_id = ?");
|
||||
$stmt->execute([$order_id]);
|
||||
$order_items = $stmt->fetchAll();
|
||||
@ -71,10 +69,10 @@ $payments = $stmt->fetchAll();
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-8">
|
||||
<div class="card p-4 mb-4">
|
||||
<div class="card p-4 mb-4" style="border-radius: 25px; border: none; shadow: 0 10px 30px rgba(0,0,0,0.05);">
|
||||
<div class="d-flex justify-content-between align-items-center mb-4">
|
||||
<h5 class="fw-bold mb-0"><?= __('order') ?> #<?= $order['order_number'] ?></h5>
|
||||
<span class="badge bg-<?= getStatusColor($order['status']) ?> fs-6 px-3 py-2"><?= __($order['status']) ?></span>
|
||||
<span class="badge bg-<?= getStatusColor($order['status']) ?> fs-6 px-3 py-2" style="border-radius: 12px;"><?= __($order['status']) ?></span>
|
||||
</div>
|
||||
|
||||
<div class="table-responsive mb-4">
|
||||
@ -97,56 +95,54 @@ $payments = $stmt->fetchAll();
|
||||
?>
|
||||
<tr>
|
||||
<td>
|
||||
<?= $lang === 'ar' ? ($item['item_ar'] ?: $item['item_en']) : $item['item_en'] ?>
|
||||
<?php if($item['variant_id']): ?>
|
||||
<br><small class="text-muted"><?= $lang === 'ar' ? $item['variant_ar'] : $item['variant_en'] ?></small>
|
||||
<?php endif; ?>
|
||||
<strong><?= $lang === 'ar' ? ($item['item_ar'] ?: $item['item_en']) : $item['item_en'] ?></strong>
|
||||
</td>
|
||||
<td><?= $lang === 'ar' ? ($item['service_ar'] ?: $item['service_en']) : $item['service_en'] ?></td>
|
||||
<td><?= $item['quantity'] ?></td>
|
||||
<td class="text-end"><?= number_format($item['unit_price'], 2) ?> SAR</td>
|
||||
<td class="text-end"><?= number_format($item['vat_amount'] * $item['quantity'], 2) ?> SAR</td>
|
||||
<td class="text-end"><?= number_format($item['subtotal'] + ($item['vat_amount'] * $item['quantity']), 2) ?> SAR</td>
|
||||
<td class="text-end fw-bold"><?= number_format($item['subtotal'] + ($item['vat_amount'] * $item['quantity']), 2) ?> SAR</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr>
|
||||
<th colspan="5" class="text-end"><?= __('subtotal') ?></th>
|
||||
<th colspan="5" class="text-end text-muted small"><?= __('subtotal') ?></th>
|
||||
<th class="text-end"><?= number_format($subtotal_sum, 2) ?> SAR</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th colspan="5" class="text-end"><?= __('vat_total') ?? 'VAT Total' ?></th>
|
||||
<th colspan="5" class="text-end text-muted small"><?= __('vat_total') ?? 'VAT Total' ?></th>
|
||||
<th class="text-end"><?= number_format($order['vat_total'], 2) ?> SAR</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th colspan="5" class="text-end"><?= __('total') ?></th>
|
||||
<th class="text-end fs-5 text-primary"><?= number_format($order['total_price'], 2) ?> SAR</th>
|
||||
<th colspan="5" class="text-end fs-5 fw-bold"><?= __('total') ?></th>
|
||||
<th class="text-end fs-5 fw-bold text-primary"><?= number_format($order['total_price'], 2) ?> SAR</th>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="row mt-4">
|
||||
<div class="row mt-4 p-4 bg-light mx-1" style="border-radius: 20px;">
|
||||
<div class="col-md-6">
|
||||
<h6 class="fw-bold"><?= __('customer_details') ?></h6>
|
||||
<p class="mb-1"><strong><?= $lang === 'ar' ? ($order['customer_name_ar'] ?: $order['customer_name_en']) : $order['customer_name_en'] ?></strong></p>
|
||||
<h6 class="fw-bold text-muted small mb-3"><?= __('customer_details') ?></h6>
|
||||
<p class="mb-1 fw-bold"><?= $lang === 'ar' ? ($order['customer_name_ar'] ?: $order['customer_name_en']) : $order['customer_name_en'] ?></p>
|
||||
<p class="mb-1"><?= $order['customer_phone'] ?></p>
|
||||
<p class="mb-0 text-muted"><?= $lang === 'ar' ? ($order['customer_address_ar'] ?: $order['customer_address_en']) : $order['customer_address_en'] ?></p>
|
||||
<p class="mb-0 text-muted small"><?= $lang === 'ar' ? ($order['customer_address_ar'] ?: $order['customer_address_en']) : $order['customer_address_en'] ?></p>
|
||||
</div>
|
||||
<div class="col-md-6 text-md-end">
|
||||
<h6 class="fw-bold"><?= __('order_date') ?></h6>
|
||||
<p><?= date('d M Y, h:i A', strtotime($order['created_at'])) ?></p>
|
||||
<div class="col-md-6 text-md-end mt-4 mt-md-0">
|
||||
<h6 class="fw-bold text-muted small mb-3"><?= __('order_date') ?></h6>
|
||||
<p class="mb-0 fw-bold"><?= date('d M Y', strtotime($order['created_at'])) ?></p>
|
||||
<p class="mb-0 text-muted"><?= date('h:i A', strtotime($order['created_at'])) ?></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card p-4">
|
||||
<div class="card p-4 border-0 shadow-sm mb-4" style="border-radius: 25px;">
|
||||
<h5 class="fw-bold mb-4"><?= __('payments') ?></h5>
|
||||
<div class="table-responsive">
|
||||
<table class="table">
|
||||
<table class="table table-sm">
|
||||
<thead>
|
||||
<tr>
|
||||
<tr class="text-muted small">
|
||||
<th><?= __('date') ?></th>
|
||||
<th><?= __('method') ?></th>
|
||||
<th class="text-end"><?= __('amount') ?></th>
|
||||
@ -156,13 +152,13 @@ $payments = $stmt->fetchAll();
|
||||
<?php foreach($payments as $p): ?>
|
||||
<tr>
|
||||
<td><?= date('d M Y, h:i A', strtotime($p['created_at'])) ?></td>
|
||||
<td><?= __($p['payment_method']) ?></td>
|
||||
<td class="text-end"><?= number_format($p['amount'], 2) ?> SAR</td>
|
||||
<td><span class="badge bg-light text-dark px-3 py-2 rounded-pill"><?= __($p['payment_method']) ?></span></td>
|
||||
<td class="text-end fw-bold"><?= number_format($p['amount'], 2) ?> SAR</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
<?php if (empty($payments)): ?>
|
||||
<tr>
|
||||
<td colspan="3" class="text-center text-muted"><?= __('no_payments') ?></td>
|
||||
<td colspan="3" class="text-center text-muted py-4"><?= __('no_payments') ?></td>
|
||||
</tr>
|
||||
<?php endif; ?>
|
||||
</tbody>
|
||||
@ -172,52 +168,57 @@ $payments = $stmt->fetchAll();
|
||||
</div>
|
||||
|
||||
<div class="col-md-4">
|
||||
<div class="card p-4 mb-4">
|
||||
<div class="card p-4 mb-4 border-0 shadow-sm" style="border-radius: 25px;">
|
||||
<h5 class="fw-bold mb-4"><?= __('actions') ?></h5>
|
||||
<form method="POST" class="mb-4">
|
||||
<input type="hidden" name="action" value="update_status">
|
||||
<label class="form-label small text-muted"><?= __('update_status') ?></label>
|
||||
<div class="input-group">
|
||||
<select name="status" class="form-select" style="border-radius: 12px 0 0 12px;">
|
||||
<label class="form-label small fw-bold text-muted"><?= __('update_status') ?></label>
|
||||
<div class="input-group shadow-sm" style="border-radius: 12px; overflow: hidden;">
|
||||
<select name="status" class="form-select border-0 bg-light">
|
||||
<option value="received" <?= $order['status'] == 'received' ? 'selected' : '' ?>><?= __('received') ?></option>
|
||||
<option value="processing" <?= $order['status'] == 'processing' ? 'selected' : '' ?>><?= __('processing') ?></option>
|
||||
<option value="ready" <?= $order['status'] == 'ready' ? 'selected' : '' ?>><?= __('ready') ?></option>
|
||||
<option value="delivered" <?= $order['status'] == 'delivered' ? 'selected' : '' ?>><?= __('delivered') ?></option>
|
||||
<option value="cancelled" <?= $order['status'] == 'cancelled' ? 'selected' : '' ?>><?= __('cancelled') ?></option>
|
||||
</select>
|
||||
<button type="submit" class="btn btn-primary" style="border-radius: 0 12px 12px 0;"><?= __('update') ?></button>
|
||||
<button type="submit" class="btn btn-primary px-3 fw-bold"><?= __('update') ?></button>
|
||||
</div>
|
||||
</form>
|
||||
<hr>
|
||||
<hr class="my-4 opacity-10">
|
||||
<?php
|
||||
$stmt = db()->prepare("SELECT SUM(amount) as total_paid FROM payments WHERE order_id = ?");
|
||||
$stmt->execute([$order_id]);
|
||||
$total_paid = $stmt->fetch()['total_paid'] ?? 0;
|
||||
$remaining = $order['total_price'] - $total_paid;
|
||||
?>
|
||||
<div class="alert alert-<?= $remaining <= 0 ? 'success' : 'warning' ?> p-2 px-3 small rounded-4">
|
||||
<?= __('remaining_amount') ?>: <strong><?= number_format(max(0, $remaining), 2) ?> SAR</strong>
|
||||
<div class="d-flex justify-content-between align-items-center mb-3">
|
||||
<span class="text-muted fw-bold small"><?= __('remaining_amount') ?></span>
|
||||
<span class="fs-5 fw-bold <?= $remaining <= 0 ? 'text-success' : 'text-danger' ?>">
|
||||
<?= number_format(max(0, $remaining), 2) ?> <small>SAR</small>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<?php if ($remaining > 0): ?>
|
||||
<form method="POST">
|
||||
<input type="hidden" name="action" value="add_payment">
|
||||
<div class="mb-3">
|
||||
<label class="form-label small text-muted"><?= __('amount') ?></label>
|
||||
<input type="number" step="0.01" name="amount" class="form-control" value="<?= $remaining ?>" required style="border-radius: 12px;">
|
||||
<label class="form-label small fw-bold text-muted"><?= __('amount') ?></label>
|
||||
<input type="number" step="0.01" name="amount" class="form-control bg-light border-0" value="<?= $remaining ?>" required style="border-radius: 12px;">
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label small text-muted"><?= __('payment_method') ?></label>
|
||||
<select name="payment_method" class="form-select" style="border-radius: 12px;">
|
||||
<label class="form-label small fw-bold text-muted"><?= __('payment_method') ?></label>
|
||||
<select name="payment_method" class="form-select bg-light border-0" style="border-radius: 12px;">
|
||||
<option value="cash"><?= __('cash') ?></option>
|
||||
<option value="card"><?= __('card') ?></option>
|
||||
<option value="transfer"><?= __('transfer') ?></option>
|
||||
</select>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-success w-100 py-2" style="border-radius: 12px;"><?= __('add_payment') ?></button>
|
||||
<button type="submit" class="btn btn-success w-100 py-3 fw-bold shadow-sm" style="border-radius: 15px;"><?= __('add_payment') ?></button>
|
||||
</form>
|
||||
<?php endif; ?>
|
||||
<button class="btn btn-outline-dark w-100 mt-3 py-2" style="border-radius: 12px;" onclick="window.print()">
|
||||
<i class="bi bi-printer me-1"></i> <?= __('print_invoice') ?>
|
||||
|
||||
<button class="btn btn-outline-dark w-100 mt-4 py-3 fw-bold shadow-sm" style="border-radius: 15px;" onclick="window.print()">
|
||||
<i class="bi bi-printer me-2"></i> <?= __('print_invoice') ?>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
@ -234,4 +235,4 @@ function getStatusColor($status) {
|
||||
][$status] ?? 'info';
|
||||
}
|
||||
require_once __DIR__ . '/includes/footer.php';
|
||||
?>
|
||||
?>
|
||||
75
pos.php
75
pos.php
@ -16,12 +16,10 @@ $stmt->execute();
|
||||
$items_raw = $stmt->fetchAll();
|
||||
|
||||
// Get all services and prices for this branch
|
||||
$stmt = db()->prepare("SELECT p.item_id, p.variant_id, p.service_id, p.price,
|
||||
s.name_en as service_en, s.name_ar as service_ar,
|
||||
v.name_en as variant_en, v.name_ar as variant_ar
|
||||
$stmt = db()->prepare("SELECT p.item_id, p.service_id, p.price,
|
||||
s.name_en as service_en, s.name_ar as service_ar
|
||||
FROM prices p
|
||||
JOIN services s ON p.service_id = s.id
|
||||
LEFT JOIN item_variants v ON p.variant_id = v.id
|
||||
WHERE p.branch_id = ?");
|
||||
$stmt->execute([$branch_id]);
|
||||
$all_prices = $stmt->fetchAll();
|
||||
@ -35,37 +33,19 @@ foreach ($items_raw as $i) {
|
||||
'category_id' => $i['category_id'],
|
||||
'image_url' => $i['image_url'],
|
||||
'vat_percent' => (float)$i['vat_percent'],
|
||||
'variants' => [],
|
||||
'default_services' => []
|
||||
'services' => []
|
||||
];
|
||||
}
|
||||
|
||||
foreach ($all_prices as $p) {
|
||||
if (!isset($items[$p['item_id']])) continue;
|
||||
|
||||
if ($p['variant_id']) {
|
||||
if (!isset($items[$p['item_id']]['variants'][$p['variant_id']])) {
|
||||
$items[$p['item_id']]['variants'][$p['variant_id']] = [
|
||||
'id' => $p['variant_id'],
|
||||
'name_en' => $p['variant_en'],
|
||||
'name_ar' => $p['variant_ar'],
|
||||
'services' => []
|
||||
];
|
||||
}
|
||||
$items[$p['item_id']]['variants'][$p['variant_id']]['services'][] = [
|
||||
'id' => $p['service_id'],
|
||||
'name_en' => $p['service_en'],
|
||||
'name_ar' => $p['service_ar'],
|
||||
'price' => (float)$p['price']
|
||||
];
|
||||
} else {
|
||||
$items[$p['item_id']]['default_services'][] = [
|
||||
'id' => $p['service_id'],
|
||||
'name_en' => $p['service_en'],
|
||||
'name_ar' => $p['service_ar'],
|
||||
'price' => (float)$p['price']
|
||||
];
|
||||
}
|
||||
$items[$p['item_id']]['services'][] = [
|
||||
'id' => $p['service_id'],
|
||||
'name_en' => $p['service_en'],
|
||||
'name_ar' => $p['service_ar'],
|
||||
'price' => (float)$p['price']
|
||||
];
|
||||
}
|
||||
|
||||
// Get all customers for this branch
|
||||
@ -99,7 +79,7 @@ $customers = $stmt->fetchAll();
|
||||
|
||||
<div class="row g-3" id="itemsList">
|
||||
<?php foreach($items as $item): ?>
|
||||
<?php if (empty($item['default_services']) && empty($item['variants'])) continue; ?>
|
||||
<?php if (empty($item['services'])) continue; ?>
|
||||
<div class="col-md-4 col-sm-6 item-card-wrapper"
|
||||
data-cat="<?= $item['category_id'] ?>"
|
||||
data-name-en="<?= strtolower($item['name_en']) ?>"
|
||||
@ -119,7 +99,7 @@ $customers = $stmt->fetchAll();
|
||||
</div>
|
||||
<div class="card-body p-3 text-center">
|
||||
<div class="fw-bold fs-6"><?= $lang === 'ar' ? $item['name_ar'] : $item['name_en'] ?></div>
|
||||
<small class="text-muted d-block mt-1"><?= count($item['default_services']) + count($item['variants']) ?> <?= __('options') ?? 'Options' ?></small>
|
||||
<small class="text-muted d-block mt-1"><?= count($item['services']) ?> <?= __('services') ?></small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -187,7 +167,7 @@ $customers = $stmt->fetchAll();
|
||||
<div class="modal-header border-0 pb-0 p-4">
|
||||
<div>
|
||||
<h5 class="modal-title fw-bold" id="selectionItemName"></h5>
|
||||
<p class="text-muted small m-0"><?= __('select_service_option') ?? 'Select service type' ?></p>
|
||||
<p class="text-muted small m-0"><?= __('select_service') ?? 'Select service type' ?></p>
|
||||
</div>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
||||
</div>
|
||||
@ -245,43 +225,30 @@ function showOptions(itemId) {
|
||||
const optionsList = document.getElementById('optionsList');
|
||||
optionsList.innerHTML = '';
|
||||
|
||||
// 1. Add Default Services
|
||||
item.default_services.forEach(service => {
|
||||
addOptionButton(item, null, service);
|
||||
});
|
||||
|
||||
// 2. Add Variant Services
|
||||
Object.values(item.variants).forEach(variant => {
|
||||
variant.services.forEach(service => {
|
||||
addOptionButton(item, variant, service);
|
||||
});
|
||||
item.services.forEach(service => {
|
||||
addOptionButton(item, service);
|
||||
});
|
||||
|
||||
selectionModal.show();
|
||||
}
|
||||
|
||||
function addOptionButton(item, variant, service) {
|
||||
function addOptionButton(item, service) {
|
||||
const optionsList = document.getElementById('optionsList');
|
||||
const btn = document.createElement('button');
|
||||
btn.className = 'list-group-item list-group-item-action d-flex justify-content-between align-items-center border-0 py-3 mb-2 rounded-4 bg-light shadow-sm-hover transition';
|
||||
|
||||
let variantText = variant ? (lang === 'ar' ? variant.name_ar : variant.name_en) : '';
|
||||
let serviceText = lang === 'ar' ? service.name_ar : service.name_en;
|
||||
|
||||
btn.innerHTML = `
|
||||
<div>
|
||||
${variantText ? `<div class="badge bg-primary text-white mb-1 small rounded-pill px-2" style="font-size: 0.7rem;">${variantText}</div>` : ''}
|
||||
<div class="fw-bold">${serviceText}</div>
|
||||
</div>
|
||||
<div class="fw-bold">${serviceText}</div>
|
||||
<div class="text-primary fw-bold fs-5">${service.price.toFixed(2)} <small style="font-size: 0.8rem;">SAR</small></div>
|
||||
`;
|
||||
btn.onclick = () => addToCart(item, variant, service);
|
||||
btn.onclick = () => addToCart(item, service);
|
||||
optionsList.appendChild(btn);
|
||||
}
|
||||
|
||||
function addToCart(item, variant, service) {
|
||||
const variantId = variant ? variant.id : null;
|
||||
const cartItemId = `${item.id}-${variantId}-${service.id}`;
|
||||
function addToCart(item, service) {
|
||||
const cartItemId = `${item.id}-${service.id}`;
|
||||
const existing = cart.find(i => i.cartItemId === cartItemId);
|
||||
|
||||
const vatPercent = item.vat_percent || 0;
|
||||
@ -293,10 +260,8 @@ function addToCart(item, variant, service) {
|
||||
cart.push({
|
||||
cartItemId,
|
||||
itemId: item.id,
|
||||
variantId: variantId,
|
||||
serviceId: service.id,
|
||||
itemName: lang === 'ar' ? item.name_ar : item.name_en,
|
||||
variantName: variant ? (lang === 'ar' ? variant.name_ar : variant.name_en) : null,
|
||||
serviceName: lang === 'ar' ? service.name_ar : service.name_en,
|
||||
price: service.price,
|
||||
vatPercent: vatPercent,
|
||||
@ -325,7 +290,7 @@ function updateCart() {
|
||||
row.className = 'cart-item-row d-flex justify-content-between align-items-center mb-3 p-3 bg-white border rounded-4 shadow-sm';
|
||||
row.innerHTML = `
|
||||
<div style="flex: 1;">
|
||||
<div class="fw-bold small">${item.itemName}${item.variantName ? ' <span class="badge bg-soft-primary text-primary mx-1" style="font-size: 0.65rem;">' + item.variantName + '</span>' : ''}</div>
|
||||
<div class="fw-bold small">${item.itemName}</div>
|
||||
<div class="text-muted" style="font-size: 0.75rem;">${item.serviceName}</div>
|
||||
</div>
|
||||
<div class="d-flex align-items-center mx-3 bg-light rounded-pill px-2 py-1">
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user