feat: setup items, categories, and suppliers database tables with real demo data and images from pexels
This commit is contained in:
parent
ccaa56bcff
commit
033b73cd60
@ -136,4 +136,19 @@ body.auth-body {
|
||||
/* Sidebar Sub-menu */
|
||||
[data-bs-toggle="collapse"][aria-expanded="true"] .toggle-icon {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
}
|
||||
/* Fix for btn-close in modal-header */
|
||||
.modal-header {
|
||||
position: relative;
|
||||
}
|
||||
.modal-header .btn-close {
|
||||
margin: 0;
|
||||
position: absolute;
|
||||
top: 1rem;
|
||||
}
|
||||
[dir="rtl"] .modal-header .btn-close {
|
||||
left: 1rem;
|
||||
}
|
||||
[dir="ltr"] .modal-header .btn-close {
|
||||
right: 1rem;
|
||||
}
|
||||
|
||||
BIN
assets/images/items/18311171.jpg
Normal file
BIN
assets/images/items/18311171.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 9.4 KiB |
BIN
assets/images/items/18641665.jpg
Normal file
BIN
assets/images/items/18641665.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.9 KiB |
BIN
assets/images/items/2537658.jpg
Normal file
BIN
assets/images/items/2537658.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 14 KiB |
BIN
assets/images/items/29765806.jpg
Normal file
BIN
assets/images/items/29765806.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 9.3 KiB |
BIN
assets/images/items/9058886.jpg
Normal file
BIN
assets/images/items/9058886.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 7.4 KiB |
5
cookies.txt
Normal file
5
cookies.txt
Normal file
@ -0,0 +1,5 @@
|
||||
# Netscape HTTP Cookie File
|
||||
# https://curl.se/docs/http-cookies.html
|
||||
# This file was generated by libcurl! Edit at your own risk.
|
||||
|
||||
127.0.0.1 FALSE / FALSE 0 PHPSESSID b0jh7ohno1tnaa8tkh48odf595
|
||||
36
db_seed.php
Normal file
36
db_seed.php
Normal file
@ -0,0 +1,36 @@
|
||||
<?php
|
||||
require 'db/config.php';
|
||||
$db = db();
|
||||
|
||||
// 1. Create items table
|
||||
$db->exec("
|
||||
CREATE TABLE IF NOT EXISTS items (
|
||||
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
|
||||
sku VARCHAR(50) NOT NULL UNIQUE,
|
||||
name VARCHAR(200) NOT NULL,
|
||||
price DECIMAL(10,3) NOT NULL,
|
||||
base_stock INT NOT NULL DEFAULT 0,
|
||||
vat DECIMAL(5,3) NOT NULL DEFAULT 5.000,
|
||||
category_id INT UNSIGNED NULL,
|
||||
supplier_id INT UNSIGNED NULL,
|
||||
image_url VARCHAR(255) NULL,
|
||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (category_id) REFERENCES categories(id) ON DELETE SET NULL,
|
||||
FOREIGN KEY (supplier_id) REFERENCES suppliers(id) ON DELETE SET NULL
|
||||
);
|
||||
");
|
||||
|
||||
// 2. Insert Categories
|
||||
$db->exec("INSERT IGNORE INTO categories (id, name_ar, name_en) VALUES
|
||||
(1, 'إلكترونيات', 'Electronics'),
|
||||
(2, 'إكسسوارات', 'Accessories'),
|
||||
(3, 'ملابس', 'Clothing');");
|
||||
|
||||
// 3. Insert Suppliers
|
||||
$db->exec("INSERT IGNORE INTO suppliers (id, name, contact_person, phone) VALUES
|
||||
(1, 'TechCorp', 'John Doe', '123456789'),
|
||||
(2, 'ElectroWholesale', 'Jane Smith', '987654321'),
|
||||
(3, 'StyleCo', 'Mike Johnson', '555666777');");
|
||||
|
||||
echo "Database schema and base entities created.\n";
|
||||
|
||||
@ -193,14 +193,30 @@ function can_access_branch(string $branchCode): bool
|
||||
|
||||
function catalog(): array
|
||||
{
|
||||
return [
|
||||
'baklava_box' => ['sku' => 'baklava_box', 'name_ar' => 'بقلاوة مشكلة', 'name_en' => 'Mixed Baklava Box', 'price' => 18.50, 'base_stock' => 72, 'unit_ar' => 'علبة', 'unit_en' => 'box'],
|
||||
'date_truffles' => ['sku' => 'date_truffles', 'name_ar' => 'ترافل التمر', 'name_en' => 'Date Truffles', 'price' => 9.25, 'base_stock' => 120, 'unit_ar' => 'علبة', 'unit_en' => 'box'],
|
||||
'saffron_maamoul' => ['sku' => 'saffron_maamoul', 'name_ar' => 'معمول الزعفران', 'name_en' => 'Saffron Maamoul', 'price' => 7.80, 'base_stock' => 88, 'unit_ar' => 'صندوق', 'unit_en' => 'pack'],
|
||||
'pistachio_bites' => ['sku' => 'pistachio_bites', 'name_ar' => 'لقيمات الفستق', 'name_en' => 'Pistachio Bites', 'price' => 11.40, 'base_stock' => 64, 'unit_ar' => 'علبة', 'unit_en' => 'box'],
|
||||
'halwa_classic' => ['sku' => 'halwa_classic', 'name_ar' => 'حلوى عمانية كلاسيك', 'name_en' => 'Classic Omani Halwa', 'price' => 6.20, 'base_stock' => 150, 'unit_ar' => 'عبوة', 'unit_en' => 'jar'],
|
||||
'gift_tin' => ['sku' => 'gift_tin', 'name_ar' => 'علبة هدايا فاخرة', 'name_en' => 'Premium Gift Tin', 'price' => 24.00, 'base_stock' => 36, 'unit_ar' => 'علبة', 'unit_en' => 'tin'],
|
||||
];
|
||||
try {
|
||||
$db = db();
|
||||
$stmt = $db->query("SELECT * FROM items");
|
||||
$items = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
$catalog = [];
|
||||
foreach ($items as $item) {
|
||||
$catalog[$item["sku"]] = [
|
||||
"sku" => $item["sku"],
|
||||
"name_ar" => $item["name"],
|
||||
"name_en" => $item["name"],
|
||||
"price" => (float)$item["price"],
|
||||
"base_stock" => (int)$item["base_stock"],
|
||||
"vat" => (float)$item["vat"],
|
||||
"category_id" => $item["category_id"],
|
||||
"supplier_id" => $item["supplier_id"],
|
||||
"image_url" => $item["image_url"],
|
||||
"unit_ar" => "قطعة",
|
||||
"unit_en" => "pcs"
|
||||
];
|
||||
}
|
||||
return $catalog;
|
||||
} catch (Throwable $e) {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
function product_label(string $sku): string
|
||||
@ -210,12 +226,13 @@ function product_label(string $sku): string
|
||||
return $sku;
|
||||
}
|
||||
|
||||
return current_lang() === 'ar' ? $item['name_ar'] : $item['name_en'];
|
||||
return current_lang() === "ar" ? $item["name_ar"] : $item["name_en"];
|
||||
}
|
||||
|
||||
|
||||
function currency(float $amount): string
|
||||
{
|
||||
return number_format($amount, 2) . ' ' . tr('ر.ع', 'OMR');
|
||||
return number_format($amount, 3) . ' ' . tr('ر.ع', 'OMR');
|
||||
}
|
||||
|
||||
function sale_mode_label(string $mode): string
|
||||
@ -440,7 +457,11 @@ function stock_snapshot(): array
|
||||
'base_stock' => $base,
|
||||
'sold' => $used,
|
||||
'available' => max(0, $base - $used),
|
||||
'price' => (float) $item['price'],
|
||||
'price' => $item['price'],
|
||||
'category_id' => $item['category_id'],
|
||||
'supplier_id' => $item['supplier_id'],
|
||||
'image_url' => $item['image_url'],
|
||||
'vat' => $item['vat'],
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
25
includes/pexels.php
Normal file
25
includes/pexels.php
Normal file
@ -0,0 +1,25 @@
|
||||
<?php
|
||||
function pexels_key() {
|
||||
$k = getenv('PEXELS_KEY');
|
||||
return $k && strlen($k) > 0 ? $k : 'Vc99rnmOhHhJAbgGQoKLZtsaIVfkeownoQNbTj78VemUjKh08ZYRbf18';
|
||||
}
|
||||
function pexels_get($url) {
|
||||
$ch = curl_init();
|
||||
curl_setopt_array($ch, [
|
||||
CURLOPT_URL => $url,
|
||||
CURLOPT_RETURNTRANSFER => true,
|
||||
CURLOPT_HTTPHEADER => [ 'Authorization: '. pexels_key() ],
|
||||
CURLOPT_TIMEOUT => 15,
|
||||
]);
|
||||
$resp = curl_exec($ch);
|
||||
$code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||
curl_close($ch);
|
||||
if ($code >= 200 && $code < 300 && $resp) return json_decode($resp, true);
|
||||
return null;
|
||||
}
|
||||
function download_to($srcUrl, $destPath) {
|
||||
$data = file_get_contents($srcUrl);
|
||||
if ($data === false) return false;
|
||||
if (!is_dir(dirname($destPath))) mkdir(dirname($destPath), 0775, true);
|
||||
return file_put_contents($destPath, $data) !== false;
|
||||
}
|
||||
17
patch_app.php
Normal file
17
patch_app.php
Normal file
@ -0,0 +1,17 @@
|
||||
<?php
|
||||
$content = file_get_contents('includes/app.php');
|
||||
$content = str_replace(
|
||||
'available' => max(0, $base - $used),
|
||||
'price' => $item['price']
|
||||
,
|
||||
'available' => max(0, $base - $used),
|
||||
'price' => $item['price'],
|
||||
'category_id' => $item['category_id'],
|
||||
'supplier_id' => $item['supplier_id'],
|
||||
'image_url' => $item['image_url'],
|
||||
'vat' => $item['vat']
|
||||
,
|
||||
$content
|
||||
);
|
||||
file_put_contents('includes/app.php', $content);
|
||||
|
||||
19
patch_modal.php
Normal file
19
patch_modal.php
Normal file
@ -0,0 +1,19 @@
|
||||
<?php
|
||||
$content = file_get_contents('stock.php');
|
||||
$content = str_replace(
|
||||
"function openItemModal(sku = '', name = '', price = '', base_stock = '') {",
|
||||
"function openItemModal(sku = '', name = '', price = '', base_stock = '', vat = '5', category_id = '', supplier_id = '', image_url = '') {",
|
||||
$content
|
||||
);
|
||||
$content = str_replace(
|
||||
"document.getElementById('item_vat').value = '5';",
|
||||
"document.getElementById('item_vat').value = vat;\n document.getElementById('item_category').value = category_id;\n document.getElementById('item_supplier').value = supplier_id;\n \n // Remove old image preview if any\n const oldPreview = document.getElementById('image_preview');\n if (oldPreview) oldPreview.remove();\n \n if (image_url) {\n const preview = document.createElement('img');\n preview.id = 'image_preview';\n preview.src = image_url;\n preview.style.maxHeight = '100px';\n preview.className = 'mt-2 rounded';\n document.getElementById('item_picture').parentElement.appendChild(preview);\n }",
|
||||
$content
|
||||
);
|
||||
$content = str_replace(
|
||||
"document.getElementById('item_category').value = '';\n document.getElementById('item_supplier').value = '';",
|
||||
"",
|
||||
$content
|
||||
);
|
||||
file_put_contents('stock.php', $content);
|
||||
|
||||
4
patch_table.php
Normal file
4
patch_table.php
Normal file
@ -0,0 +1,4 @@
|
||||
<?php
|
||||
$content = file_get_contents('stock.php');
|
||||
$content = preg_replace('/(\s*)<td><\?= h\(\$row[\'name\']\) \?><\/td>/', "$1<td>\n$1 <?php if (!empty(\$row['image_url'])): ?>\n$1 <img src=\"<?= h(\$row['image_url']) ?>\" alt=\"\" class=\"rounded\" style=\"width: 40px; height: 40px; object-fit: cover;\">\n$1 <?php else: ?>\n$1 <div class=\"bg-light rounded d-flex align-items-center justify-content-center text-muted\" style=\"width: 40px; height: 40px;\"><i class=\"bi bi-image\"></i></div>\n$1 <?php endif; ?>\n$1</td>\n$1<td><?= h(\$row['name']) ?></td>", $content);
|
||||
file_put_contents('stock.php', $content);
|
||||
@ -10,11 +10,11 @@ $allPurchases = purchase_pipeline();
|
||||
$search = $_GET['q'] ?? '';
|
||||
$filteredPurchases = [];
|
||||
if ($search) {
|
||||
$lowerSearch = mb_strtolower($search);
|
||||
$lowerSearch = strtolower($search);
|
||||
foreach ($allPurchases as $key => $row) {
|
||||
if (
|
||||
str_contains(mb_strtolower($row['supplier']), $lowerSearch) ||
|
||||
str_contains(mb_strtolower($row['reference']), $lowerSearch)
|
||||
str_contains(strtolower((string)$row['supplier']), $lowerSearch) ||
|
||||
str_contains(strtolower((string)$row['reference']), $lowerSearch)
|
||||
) {
|
||||
$filteredPurchases[$key] = $row;
|
||||
}
|
||||
|
||||
61
seed_items.php
Normal file
61
seed_items.php
Normal file
@ -0,0 +1,61 @@
|
||||
<?php
|
||||
require 'db/config.php';
|
||||
require 'includes/pexels.php';
|
||||
|
||||
$db = db();
|
||||
|
||||
// Define items to insert
|
||||
$items = [
|
||||
['sku' => '10000001', 'name' => 'Laptop Pro 15', 'price' => 1200.000, 'base_stock' => 10, 'category_id' => 1, 'supplier_id' => 1, 'query' => 'laptop'],
|
||||
['sku' => '10000002', 'name' => 'Wireless Mouse', 'price' => 25.500, 'base_stock' => 50, 'category_id' => 2, 'supplier_id' => 2, 'query' => 'computer mouse'],
|
||||
['sku' => '10000003', 'name' => 'Mechanical Keyboard', 'price' => 85.000, 'base_stock' => 30, 'category_id' => 2, 'supplier_id' => 1, 'query' => 'keyboard'],
|
||||
['sku' => '10000004', 'name' => 'USB-C Hub', 'price' => 40.000, 'base_stock' => 100, 'category_id' => 2, 'supplier_id' => 2, 'query' => 'usb cable'],
|
||||
['sku' => '10000005', 'name' => 'Cotton T-Shirt', 'price' => 15.000, 'base_stock' => 200, 'category_id' => 3, 'supplier_id' => 3, 'query' => 't-shirt'],
|
||||
];
|
||||
|
||||
foreach ($items as $item) {
|
||||
// Check if sku already exists
|
||||
$stmt = $db->prepare("SELECT id FROM items WHERE sku = ?");
|
||||
$stmt->execute([$item['sku']]);
|
||||
if ($stmt->fetch()) {
|
||||
echo "SKU {" . $item['sku'] . "} already exists.\n";
|
||||
continue;
|
||||
}
|
||||
|
||||
$imageUrl = null;
|
||||
$localImagePath = null;
|
||||
|
||||
// Fetch image from pexels
|
||||
$url = 'https://api.pexels.com/v1/search?query=' . urlencode($item['query']) . '&orientation=square&per_page=1&page=1';
|
||||
$data = pexels_get($url);
|
||||
if ($data && !empty($data['photos'])) {
|
||||
$photo = $data['photos'][0];
|
||||
$src = $photo['src']['medium'] ?? ($photo['src']['original'] ?? null);
|
||||
if ($src) {
|
||||
$dest = __DIR__ . '/assets/images/items/' . $photo['id'] . '.jpg';
|
||||
if (download_to($src, $dest)) {
|
||||
$localImagePath = 'assets/images/items/' . $photo['id'] . '.jpg';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!$localImagePath) {
|
||||
$localImagePath = 'https://picsum.photos/400?random=' . rand(1, 1000); // fallback
|
||||
}
|
||||
|
||||
$stmt = $db->prepare("INSERT INTO items (sku, name, price, base_stock, vat, category_id, supplier_id, image_url) VALUES (?, ?, ?, ?, ?, ?, ?, ?)");
|
||||
$stmt->execute([
|
||||
$item['sku'],
|
||||
$item['name'],
|
||||
$item['price'],
|
||||
$item['base_stock'],
|
||||
5.000, // default VAT
|
||||
$item['category_id'],
|
||||
$item['supplier_id'],
|
||||
$localImagePath
|
||||
]);
|
||||
echo "Inserted {" . $item['name'] . "}\n";
|
||||
}
|
||||
|
||||
echo "Done seeding items.\n";
|
||||
|
||||
89
stock.php
89
stock.php
@ -22,21 +22,23 @@ try {
|
||||
// Ignore if not present
|
||||
}
|
||||
|
||||
// Search logic
|
||||
// Search and filter logic
|
||||
$search = $_GET['q'] ?? '';
|
||||
$catFilter = $_GET['category'] ?? '';
|
||||
$supFilter = $_GET['supplier'] ?? '';
|
||||
$filteredStock = [];
|
||||
if ($search && empty($dbError)) {
|
||||
$lowerSearch = mb_strtolower($search);
|
||||
|
||||
if (empty($dbError)) {
|
||||
$lowerSearch = strtolower($search);
|
||||
foreach ($allStock as $key => $row) {
|
||||
if (
|
||||
str_contains(mb_strtolower($row['sku']), $lowerSearch) ||
|
||||
str_contains(mb_strtolower($row['name']), $lowerSearch)
|
||||
) {
|
||||
$matchSearch = !$search || str_contains(strtolower((string)$row['sku']), $lowerSearch) || str_contains(strtolower((string)$row['name']), $lowerSearch);
|
||||
$matchCat = !$catFilter || (isset($row['category_id']) && $row['category_id'] == $catFilter);
|
||||
$matchSup = !$supFilter || (isset($row['supplier_id']) && $row['supplier_id'] == $supFilter);
|
||||
|
||||
if ($matchSearch && $matchCat && $matchSup) {
|
||||
$filteredStock[$key] = $row;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$filteredStock = $allStock;
|
||||
}
|
||||
|
||||
// Pagination logic
|
||||
@ -63,10 +65,32 @@ require __DIR__ . '/includes/header.php';
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<form class="d-flex mb-3" method="GET" action="stock.php">
|
||||
<div class="input-group" style="max-width: 400px;">
|
||||
<input type="text" name="q" class="form-control" placeholder="<?= h(tr('بحث برمز الصنف أو الاسم...', 'Search by SKU or name...')) ?>" value="<?= h($search) ?>">
|
||||
<button class="btn btn-outline-secondary" type="submit"><i class="bi bi-search"></i></button>
|
||||
<form class="mb-4" method="GET" action="stock.php">
|
||||
<div class="row g-2">
|
||||
<div class="col-md-4">
|
||||
<input type="text" name="q" class="form-control" placeholder="<?= h(tr('بحث برمز الصنف أو الاسم...', 'Search by SKU or name...')) ?>" value="<?= h($search) ?>">
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<select name="category" class="form-select">
|
||||
<option value=""><?= h(tr('الكل (التصنيف)', 'All Categories')) ?></option>
|
||||
<?php foreach($categories as $cat): ?>
|
||||
<option value="<?= h($cat['id']) ?>" <?= ($catFilter == $cat['id']) ? 'selected' : '' ?>><?= h(current_lang() === 'ar' ? $cat['name_ar'] : $cat['name_en']) ?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<select name="supplier" class="form-select">
|
||||
<option value=""><?= h(tr('الكل (المورد)', 'All Suppliers')) ?></option>
|
||||
<?php foreach($suppliers as $sup): ?>
|
||||
<option value="<?= h($sup['id']) ?>" <?= ($supFilter == $sup['id']) ? 'selected' : '' ?>><?= h($sup['name']) ?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-2">
|
||||
<button class="btn btn-primary w-100" type="submit">
|
||||
<i class="bi bi-funnel"></i> <?= h(tr('تصفية', 'Filter')) ?>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</section>
|
||||
@ -77,9 +101,10 @@ require __DIR__ . '/includes/header.php';
|
||||
<?php else: ?>
|
||||
<div class="table-responsive">
|
||||
<table class="table app-table align-middle mb-0">
|
||||
<thead>
|
||||
<thead class="table-primary">
|
||||
<tr>
|
||||
<th>SKU</th>
|
||||
<th width="60"><?= h(tr('صورة', 'Pic')) ?></th>
|
||||
<th><?= h(tr('الصنف', 'Product')) ?></th>
|
||||
<th><?= h(tr('السعر', 'Price')) ?></th>
|
||||
<th><?= h(tr('افتتاحي', 'Opening')) ?></th>
|
||||
@ -109,7 +134,7 @@ require __DIR__ . '/includes/header.php';
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
<td class="text-end">
|
||||
<button class="btn btn-sm btn-light text-primary border" onclick="openItemModal('<?= h($row['sku']) ?>', '<?= h(addslashes($row['name'])) ?>', '<?= h($row['price']) ?>', '<?= h($row['base_stock']) ?>')" data-bs-toggle="tooltip" title="<?= h(tr('تعديل', 'Edit')) ?>">
|
||||
<button class="btn btn-sm btn-light text-primary border" onclick="openItemModal('<?= h($row['sku']) ?>', '<?= h(addslashes($row['name'])) ?>', '<?= h($row['price']) ?>', '<?= h($row['base_stock']) ?>', '<?= h($row['vat'] ?? 5) ?>', '<?= h($row['category_id'] ?? '') ?>', '<?= h($row['supplier_id'] ?? '') ?>', '<?= h($row['image_url'] ?? '') ?>')" data-bs-toggle="tooltip" title="<?= h(tr('تعديل', 'Edit')) ?>">
|
||||
<i class="bi bi-pencil"></i>
|
||||
</button>
|
||||
<button class="btn btn-sm btn-light text-danger border" onclick="mockDelete()" data-bs-toggle="tooltip" title="<?= h(tr('حذف', 'Delete')) ?>">
|
||||
@ -127,7 +152,7 @@ require __DIR__ . '/includes/header.php';
|
||||
<ul class="pagination justify-content-center mb-0">
|
||||
<?php for($i=1; $i<=$totalPages; $i++): ?>
|
||||
<li class="page-item <?= $i === $page ? 'active' : '' ?>">
|
||||
<a class="page-link" href="<?= h(url_for('stock.php', ['p' => $i, 'q' => $search])) ?>"><?= $i ?></a>
|
||||
<a class="page-link" href="<?= h(url_for('stock.php', ['p' => $i, 'q' => $search, 'category' => $catFilter, 'supplier' => $supFilter])) ?>"><?= $i ?></a>
|
||||
</li>
|
||||
<?php endfor; ?>
|
||||
</ul>
|
||||
@ -141,9 +166,9 @@ require __DIR__ . '/includes/header.php';
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<form onsubmit="handleItemSubmit(event)">
|
||||
<div class="modal-header">
|
||||
<div class="modal-header bg-primary text-white ">
|
||||
<h5 class="modal-title" id="itemModalLabel"><?= h(tr('إضافة / تعديل صنف', 'Add / Edit Item')) ?></h5>
|
||||
<button type="button" class="btn-close" 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 class="modal-body">
|
||||
<div class="mb-3 text-center">
|
||||
@ -166,7 +191,7 @@ require __DIR__ . '/includes/header.php';
|
||||
<div class="row mb-3">
|
||||
<div class="col-4">
|
||||
<label class="form-label"><?= h(tr('السعر', 'Price')) ?></label>
|
||||
<input type="number" step="0.01" class="form-control" id="item_price" required>
|
||||
<input type="number" step="0.001" class="form-control" id="item_price" required>
|
||||
</div>
|
||||
<div class="col-4">
|
||||
<label class="form-label"><?= h(tr('الرصيد الافتتاحي', 'Opening Stock')) ?></label>
|
||||
@ -174,7 +199,7 @@ require __DIR__ . '/includes/header.php';
|
||||
</div>
|
||||
<div class="col-4">
|
||||
<label class="form-label"><?= h(tr('الضريبة (VAT %)', 'VAT %')) ?></label>
|
||||
<input type="number" step="0.01" class="form-control" id="item_vat" value="5" required>
|
||||
<input type="number" step="0.001" class="form-control" id="item_vat" value="5" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
@ -227,15 +252,29 @@ document.addEventListener('DOMContentLoaded', function () {
|
||||
itemModalObj = new bootstrap.Modal(document.getElementById('itemModal'));
|
||||
});
|
||||
|
||||
function openItemModal(sku = '', name = '', price = '', base_stock = '') {
|
||||
function openItemModal(sku = '', name = '', price = '', base_stock = '', vat = '5', category_id = '', supplier_id = '', image_url = '') {
|
||||
document.getElementById('item_sku').value = sku;
|
||||
document.getElementById('item_name').value = name;
|
||||
document.getElementById('item_price').value = price;
|
||||
document.getElementById('item_base_stock').value = base_stock;
|
||||
document.getElementById('item_vat').value = '5';
|
||||
document.getElementById('item_vat').value = vat;
|
||||
document.getElementById('item_category').value = category_id;
|
||||
document.getElementById('item_supplier').value = supplier_id;
|
||||
|
||||
// Remove old image preview if any
|
||||
const oldPreview = document.getElementById('image_preview');
|
||||
if (oldPreview) oldPreview.remove();
|
||||
|
||||
if (image_url) {
|
||||
const preview = document.createElement('img');
|
||||
preview.id = 'image_preview';
|
||||
preview.src = image_url;
|
||||
preview.style.maxHeight = '100px';
|
||||
preview.className = 'mt-2 rounded';
|
||||
document.getElementById('item_picture').parentElement.appendChild(preview);
|
||||
}
|
||||
document.getElementById('item_picture').value = '';
|
||||
document.getElementById('item_category').value = '';
|
||||
document.getElementById('item_supplier').value = '';
|
||||
|
||||
|
||||
itemModalObj.show();
|
||||
}
|
||||
@ -273,4 +312,4 @@ function mockDelete() {
|
||||
}
|
||||
</script>
|
||||
|
||||
<?php require __DIR__ . '/includes/footer.php'; ?>
|
||||
<?php require __DIR__ . '/includes/footer.php'; ?>
|
||||
@ -10,12 +10,12 @@ $allAccounts = demo_users();
|
||||
$search = $_GET['q'] ?? '';
|
||||
$filteredAccounts = [];
|
||||
if ($search) {
|
||||
$lowerSearch = mb_strtolower($search);
|
||||
$lowerSearch = strtolower($search);
|
||||
foreach ($allAccounts as $key => $acc) {
|
||||
if (
|
||||
str_contains(mb_strtolower($acc['name_ar']), $lowerSearch) ||
|
||||
str_contains(mb_strtolower($acc['name_en']), $lowerSearch) ||
|
||||
str_contains(mb_strtolower($acc['username']), $lowerSearch)
|
||||
str_contains(strtolower((string)$acc['name_ar']), $lowerSearch) ||
|
||||
str_contains(strtolower((string)$acc['name_en']), $lowerSearch) ||
|
||||
str_contains(strtolower((string)$acc['username']), $lowerSearch)
|
||||
) {
|
||||
$filteredAccounts[$key] = $acc;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user