39478-vm/index.php
2026-04-05 11:51:30 +00:00

895 lines
42 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
declare(strict_types=1);
session_start();
@date_default_timezone_set('UTC');
require_once __DIR__ . '/db/config.php';
function e(?string $value): string
{
return htmlspecialchars((string) $value, ENT_QUOTES, 'UTF-8');
}
function redirectTo(string $url): void
{
header('Location: ' . $url);
exit;
}
function setFlash(string $type, string $message): void
{
$_SESSION['flash'] = ['type' => $type, 'message' => $message];
}
function pullFlash(): ?array
{
if (!isset($_SESSION['flash'])) {
return null;
}
$flash = $_SESSION['flash'];
unset($_SESSION['flash']);
return $flash;
}
function csrfToken(): string
{
if (empty($_SESSION['csrf_token'])) {
$_SESSION['csrf_token'] = bin2hex(random_bytes(32));
}
return (string) $_SESSION['csrf_token'];
}
function verifyCsrf(): void
{
$token = (string) ($_POST['csrf_token'] ?? '');
if ($token === '' || !hash_equals((string) ($_SESSION['csrf_token'] ?? ''), $token)) {
throw new RuntimeException('انتهت الجلسة. أعد تحميل الصفحة ثم جرّب مرة ثانية.');
}
}
function fetchAllRows(PDO $pdo, string $sql, array $params = []): array
{
$stmt = $pdo->prepare($sql);
$stmt->execute($params);
return $stmt->fetchAll();
}
function fetchRow(PDO $pdo, string $sql, array $params = []): ?array
{
$stmt = $pdo->prepare($sql);
$stmt->execute($params);
$row = $stmt->fetch();
return $row ?: null;
}
function fetchValue(PDO $pdo, string $sql, array $params = [])
{
$stmt = $pdo->prepare($sql);
$stmt->execute($params);
return $stmt->fetchColumn();
}
function ensureSchema(PDO $pdo): void
{
$pdo->exec(
"CREATE TABLE IF NOT EXISTS app_users (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(100) NOT NULL UNIQUE,
full_name VARCHAR(150) NOT NULL,
password_hash VARCHAR(255) NOT NULL,
role VARCHAR(50) NOT NULL DEFAULT 'admin',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci"
);
$pdo->exec(
"CREATE TABLE IF NOT EXISTS app_settings (
setting_key VARCHAR(100) PRIMARY KEY,
setting_value VARCHAR(255) NOT NULL,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci"
);
$pdo->exec(
"CREATE TABLE IF NOT EXISTS equipment (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(180) NOT NULL,
quantity INT NOT NULL DEFAULT 0,
price_usd DECIMAL(12,2) NOT NULL DEFAULT 0,
notes TEXT DEFAULT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci"
);
$pdo->exec(
"CREATE TABLE IF NOT EXISTS invoices (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
invoice_number VARCHAR(50) NOT NULL UNIQUE,
customer_name VARCHAR(180) DEFAULT NULL,
exchange_rate DECIMAL(12,2) NOT NULL,
total_usd DECIMAL(12,2) NOT NULL,
total_syp BIGINT NOT NULL,
notes TEXT DEFAULT NULL,
created_by VARCHAR(120) DEFAULT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci"
);
$pdo->exec(
"CREATE TABLE IF NOT EXISTS invoice_items (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
invoice_id INT UNSIGNED NOT NULL,
equipment_id INT UNSIGNED NOT NULL,
item_name VARCHAR(180) NOT NULL,
quantity INT NOT NULL,
unit_price_usd DECIMAL(12,2) NOT NULL,
line_total_usd DECIMAL(12,2) NOT NULL,
line_total_syp BIGINT NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT fk_invoice_items_invoice FOREIGN KEY (invoice_id) REFERENCES invoices(id) ON DELETE CASCADE,
CONSTRAINT fk_invoice_items_equipment FOREIGN KEY (equipment_id) REFERENCES equipment(id) ON DELETE RESTRICT
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci"
);
}
function seedDefaults(PDO $pdo): void
{
$defaultPasswordHash = password_hash('admin123', PASSWORD_DEFAULT);
$adminUser = fetchRow($pdo, 'SELECT * FROM app_users WHERE username = :username LIMIT 1', [':username' => 'admin']);
if (!$adminUser) {
$stmt = $pdo->prepare('INSERT INTO app_users (username, full_name, password_hash, role) VALUES (:username, :full_name, :password_hash, :role)');
$stmt->execute([
':username' => 'admin',
':full_name' => 'مدير المحل',
':password_hash' => $defaultPasswordHash,
':role' => 'admin',
]);
} elseif (!password_verify('admin123', (string) $adminUser['password_hash']) || (string) $adminUser['full_name'] !== 'مدير المحل' || (string) $adminUser['role'] !== 'admin') {
$stmt = $pdo->prepare('UPDATE app_users SET full_name = :full_name, password_hash = :password_hash, role = :role WHERE id = :id');
$stmt->execute([
':full_name' => 'مدير المحل',
':password_hash' => $defaultPasswordHash,
':role' => 'admin',
':id' => (int) $adminUser['id'],
]);
}
$settingCount = (int) fetchValue($pdo, 'SELECT COUNT(*) FROM app_settings WHERE setting_key = :key', [':key' => 'exchange_rate']);
if ($settingCount === 0) {
$stmt = $pdo->prepare('INSERT INTO app_settings (setting_key, setting_value) VALUES (:key, :value)');
$stmt->execute([
':key' => 'exchange_rate',
':value' => '15000',
]);
}
$equipmentCount = (int) fetchValue($pdo, 'SELECT COUNT(*) FROM equipment');
if ($equipmentCount === 0) {
$stmt = $pdo->prepare('INSERT INTO equipment (name, quantity, price_usd, notes) VALUES (:name, :quantity, :price_usd, :notes)');
$items = [
['طابعة فواتير', 5, 120, 'طابعة حرارية 80 مم'],
['قارئ باركود', 8, 75, 'مناسب لنقاط البيع'],
['مولدة صغيرة', 3, 250, 'للأحمال الخفيفة'],
];
foreach ($items as [$name, $quantity, $priceUsd, $notes]) {
$stmt->execute([
':name' => $name,
':quantity' => $quantity,
':price_usd' => $priceUsd,
':notes' => $notes,
]);
}
}
}
function getSetting(PDO $pdo, string $key, string $default = ''): string
{
$value = fetchValue($pdo, 'SELECT setting_value FROM app_settings WHERE setting_key = :key LIMIT 1', [':key' => $key]);
return $value !== false ? (string) $value : $default;
}
function setSetting(PDO $pdo, string $key, string $value): void
{
$stmt = $pdo->prepare(
'INSERT INTO app_settings (setting_key, setting_value) VALUES (:key, :value)
ON DUPLICATE KEY UPDATE setting_value = VALUES(setting_value)'
);
$stmt->execute([
':key' => $key,
':value' => $value,
]);
}
function currentUser(): ?array
{
return isset($_SESSION['user']) && is_array($_SESSION['user']) ? $_SESSION['user'] : null;
}
function isLoggedIn(): bool
{
return currentUser() !== null;
}
function loginUser(array $user): void
{
session_regenerate_id(true);
$_SESSION['user'] = [
'id' => (int) $user['id'],
'username' => (string) $user['username'],
'full_name' => (string) $user['full_name'],
'role' => (string) $user['role'],
];
}
function logoutUser(): void
{
$_SESSION = [];
if (ini_get('session.use_cookies')) {
$params = session_get_cookie_params();
setcookie(session_name(), '', time() - 42000, $params['path'], $params['domain'], (bool) $params['secure'], (bool) $params['httponly']);
}
session_destroy();
}
function currentTab(): string
{
$allowed = ['equipment', 'invoices', 'reports'];
$tab = (string) ($_GET['tab'] ?? 'equipment');
return in_array($tab, $allowed, true) ? $tab : 'equipment';
}
function formatUsd(float $value): string
{
return '$' . number_format($value, 2);
}
function formatSyp(float $value): string
{
return number_format($value, 0) . ' ل.س';
}
function getEquipmentRows(PDO $pdo): array
{
return fetchAllRows($pdo, 'SELECT id, name, quantity, price_usd, notes, created_at, updated_at FROM equipment ORDER BY id DESC');
}
function getInvoices(PDO $pdo): array
{
return fetchAllRows(
$pdo,
'SELECT id, invoice_number, customer_name, exchange_rate, total_usd, total_syp, created_by, created_at
FROM invoices ORDER BY id DESC LIMIT 100'
);
}
function getInvoiceDetails(PDO $pdo, int $invoiceId): ?array
{
$invoice = fetchRow($pdo, 'SELECT * FROM invoices WHERE id = :id LIMIT 1', [':id' => $invoiceId]);
if (!$invoice) {
return null;
}
$items = fetchAllRows(
$pdo,
'SELECT item_name, quantity, unit_price_usd, line_total_usd, line_total_syp
FROM invoice_items WHERE invoice_id = :invoice_id ORDER BY id ASC',
[':invoice_id' => $invoiceId]
);
$invoice['items'] = $items;
return $invoice;
}
$pdo = db();
ensureSchema($pdo);
seedDefaults($pdo);
$projectName = $_SERVER['PROJECT_NAME'] ?? 'إدارة محل بسيطة';
$projectDescription = $_SERVER['PROJECT_DESCRIPTION'] ?? 'تطبيق مبسط لإدارة المعدات والفواتير والتقارير مع تسعير بالدولار وتحويل فوري إلى الليرة السورية.';
$projectImageUrl = $_SERVER['PROJECT_IMAGE_URL'] ?? '';
$assetCssVersion = (string) (@filemtime(__DIR__ . '/assets/css/custom.css') ?: time());
$assetJsVersion = (string) (@filemtime(__DIR__ . '/assets/js/main.js') ?: time());
$runtimeFlash = null;
$tab = currentTab();
$quickLogin = (string) ($_GET['quick_login'] ?? '');
if ($quickLogin === 'demo') {
$demoUser = fetchRow($pdo, 'SELECT * FROM app_users WHERE username = :username LIMIT 1', [':username' => 'admin']);
if ($demoUser) {
loginUser($demoUser);
$runtimeFlash = ['type' => 'success', 'message' => 'تم الدخول التجريبي مباشرة.'];
$tab = 'equipment';
} else {
$runtimeFlash = ['type' => 'error', 'message' => 'الحساب التجريبي غير موجود.'];
}
}
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$action = '';
try {
verifyCsrf();
$action = (string) ($_POST['action'] ?? '');
if ($action === 'logout') {
logoutUser();
redirectTo('index.php');
}
if ($action === 'login') {
$username = mb_strtolower(trim((string) ($_POST['username'] ?? '')));
$password = trim((string) ($_POST['password'] ?? ''));
if ($username === '' || $password === '') {
throw new RuntimeException('أدخل اسم المستخدم وكلمة المرور.');
}
$user = fetchRow($pdo, 'SELECT * FROM app_users WHERE username = :username LIMIT 1', [':username' => $username]);
if (!$user || !password_verify($password, (string) $user['password_hash'])) {
throw new RuntimeException('بيانات الدخول غير صحيحة. استخدم بالضبط: admin / admin123');
}
loginUser($user);
$runtimeFlash = ['type' => 'success', 'message' => 'تم تسجيل الدخول بنجاح.'];
$tab = 'equipment';
}
if (!isLoggedIn()) {
throw new RuntimeException('يرجى تسجيل الدخول أولاً.');
}
if ($action === 'save_rate') {
$rate = (float) ($_POST['exchange_rate'] ?? 0);
if ($rate <= 0) {
throw new RuntimeException('أدخل قيمة صحيحة لسعر الدولار اليومي.');
}
setSetting($pdo, 'exchange_rate', (string) $rate);
setFlash('success', 'تم تحديث سعر الدولار اليومي.');
redirectTo('index.php?tab=equipment');
}
if ($action === 'add_equipment') {
$name = trim((string) ($_POST['name'] ?? ''));
$quantity = (int) ($_POST['quantity'] ?? 0);
$priceUsd = (float) ($_POST['price_usd'] ?? 0);
$notes = trim((string) ($_POST['notes'] ?? ''));
if ($name === '') {
throw new RuntimeException('أدخل اسم المعدة.');
}
if ($quantity < 0) {
throw new RuntimeException('الكمية يجب أن تكون صفر أو أكثر.');
}
if ($priceUsd <= 0) {
throw new RuntimeException('سعر الدولار يجب أن يكون أكبر من الصفر.');
}
$stmt = $pdo->prepare('INSERT INTO equipment (name, quantity, price_usd, notes) VALUES (:name, :quantity, :price_usd, :notes)');
$stmt->execute([
':name' => $name,
':quantity' => $quantity,
':price_usd' => $priceUsd,
':notes' => $notes !== '' ? $notes : null,
]);
setFlash('success', 'تمت إضافة المعدة بنجاح.');
redirectTo('index.php?tab=equipment');
}
if ($action === 'create_invoice') {
$equipmentId = (int) ($_POST['equipment_id'] ?? 0);
$quantity = (int) ($_POST['invoice_quantity'] ?? 0);
$customerName = trim((string) ($_POST['customer_name'] ?? ''));
$notes = trim((string) ($_POST['invoice_notes'] ?? ''));
$exchangeRate = (float) getSetting($pdo, 'exchange_rate', '0');
if ($equipmentId <= 0) {
throw new RuntimeException('اختر المعدة أولاً.');
}
if ($quantity <= 0) {
throw new RuntimeException('أدخل كمية صحيحة للفاتورة.');
}
if ($exchangeRate <= 0) {
throw new RuntimeException('أدخل سعر الدولار اليومي قبل إنشاء أي فاتورة.');
}
$pdo->beginTransaction();
try {
$equipment = fetchRow($pdo, 'SELECT id, name, quantity, price_usd FROM equipment WHERE id = :id FOR UPDATE', [':id' => $equipmentId]);
if (!$equipment) {
throw new RuntimeException('المعدة غير موجودة.');
}
if ((int) $equipment['quantity'] < $quantity) {
throw new RuntimeException('الكمية المطلوبة أكبر من المخزون المتاح.');
}
$lineTotalUsd = round((float) $equipment['price_usd'] * $quantity, 2);
$lineTotalSyp = (int) round($lineTotalUsd * $exchangeRate);
$invoiceStmt = $pdo->prepare(
'INSERT INTO invoices (invoice_number, customer_name, exchange_rate, total_usd, total_syp, notes, created_by)
VALUES (:invoice_number, :customer_name, :exchange_rate, :total_usd, :total_syp, :notes, :created_by)'
);
$tempNumber = 'TMP-' . bin2hex(random_bytes(4));
$invoiceStmt->execute([
':invoice_number' => $tempNumber,
':customer_name' => $customerName !== '' ? $customerName : null,
':exchange_rate' => $exchangeRate,
':total_usd' => $lineTotalUsd,
':total_syp' => $lineTotalSyp,
':notes' => $notes !== '' ? $notes : null,
':created_by' => currentUser()['full_name'] ?? 'admin',
]);
$invoiceId = (int) $pdo->lastInsertId();
$invoiceNumber = 'INV-' . gmdate('Ymd') . '-' . str_pad((string) $invoiceId, 4, '0', STR_PAD_LEFT);
$updateNumberStmt = $pdo->prepare('UPDATE invoices SET invoice_number = :invoice_number WHERE id = :id');
$updateNumberStmt->execute([
':invoice_number' => $invoiceNumber,
':id' => $invoiceId,
]);
$itemStmt = $pdo->prepare(
'INSERT INTO invoice_items (invoice_id, equipment_id, item_name, quantity, unit_price_usd, line_total_usd, line_total_syp)
VALUES (:invoice_id, :equipment_id, :item_name, :quantity, :unit_price_usd, :line_total_usd, :line_total_syp)'
);
$itemStmt->execute([
':invoice_id' => $invoiceId,
':equipment_id' => $equipmentId,
':item_name' => $equipment['name'],
':quantity' => $quantity,
':unit_price_usd' => $equipment['price_usd'],
':line_total_usd' => $lineTotalUsd,
':line_total_syp' => $lineTotalSyp,
]);
$stockStmt = $pdo->prepare('UPDATE equipment SET quantity = quantity - :qty WHERE id = :id');
$stockStmt->execute([
':qty' => $quantity,
':id' => $equipmentId,
]);
$pdo->commit();
setFlash('success', 'تم إنشاء الفاتورة وتحديث المخزون تلقائياً.');
redirectTo('index.php?tab=invoices&invoice_id=' . $invoiceId);
} catch (Throwable $exception) {
$pdo->rollBack();
throw $exception;
}
}
} catch (Throwable $exception) {
if ($action === 'login') {
$runtimeFlash = ['type' => 'error', 'message' => $exception->getMessage()];
$tab = 'equipment';
} else {
setFlash('error', $exception->getMessage());
$tab = currentTab();
redirectTo('index.php?tab=' . $tab);
}
}
}
$flash = $runtimeFlash ?? pullFlash();
$csrfToken = csrfToken();
$exchangeRate = (float) getSetting($pdo, 'exchange_rate', '15000');
$equipmentRows = getEquipmentRows($pdo);
$invoiceRows = getInvoices($pdo);
$selectedInvoiceId = (int) ($_GET['invoice_id'] ?? ($invoiceRows[0]['id'] ?? 0));
$selectedInvoice = $selectedInvoiceId > 0 ? getInvoiceDetails($pdo, $selectedInvoiceId) : null;
$tab = currentTab();
$user = currentUser();
$totalEquipmentTypes = (int) fetchValue($pdo, 'SELECT COUNT(*) FROM equipment');
$totalStockUnits = (int) fetchValue($pdo, 'SELECT COALESCE(SUM(quantity), 0) FROM equipment');
$totalInvoices = (int) fetchValue($pdo, 'SELECT COUNT(*) FROM invoices');
$totalSalesSyp = (float) fetchValue($pdo, 'SELECT COALESCE(SUM(total_syp), 0) FROM invoices');
$todaySalesSyp = (float) fetchValue($pdo, 'SELECT COALESCE(SUM(total_syp), 0) FROM invoices WHERE DATE(created_at) = UTC_DATE()');
$todayInvoices = (int) fetchValue($pdo, 'SELECT COUNT(*) FROM invoices WHERE DATE(created_at) = UTC_DATE()');
?>
<!doctype html>
<html lang="ar" dir="rtl">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title><?= e($projectName) ?> | إدارة محل بسيطة</title>
<meta name="description" content="<?= e($projectDescription) ?>">
<meta name="keywords" content="إدارة محل, معدات, فواتير, تقارير, دولار, ليرة سورية">
<meta name="author" content="Flatlogic AI">
<meta property="og:title" content="<?= e($projectName) ?>">
<meta property="og:description" content="<?= e($projectDescription) ?>">
<?php if ($projectImageUrl !== ''): ?>
<meta property="og:image" content="<?= e($projectImageUrl) ?>">
<meta property="twitter:image" content="<?= e($projectImageUrl) ?>">
<?php endif; ?>
<link rel="stylesheet" href="assets/css/custom.css?v=<?= e($assetCssVersion) ?>">
</head>
<body data-theme="light" data-current-rate="<?= e((string) $exchangeRate) ?>">
<div class="page-shell">
<header class="topbar">
<div>
<p class="eyebrow">Store Admin</p>
<h1><?= isLoggedIn() ? 'إدارة المحل' : 'تسجيل الدخول' ?></h1>
<p class="subtitle">
<?= isLoggedIn() ? 'واجهة بسيطة: معدات + فواتير + تقارير، مع تسعير ثابت بالدولار وتحويل يومي إلى الليرة السورية.' : 'ادخل بحساب واحد بسيط ثم افتح 3 أقسام فقط داخل التطبيق.' ?>
</p>
</div>
<div class="topbar-actions">
<button type="button" class="ghost-btn" data-theme-toggle>نهاري / ليلي</button>
<button type="button" class="ghost-btn" data-help-toggle>مساعدة</button>
</div>
</header>
<aside class="help-drawer" data-help-drawer aria-hidden="true">
<div class="help-card">
<div class="help-header">
<h2>مساعدة سريعة</h2>
<button type="button" class="icon-btn" data-help-close aria-label="إغلاق">×</button>
</div>
<ol>
<li>سجّل الدخول بالحساب التجريبي أو بحسابك.</li>
<li>حدّث سعر الدولار اليومي مرة واحدة.</li>
<li>أضف المعدات بالدولار والكمية الحالية.</li>
<li>أنشئ فاتورة، وسيتم حساب الليرة السورية وتخفيض المخزون تلقائياً.</li>
<li>من قسم التقارير راقب المبيعات اليومية والإجمالية.</li>
</ol>
<p class="help-note">بيانات التجربة الحالية: <strong>admin</strong> / <strong>admin123</strong></p>
</div>
</aside>
<?php if (!isLoggedIn()): ?>
<main class="login-layout">
<section class="login-card">
<div class="card-head">
<h2>دخول المدير</h2>
<p>أبسط نسخة ممكنة: شاشة دخول واحدة ثم 3 أقسام فقط داخل التطبيق.</p>
</div>
<?php if ($flash): ?>
<div class="alert alert-<?= e($flash['type']) ?>" data-auto-hide><?= e($flash['message']) ?></div>
<?php endif; ?>
<div class="demo-box">
<p><strong>بيانات الدخول الأكيدة:</strong> <span dir="ltr">admin / admin123</span></p>
<a class="primary-link" href="index.php?quick_login=demo">دخول مباشر للتطبيق</a>
</div>
<form method="post" class="stack-form">
<input type="hidden" name="csrf_token" value="<?= e($csrfToken) ?>">
<input type="hidden" name="action" value="login">
<label>
<span>اسم المستخدم</span>
<input type="text" name="username" placeholder="admin" autocomplete="username" required>
</label>
<label>
<span>كلمة المرور</span>
<input type="password" name="password" placeholder="admin123" autocomplete="current-password" required>
</label>
<button type="submit" class="primary-btn">دخول</button>
</form>
</section>
<section class="login-preview">
<div class="preview-card gradient-card">
<h2>شو داخل التطبيق؟</h2>
<ul>
<li>واجهة <strong>المعدات</strong> لإدخال أسعار الدولار والكمية.</li>
<li>واجهة <strong>الفواتير</strong> لحساب السعر بالليرة السورية مباشرة.</li>
<li>واجهة <strong>التقارير</strong> لمبيعات اليوم والإجمالي.</li>
<li>زر <strong>PDF</strong> وزر <strong>طباعة</strong> للفواتير.</li>
<li>زر <strong>نهاري / ليلي</strong> + زر <strong>مساعدة</strong>.</li>
</ul>
</div>
</section>
</main>
<?php else: ?>
<main class="app-layout">
<?php if ($flash): ?>
<div class="alert alert-<?= e($flash['type']) ?> app-alert" data-auto-hide><?= e($flash['message']) ?></div>
<?php endif; ?>
<section class="hero-card">
<div>
<p class="eyebrow">مرحبا، <?= e($user['full_name'] ?? 'مدير المحل') ?></p>
<h2>تطبيق مبسط فعلاً</h2>
<p>كل الأسعار الأساسية بالدولار، والتحويل إلى الليرة السورية يتم حسب سعر اليوم فقط.</p>
</div>
<div class="hero-actions">
<form method="post">
<input type="hidden" name="csrf_token" value="<?= e($csrfToken) ?>">
<input type="hidden" name="action" value="logout">
<button type="submit" class="ghost-btn">تسجيل الخروج</button>
</form>
</div>
</section>
<nav class="tab-nav" aria-label="أقسام التطبيق">
<a class="tab-link <?= $tab === 'equipment' ? 'is-active' : '' ?>" href="index.php?tab=equipment">المعدات</a>
<a class="tab-link <?= $tab === 'invoices' ? 'is-active' : '' ?>" href="index.php?tab=invoices">الفواتير</a>
<a class="tab-link <?= $tab === 'reports' ? 'is-active' : '' ?>" href="index.php?tab=reports">التقارير</a>
</nav>
<?php if ($tab === 'equipment'): ?>
<section class="grid two-col">
<article class="panel-card">
<div class="card-head">
<h2>سعر الدولار اليومي</h2>
<p>هذا هو الرقم الوحيد الذي يتغير، أما أسعار المعدات فتظل ثابتة بالدولار.</p>
</div>
<form method="post" class="stack-form compact-form">
<input type="hidden" name="csrf_token" value="<?= e($csrfToken) ?>">
<input type="hidden" name="action" value="save_rate">
<label>
<span>سعر الدولار اليوم</span>
<input type="number" step="0.01" min="0" name="exchange_rate" value="<?= e((string) $exchangeRate) ?>" data-rate-input required>
</label>
<div class="stat-inline">
<span>المعاينة الحالية بالليرة:</span>
<strong data-rate-preview><?= e(formatSyp($exchangeRate)) ?></strong>
</div>
<button type="submit" class="primary-btn">حفظ السعر</button>
</form>
</article>
<article class="panel-card">
<div class="card-head">
<h2>إضافة معدة</h2>
<p>أدخل السعر بالدولار، والتطبيق سيحسب الليرة السورية عند البيع فقط.</p>
</div>
<form method="post" class="stack-form compact-form">
<input type="hidden" name="csrf_token" value="<?= e($csrfToken) ?>">
<input type="hidden" name="action" value="add_equipment">
<label>
<span>اسم المعدة</span>
<input type="text" name="name" placeholder="مثال: شاشة 24 إنش" required>
</label>
<div class="split-fields">
<label>
<span>الكمية</span>
<input type="number" min="0" name="quantity" placeholder="10" required>
</label>
<label>
<span>السعر بالدولار</span>
<input type="number" step="0.01" min="0" name="price_usd" placeholder="150" data-equipment-usd required>
</label>
</div>
<label>
<span>ملاحظات</span>
<textarea name="notes" rows="3" placeholder="اختياري"></textarea>
</label>
<div class="stat-inline">
<span>معاينة السعر بالليرة حسب اليوم:</span>
<strong data-equipment-preview>—</strong>
</div>
<button type="submit" class="primary-btn">إضافة المعدة</button>
</form>
</article>
</section>
<section class="panel-card">
<div class="card-head inline-head">
<div>
<h2>قائمة المعدات</h2>
<p><?= e((string) $totalEquipmentTypes) ?> نوع / <?= e((string) $totalStockUnits) ?> قطعة في المخزون</p>
</div>
</div>
<div class="table-wrap">
<table>
<thead>
<tr>
<th>المعدة</th>
<th>الكمية</th>
<th>السعر بالدولار</th>
<th>السعر بالليرة</th>
<th>ملاحظات</th>
</tr>
</thead>
<tbody>
<?php if (!$equipmentRows): ?>
<tr><td colspan="5" class="empty-cell">لا توجد معدات حتى الآن.</td></tr>
<?php else: ?>
<?php foreach ($equipmentRows as $item): ?>
<tr>
<td><?= e($item['name']) ?></td>
<td><?= e((string) $item['quantity']) ?></td>
<td><?= e(formatUsd((float) $item['price_usd'])) ?></td>
<td><?= e(formatSyp((float) $item['price_usd'] * $exchangeRate)) ?></td>
<td><?= e($item['notes'] ?? '—') ?></td>
</tr>
<?php endforeach; ?>
<?php endif; ?>
</tbody>
</table>
</div>
</section>
<?php elseif ($tab === 'invoices'): ?>
<section class="grid two-col invoice-grid">
<article class="panel-card">
<div class="card-head">
<h2>إنشاء فاتورة</h2>
<p>اختر معدة واحدة، أدخل الكمية، وسيتم خصمها من المخزون مباشرة.</p>
</div>
<form method="post" class="stack-form compact-form">
<input type="hidden" name="csrf_token" value="<?= e($csrfToken) ?>">
<input type="hidden" name="action" value="create_invoice">
<label>
<span>المعدة</span>
<select name="equipment_id" data-invoice-equipment required>
<option value="">اختر من القائمة</option>
<?php foreach ($equipmentRows as $item): ?>
<option value="<?= e((string) $item['id']) ?>" data-price="<?= e((string) $item['price_usd']) ?>" data-stock="<?= e((string) $item['quantity']) ?>">
<?= e($item['name']) ?> — <?= e(formatUsd((float) $item['price_usd'])) ?>
</option>
<?php endforeach; ?>
</select>
</label>
<div class="split-fields">
<label>
<span>الكمية</span>
<input type="number" min="1" name="invoice_quantity" value="1" data-invoice-qty required>
</label>
<label>
<span>العميل</span>
<input type="text" name="customer_name" placeholder="اختياري">
</label>
</div>
<label>
<span>ملاحظات</span>
<textarea name="invoice_notes" rows="3" placeholder="اختياري"></textarea>
</label>
<div class="invoice-preview-box">
<div><span>المخزون الحالي:</span> <strong data-invoice-stock>—</strong></div>
<div><span>إجمالي الفاتورة بالليرة:</span> <strong data-invoice-total>—</strong></div>
</div>
<button type="submit" class="primary-btn">حفظ الفاتورة</button>
</form>
</article>
<article class="panel-card printable-panel" data-printable-invoice>
<div class="card-head inline-head">
<div>
<h2>الفاتورة المحددة</h2>
<p>اختر فاتورة من الجدول أو أنشئ واحدة جديدة لتظهر هنا.</p>
</div>
<div class="inline-actions">
<button type="button" class="ghost-btn" data-print-invoice <?= $selectedInvoice ? '' : 'disabled' ?>>طباعة</button>
<button type="button" class="ghost-btn" data-export-selected-pdf <?= $selectedInvoice ? '' : 'disabled' ?>>PDF للفاتورة</button>
</div>
</div>
<?php if (!$selectedInvoice): ?>
<div class="empty-state">لا توجد فاتورة محددة بعد.</div>
<?php else: ?>
<div class="invoice-sheet">
<div class="invoice-row"><span>رقم الفاتورة</span><strong><?= e($selectedInvoice['invoice_number']) ?></strong></div>
<div class="invoice-row"><span>العميل</span><strong><?= e($selectedInvoice['customer_name'] ?: 'عميل مباشر') ?></strong></div>
<div class="invoice-row"><span>سعر الدولار</span><strong><?= e(formatSyp((float) $selectedInvoice['exchange_rate'])) ?></strong></div>
<div class="invoice-row"><span>الإجمالي بالدولار</span><strong><?= e(formatUsd((float) $selectedInvoice['total_usd'])) ?></strong></div>
<div class="invoice-row"><span>الإجمالي بالليرة</span><strong><?= e(formatSyp((float) $selectedInvoice['total_syp'])) ?></strong></div>
<div class="invoice-row"><span>التاريخ</span><strong><?= e((string) $selectedInvoice['created_at']) ?></strong></div>
<div class="invoice-items">
<h3>العناصر</h3>
<?php foreach ($selectedInvoice['items'] as $line): ?>
<div class="invoice-item">
<span><?= e($line['item_name']) ?> × <?= e((string) $line['quantity']) ?></span>
<strong><?= e(formatSyp((float) $line['line_total_syp'])) ?></strong>
</div>
<?php endforeach; ?>
</div>
<p class="invoice-note"><?= e($selectedInvoice['notes'] ?: 'بدون ملاحظات') ?></p>
</div>
<?php endif; ?>
</article>
</section>
<section class="panel-card">
<div class="card-head inline-head">
<div>
<h2>سجل الفواتير</h2>
<p>آخر 100 فاتورة مع إمكانية تصدير القائمة كاملة كملف PDF.</p>
</div>
<button type="button" class="primary-btn secondary-tone" data-export-invoices <?= $invoiceRows ? '' : 'disabled' ?>>تصدير سجل الفواتير PDF</button>
</div>
<div class="table-wrap">
<table data-invoices-table>
<thead>
<tr>
<th>رقم الفاتورة</th>
<th>العميل</th>
<th>الإجمالي بالدولار</th>
<th>الإجمالي بالليرة</th>
<th>التاريخ</th>
</tr>
</thead>
<tbody>
<?php if (!$invoiceRows): ?>
<tr><td colspan="5" class="empty-cell">لا توجد فواتير حتى الآن.</td></tr>
<?php else: ?>
<?php foreach ($invoiceRows as $invoice): ?>
<tr class="clickable-row" onclick="window.location='index.php?tab=invoices&amp;invoice_id=<?= e((string) $invoice['id']) ?>'">
<td><?= e($invoice['invoice_number']) ?></td>
<td><?= e($invoice['customer_name'] ?: 'عميل مباشر') ?></td>
<td><?= e(formatUsd((float) $invoice['total_usd'])) ?></td>
<td><?= e(formatSyp((float) $invoice['total_syp'])) ?></td>
<td><?= e((string) $invoice['created_at']) ?></td>
</tr>
<?php endforeach; ?>
<?php endif; ?>
</tbody>
</table>
</div>
</section>
<?php else: ?>
<section class="stats-grid">
<article class="stat-card">
<span>أنواع المعدات</span>
<strong><?= e((string) $totalEquipmentTypes) ?></strong>
</article>
<article class="stat-card">
<span>إجمالي المخزون</span>
<strong><?= e((string) $totalStockUnits) ?> قطعة</strong>
</article>
<article class="stat-card">
<span>فواتير اليوم</span>
<strong><?= e((string) $todayInvoices) ?></strong>
</article>
<article class="stat-card">
<span>مبيعات اليوم</span>
<strong><?= e(formatSyp($todaySalesSyp)) ?></strong>
</article>
</section>
<section class="grid two-col reports-grid">
<article class="panel-card">
<div class="card-head">
<h2>ملخص سريع</h2>
<p>قراءة مباشرة لوضع المحل اليوم.</p>
</div>
<ul class="summary-list">
<li><span>عدد الفواتير الكلي</span><strong><?= e((string) $totalInvoices) ?></strong></li>
<li><span>إجمالي المبيعات</span><strong><?= e(formatSyp($totalSalesSyp)) ?></strong></li>
<li><span>سعر الدولار الحالي</span><strong><?= e(formatSyp($exchangeRate)) ?></strong></li>
<li><span>آخر تحديث للأسعار</span><strong><?= e(gmdate('Y-m-d H:i')) ?></strong></li>
</ul>
</article>
<article class="panel-card">
<div class="card-head">
<h2>آخر الفواتير</h2>
<p>أحدث الحركات المالية داخل التطبيق.</p>
</div>
<div class="mini-list">
<?php if (!$invoiceRows): ?>
<div class="empty-state">لا توجد بيانات بعد.</div>
<?php else: ?>
<?php foreach (array_slice($invoiceRows, 0, 5) as $invoice): ?>
<div class="mini-item">
<div>
<strong><?= e($invoice['invoice_number']) ?></strong>
<p><?= e($invoice['customer_name'] ?: 'عميل مباشر') ?></p>
</div>
<span><?= e(formatSyp((float) $invoice['total_syp'])) ?></span>
</div>
<?php endforeach; ?>
<?php endif; ?>
</div>
</article>
</section>
<?php endif; ?>
</main>
<?php endif; ?>
</div>
<script src="https://cdn.jsdelivr.net/npm/jspdf@2.5.1/dist/jspdf.umd.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/jspdf-autotable@3.8.2/dist/jspdf.plugin.autotable.min.js"></script>
<script src="assets/js/main.js?v=<?= e($assetJsVersion) ?>"></script>
</body>
</html>