Autosave: 20260310-135333
This commit is contained in:
parent
031d73aec7
commit
4b01726905
@ -207,10 +207,14 @@ render_header('Manage Cities', 'admin', true);
|
|||||||
<td><?= e($city['name_en']) ?></td>
|
<td><?= e($city['name_en']) ?></td>
|
||||||
<td><?= e((string)($city['name_ar'] ?? '-')) ?></td>
|
<td><?= e((string)($city['name_ar'] ?? '-')) ?></td>
|
||||||
<td class="text-end">
|
<td class="text-end">
|
||||||
<a class="btn btn-sm btn-outline-primary" href="<?= e(url_with_lang('admin_cities.php', ['edit_city' => (int)$city['id']])) ?>">Edit</a>
|
<a class="btn btn-sm p-1 border-0 bg-transparent text-primary" href="<?= e(url_with_lang('admin_cities.php', ['edit_city' => (int)$city['id']])) ?>">
|
||||||
<form method="post" class="d-inline" onsubmit="return confirm('Delete this city?');">
|
<i class="bi bi-pencil"></i>
|
||||||
|
</a>
|
||||||
|
<form method="post" class="d-inline m-0 p-0" onsubmit="return confirm('Delete this city?');">
|
||||||
<input type="hidden" name="city_id" value="<?= e((string)$city['id']) ?>">
|
<input type="hidden" name="city_id" value="<?= e((string)$city['id']) ?>">
|
||||||
<button type="submit" name="delete_city" class="btn btn-sm btn-outline-danger">Del</button>
|
<button type="submit" name="delete_city" class="btn btn-sm p-1 border-0 bg-transparent text-danger">
|
||||||
|
<i class="bi bi-trash"></i>
|
||||||
|
</button>
|
||||||
</form>
|
</form>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|||||||
@ -109,7 +109,28 @@ render_header('Company Profile', 'admin', true);
|
|||||||
|
|
||||||
<div class="panel p-4">
|
<div class="panel p-4">
|
||||||
<form method="post" enctype="multipart/form-data">
|
<form method="post" enctype="multipart/form-data">
|
||||||
<div class="row g-0">
|
<ul class="nav nav-tabs mb-4" id="companySettingsTab" role="tablist">
|
||||||
|
<li class="nav-item" role="presentation">
|
||||||
|
<button class="nav-link active" id="company-tab" data-bs-toggle="tab" data-bs-target="#company" type="button" role="tab" aria-controls="company" aria-selected="true">
|
||||||
|
<i class="bi bi-building me-2"></i>Company Setting
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item" role="presentation">
|
||||||
|
<button class="nav-link" id="legal-tab" data-bs-toggle="tab" data-bs-target="#legal" type="button" role="tab" aria-controls="legal" aria-selected="false">
|
||||||
|
<i class="bi bi-file-earmark-text me-2"></i>Legal & Policies
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item" role="presentation">
|
||||||
|
<button class="nav-link" id="privacy-tab" data-bs-toggle="tab" data-bs-target="#privacy" type="button" role="tab" aria-controls="privacy" aria-selected="false">
|
||||||
|
<i class="bi bi-shield-lock me-2"></i>Privacy Policy
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<div class="tab-content" id="companySettingsTabContent">
|
||||||
|
<!-- Tab 1: Company Setting -->
|
||||||
|
<div class="tab-pane fade show active" id="company" role="tabpanel" aria-labelledby="company-tab">
|
||||||
|
<div class="row g-3">
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<label class="form-label fw-bold">Company / App Name</label>
|
<label class="form-label fw-bold">Company / App Name</label>
|
||||||
<input type="text" name="company_name" class="form-control" value="<?= e($currentName) ?>" required>
|
<input type="text" name="company_name" class="form-control" value="<?= e($currentName) ?>" required>
|
||||||
@ -167,30 +188,41 @@ render_header('Company Profile', 'admin', true);
|
|||||||
<input type="file" name="favicon_file" class="form-control" accept="image/png, image/x-icon, image/svg+xml">
|
<input type="file" name="favicon_file" class="form-control" accept="image/png, image/x-icon, image/svg+xml">
|
||||||
<div class="form-text">Recommended size: 32x32px (ICO, PNG, SVG). Leave empty to keep current.</div>
|
<div class="form-text">Recommended size: 32x32px (ICO, PNG, SVG). Leave empty to keep current.</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
<div class="col-md-12">
|
|
||||||
<hr class="my-2">
|
|
||||||
<h5 class="fw-bold mb-3">Legal & Policies</h5>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- Tab 2: Legal & Policies -->
|
||||||
|
<div class="tab-pane fade" id="legal" role="tabpanel" aria-labelledby="legal-tab">
|
||||||
|
<div class="row g-3">
|
||||||
|
<div class="col-12">
|
||||||
|
<h5 class="fw-bold mb-3">Terms of Service</h5>
|
||||||
|
</div>
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<label class="form-label fw-bold">Terms of Service (English)</label>
|
<label class="form-label fw-bold">English</label>
|
||||||
<textarea name="terms_en" class="form-control" rows="5" placeholder="Enter Terms of Service in English..."><?= e($currentTermsEn) ?></textarea>
|
<textarea name="terms_en" class="form-control" rows="10" placeholder="Enter Terms of Service in English..."><?= e($currentTermsEn) ?></textarea>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6">
|
||||||
|
<label class="form-label fw-bold">Arabic</label>
|
||||||
|
<textarea name="terms_ar" class="form-control" rows="10" dir="rtl" placeholder="أدخل شروط الخدمة باللغة العربية..."><?= e($currentTermsAr) ?></textarea>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="col-md-6">
|
<!-- Tab 3: Privacy Policy -->
|
||||||
<label class="form-label fw-bold">Terms of Service (Arabic)</label>
|
<div class="tab-pane fade" id="privacy" role="tabpanel" aria-labelledby="privacy-tab">
|
||||||
<textarea name="terms_ar" class="form-control" rows="5" dir="rtl" placeholder="أدخل شروط الخدمة باللغة العربية..."><?= e($currentTermsAr) ?></textarea>
|
<div class="row g-3">
|
||||||
|
<div class="col-12">
|
||||||
|
<h5 class="fw-bold mb-3">Privacy Policy</h5>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<label class="form-label fw-bold">Privacy Policy (English)</label>
|
<label class="form-label fw-bold">English</label>
|
||||||
<textarea name="privacy_en" class="form-control" rows="5" placeholder="Enter Privacy Policy in English..."><?= e($currentPrivacyEn) ?></textarea>
|
<textarea name="privacy_en" class="form-control" rows="10" placeholder="Enter Privacy Policy in English..."><?= e($currentPrivacyEn) ?></textarea>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<label class="form-label fw-bold">Privacy Policy (Arabic)</label>
|
<label class="form-label fw-bold">Arabic</label>
|
||||||
<textarea name="privacy_ar" class="form-control" rows="5" dir="rtl" placeholder="أدخل سياسة الخصوصية باللغة العربية..."><?= e($currentPrivacyAr) ?></textarea>
|
<textarea name="privacy_ar" class="form-control" rows="10" dir="rtl" placeholder="أدخل سياسة الخصوصية باللغة العربية..."><?= e($currentPrivacyAr) ?></textarea>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@ -164,10 +164,14 @@ render_header('Manage Countries', 'admin', true);
|
|||||||
<td><?= e($country['name_en']) ?></td>
|
<td><?= e($country['name_en']) ?></td>
|
||||||
<td><?= e((string)($country['name_ar'] ?? '-')) ?></td>
|
<td><?= e((string)($country['name_ar'] ?? '-')) ?></td>
|
||||||
<td class="text-end">
|
<td class="text-end">
|
||||||
<a class="btn btn-sm btn-outline-primary" href="<?= e(url_with_lang('admin_countries.php', ['edit_country' => (int)$country['id']])) ?>">Edit</a>
|
<a class="btn btn-sm p-1 border-0 bg-transparent text-primary" href="<?= e(url_with_lang('admin_countries.php', ['edit_country' => (int)$country['id']])) ?>">
|
||||||
<form method="post" class="d-inline" onsubmit="return confirm('Delete this country and its cities?');">
|
<i class="bi bi-pencil"></i>
|
||||||
|
</a>
|
||||||
|
<form method="post" class="d-inline m-0 p-0" onsubmit="return confirm('Delete this country and its cities?');">
|
||||||
<input type="hidden" name="country_id" value="<?= e((string)$country['id']) ?>">
|
<input type="hidden" name="country_id" value="<?= e((string)$country['id']) ?>">
|
||||||
<button type="submit" name="delete_country" class="btn btn-sm btn-outline-danger">Del</button>
|
<button type="submit" name="delete_country" class="btn btn-sm p-1 border-0 bg-transparent text-danger">
|
||||||
|
<i class="bi bi-trash"></i>
|
||||||
|
</button>
|
||||||
</form>
|
</form>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|||||||
@ -85,11 +85,12 @@ render_header(t('admin_dashboard'), 'admin', true);
|
|||||||
<div class="row g-0">
|
<div class="row g-0">
|
||||||
<!-- Main Content: Shipments -->
|
<!-- Main Content: Shipments -->
|
||||||
<div class="col-lg-8">
|
<div class="col-lg-8">
|
||||||
<div class="panel p-4 shadow-sm border-0 h-100 rounded-4 d-flex flex-column">
|
<div class="panel shadow-sm border-0 h-100 rounded-4 d-flex flex-column">
|
||||||
<div class="d-flex justify-content-between align-items-center mb-4">
|
<div class="panel-heading d-flex justify-content-between align-items-center">
|
||||||
<h2 class="h5 mb-0 fw-bold"><i class="bi bi-clock-history text-muted me-2"></i>Recent Shipments</h2>
|
<h2 class="h5 mb-0 fw-bold text-white"><i class="bi bi-clock-history text-white-50 me-2"></i>Recent Shipments</h2>
|
||||||
<span class="badge bg-light text-dark border"><?= e(count($shipments)) ?> shown</span>
|
<span class="badge bg-white text-dark"><?= e(count($shipments)) ?> shown</span>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="p-4 flex-grow-1 d-flex flex-column">
|
||||||
<?php if ($flash): ?>
|
<?php if ($flash): ?>
|
||||||
<div class="alert alert-success" data-auto-dismiss="true"><?= e($flash['message']) ?></div>
|
<div class="alert alert-success" data-auto-dismiss="true"><?= e($flash['message']) ?></div>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
@ -128,8 +129,8 @@ render_header(t('admin_dashboard'), 'admin', true);
|
|||||||
</td>
|
</td>
|
||||||
<td><span class="badge <?= e($row['status']) ?> rounded-pill px-3 py-2"><?= e(status_label($row['status'])) ?></span></td>
|
<td><span class="badge <?= e($row['status']) ?> rounded-pill px-3 py-2"><?= e(status_label($row['status'])) ?></span></td>
|
||||||
<td class="text-end">
|
<td class="text-end">
|
||||||
<a href="<?= e(url_with_lang('shipment_detail.php', ['id' => $row['id']])) ?>" class="btn btn-sm btn-outline-primary rounded-pill px-3">
|
<a href="<?= e(url_with_lang('shipment_detail.php', ['id' => $row['id']])) ?>" class="btn btn-sm p-1 border-0 bg-transparent text-primary" title="View Details">
|
||||||
View Details
|
<i class="bi bi-eye"></i>
|
||||||
</a>
|
</a>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
@ -140,11 +141,15 @@ render_header(t('admin_dashboard'), 'admin', true);
|
|||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- Sidebar: Quick Links List -->
|
<!-- Sidebar: Quick Links List -->
|
||||||
<div class="col-lg-4">
|
<div class="col-lg-4">
|
||||||
<div class="panel p-4 shadow-sm border-0 h-100 rounded-4" style="background-color: #fafbfc;">
|
<div class="panel shadow-sm border-0 h-100 rounded-4" style="background-color: #fafbfc;">
|
||||||
<h2 class="h5 mb-4 fw-bold"><i class="bi bi-lightning-charge text-warning me-2"></i>Quick Links</h2>
|
<div class="panel-heading">
|
||||||
|
<h2 class="h5 mb-0 fw-bold text-white"><i class="bi bi-lightning-charge text-warning me-2"></i>Quick Links</h2>
|
||||||
|
</div>
|
||||||
|
<div class="p-4">
|
||||||
<div class="list-group list-group-flush bg-transparent">
|
<div class="list-group list-group-flush bg-transparent">
|
||||||
<a href="<?= e(url_with_lang('admin_countries.php')) ?>" class="list-group-item list-group-item-action bg-transparent border-bottom d-flex align-items-center py-3 px-0">
|
<a href="<?= e(url_with_lang('admin_countries.php')) ?>" class="list-group-item list-group-item-action bg-transparent border-bottom d-flex align-items-center py-3 px-0">
|
||||||
<div class="bg-white rounded p-3 shadow-sm me-3 text-primary d-flex align-items-center justify-content-center" style="width: 48px; height: 48px;"><i class="bi bi-globe2 fs-5"></i></div>
|
<div class="bg-white rounded p-3 shadow-sm me-3 text-primary d-flex align-items-center justify-content-center" style="width: 48px; height: 48px;"><i class="bi bi-globe2 fs-5"></i></div>
|
||||||
@ -191,6 +196,7 @@ render_header(t('admin_dashboard'), 'admin', true);
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<?php render_footer(); ?>
|
<?php render_footer(); ?>
|
||||||
@ -129,7 +129,7 @@ render_header('Manage FAQs', 'admin', true);
|
|||||||
|
|
||||||
<?php if ($editingFaq): ?>
|
<?php if ($editingFaq): ?>
|
||||||
<div class="card border-0 shadow-sm mb-4">
|
<div class="card border-0 shadow-sm mb-4">
|
||||||
<div class="card-header bg-white border-bottom-0 pt-4 pb-0">
|
<div class="card-header">
|
||||||
<h5 class="mb-0">Edit FAQ</h5>
|
<h5 class="mb-0">Edit FAQ</h5>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
@ -168,7 +168,7 @@ render_header('Manage FAQs', 'admin', true);
|
|||||||
</div>
|
</div>
|
||||||
<?php else: ?>
|
<?php else: ?>
|
||||||
<div class="card border-0 shadow-sm mb-4">
|
<div class="card border-0 shadow-sm mb-4">
|
||||||
<div class="card-header bg-white border-bottom-0 pt-4 pb-0">
|
<div class="card-header">
|
||||||
<h5 class="mb-0">Add New FAQ</h5>
|
<h5 class="mb-0">Add New FAQ</h5>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
@ -205,7 +205,7 @@ render_header('Manage FAQs', 'admin', true);
|
|||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
|
|
||||||
<div class="card border-0 shadow-sm">
|
<div class="card border-0 shadow-sm">
|
||||||
<div class="card-header bg-white border-bottom-0 pt-4 pb-3">
|
<div class="card-header">
|
||||||
<h5 class="mb-0">Current FAQs</h5>
|
<h5 class="mb-0">Current FAQs</h5>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-body p-0">
|
<div class="card-body p-0">
|
||||||
@ -217,7 +217,7 @@ render_header('Manage FAQs', 'admin', true);
|
|||||||
<?php else: ?>
|
<?php else: ?>
|
||||||
<div class="table-responsive">
|
<div class="table-responsive">
|
||||||
<table class="table table-hover align-middle mb-0">
|
<table class="table table-hover align-middle mb-0">
|
||||||
<thead class="table-light">
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th class="ps-4">Sort</th>
|
<th class="ps-4">Sort</th>
|
||||||
<th>Question (EN)</th>
|
<th>Question (EN)</th>
|
||||||
|
|||||||
@ -73,7 +73,29 @@ render_header('Integrations', 'admin', true);
|
|||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
|
|
||||||
<form method="post">
|
<form method="post">
|
||||||
|
|
||||||
|
<ul class="nav nav-tabs mb-4" id="integrationsTab" role="tablist">
|
||||||
|
<li class="nav-item" role="presentation">
|
||||||
|
<button class="nav-link active" id="thawani-tab" data-bs-toggle="tab" data-bs-target="#thawani" type="button" role="tab" aria-controls="thawani" aria-selected="true">
|
||||||
|
Thawani Gateway
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item" role="presentation">
|
||||||
|
<button class="nav-link" id="whatsapp-tab" data-bs-toggle="tab" data-bs-target="#whatsapp" type="button" role="tab" aria-controls="whatsapp" aria-selected="false">
|
||||||
|
Whatsapp Setting
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item" role="presentation">
|
||||||
|
<button class="nav-link" id="smtp-tab" data-bs-toggle="tab" data-bs-target="#smtp" type="button" role="tab" aria-controls="smtp" aria-selected="false">
|
||||||
|
SMTP Mail
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<div class="tab-content" id="integrationsTabContent">
|
||||||
|
|
||||||
<!-- Thawani Payments Panel -->
|
<!-- Thawani Payments Panel -->
|
||||||
|
<div class="tab-pane fade show active" id="thawani" role="tabpanel" aria-labelledby="thawani-tab">
|
||||||
<div class="panel p-4 mb-4">
|
<div class="panel p-4 mb-4">
|
||||||
<h3 class="h5 fw-bold mb-3 d-flex align-items-center">
|
<h3 class="h5 fw-bold mb-3 d-flex align-items-center">
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor" class="bi bi-credit-card me-2 text-primary" viewBox="0 0 16 16">
|
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor" class="bi bi-credit-card me-2 text-primary" viewBox="0 0 16 16">
|
||||||
@ -105,8 +127,10 @@ render_header('Integrations', 'admin', true);
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- Wablas WhatsApp Gateway Panel -->
|
<!-- Wablas WhatsApp Gateway Panel -->
|
||||||
|
<div class="tab-pane fade" id="whatsapp" role="tabpanel" aria-labelledby="whatsapp-tab">
|
||||||
<div class="panel p-4 mb-4">
|
<div class="panel p-4 mb-4">
|
||||||
<h3 class="h5 fw-bold mb-3 d-flex align-items-center">
|
<h3 class="h5 fw-bold mb-3 d-flex align-items-center">
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor" class="bi bi-whatsapp me-2 text-success" viewBox="0 0 16 16">
|
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor" class="bi bi-whatsapp me-2 text-success" viewBox="0 0 16 16">
|
||||||
@ -142,8 +166,10 @@ render_header('Integrations', 'admin', true);
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- SMTP Mail Gateway Panel -->
|
<!-- SMTP Mail Gateway Panel -->
|
||||||
|
<div class="tab-pane fade" id="smtp" role="tabpanel" aria-labelledby="smtp-tab">
|
||||||
<div class="panel p-4 mb-4">
|
<div class="panel p-4 mb-4">
|
||||||
<h3 class="h5 fw-bold mb-3 d-flex align-items-center">
|
<h3 class="h5 fw-bold mb-3 d-flex align-items-center">
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor" class="bi bi-envelope me-2 text-danger" viewBox="0 0 16 16">
|
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor" class="bi bi-envelope me-2 text-danger" viewBox="0 0 16 16">
|
||||||
@ -194,8 +220,11 @@ render_header('Integrations', 'admin', true);
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="d-flex justify-content-end">
|
</div>
|
||||||
|
|
||||||
|
<div class="d-flex justify-content-end mt-4">
|
||||||
<button type="submit" class="btn btn-primary px-5">Save Integrations</button>
|
<button type="submit" class="btn btn-primary px-5">Save Integrations</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|||||||
@ -222,12 +222,16 @@ render_header(t('app_name') . ' - Landing Pages', 'admin', true);
|
|||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
</div>
|
</div>
|
||||||
<div class="d-flex gap-2">
|
<div class="d-flex gap-2">
|
||||||
<a href="<?= e(url_with_lang('admin_landing_pages.php', ['edit' => $sec['id']])) ?>" class="btn btn-sm btn-outline-primary">Edit</a>
|
<a href="<?= e(url_with_lang('admin_landing_pages.php', ['edit' => $sec['id']])) ?>" class="btn btn-sm p-1 border-0 bg-transparent text-primary" title="Edit">
|
||||||
|
<i class="bi bi-pencil"></i>
|
||||||
|
</a>
|
||||||
<?php if ($sec['section_type'] === 'custom'): ?>
|
<?php if ($sec['section_type'] === 'custom'): ?>
|
||||||
<form action="<?= e(url_with_lang('admin_landing_pages.php')) ?>" method="POST" onsubmit="return confirm('Are you sure you want to delete this section?');" style="display:inline;">
|
<form action="<?= e(url_with_lang('admin_landing_pages.php')) ?>" method="POST" onsubmit="return confirm('Are you sure you want to delete this section?');" style="display:inline;">
|
||||||
<input type="hidden" name="action" value="delete">
|
<input type="hidden" name="action" value="delete">
|
||||||
<input type="hidden" name="id" value="<?= e($sec['id']) ?>">
|
<input type="hidden" name="id" value="<?= e($sec['id']) ?>">
|
||||||
<button type="submit" class="btn btn-sm btn-outline-danger">Delete</button>
|
<button type="submit" class="btn btn-sm p-1 border-0 bg-transparent text-danger" title="Delete">
|
||||||
|
<i class="bi bi-trash"></i>
|
||||||
|
</button>
|
||||||
</form>
|
</form>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -185,8 +185,8 @@ render_header('Notification Templates', 'admin', true);
|
|||||||
<td><?= e($t['email_subject_en']) ?></td>
|
<td><?= e($t['email_subject_en']) ?></td>
|
||||||
<td><?= e($t['email_subject_ar']) ?></td>
|
<td><?= e($t['email_subject_ar']) ?></td>
|
||||||
<td class="text-end pe-4">
|
<td class="text-end pe-4">
|
||||||
<a href="<?= e(url_with_lang('admin_notification_templates.php', ['action' => 'edit', 'id' => $t['id']])) ?>" class="btn btn-sm btn-outline-primary">
|
<a href="<?= e(url_with_lang('admin_notification_templates.php', ['action' => 'edit', 'id' => $t['id']])) ?>" class="btn btn-sm p-1 border-0 bg-transparent text-primary" title="Edit">
|
||||||
Edit
|
<i class="bi bi-pencil"></i>
|
||||||
</a>
|
</a>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|||||||
@ -166,12 +166,12 @@ render_header(t('nav_platform_users'), 'platform_users', true);
|
|||||||
<td><?= e($user['email']) ?></td>
|
<td><?= e($user['email']) ?></td>
|
||||||
<td class="text-muted small"><?= e(date('M j, Y', strtotime($user['created_at']))) ?></td>
|
<td class="text-muted small"><?= e(date('M j, Y', strtotime($user['created_at']))) ?></td>
|
||||||
<td class="pe-4 text-end">
|
<td class="pe-4 text-end">
|
||||||
<button class="btn btn-sm btn-outline-primary rounded-pill px-3 me-1" onclick="editUser(<?= e(json_encode($user)) ?>)">
|
<button class="btn btn-sm p-1 border-0 bg-transparent text-primary" onclick="editUser(<?= e(json_encode($user)) ?>)">
|
||||||
<i class="bi bi-pencil-fill me-1"></i><?= e(t('edit_user')) ?>
|
<i class="bi bi-pencil"></i>
|
||||||
</button>
|
</button>
|
||||||
<?php if ($user['id'] !== $_SESSION['user_id']): ?>
|
<?php if ($user['id'] !== $_SESSION['user_id']): ?>
|
||||||
<button class="btn btn-sm btn-outline-danger rounded-pill px-3" onclick="confirmDelete(<?= $user['id'] ?>)">
|
<button class="btn btn-sm p-1 border-0 bg-transparent text-danger" onclick="confirmDelete(<?= $user['id'] ?>)">
|
||||||
<i class="bi bi-trash-fill"></i>
|
<i class="bi bi-trash"></i>
|
||||||
</button>
|
</button>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
</td>
|
</td>
|
||||||
|
|||||||
@ -3,19 +3,29 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
require_once __DIR__ . '/includes/layout.php';
|
require_once __DIR__ . '/includes/layout.php';
|
||||||
|
|
||||||
$errors = [];
|
|
||||||
$flash = null;
|
|
||||||
|
|
||||||
$id = (int)($_GET['id'] ?? 0);
|
$id = (int)($_GET['id'] ?? 0);
|
||||||
|
$isAjax = isset($_GET['ajax']) && $_GET['ajax'] === '1';
|
||||||
|
|
||||||
if (!$id) {
|
if (!$id) {
|
||||||
|
if ($isAjax) {
|
||||||
|
echo json_encode(['success' => false, 'message' => 'Invalid ID']);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
header('Location: admin_shipments.php'); exit;
|
header('Location: admin_shipments.php'); exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$errors = [];
|
||||||
|
$flash = null;
|
||||||
|
|
||||||
$stmt = db()->prepare("SELECT * FROM shipments WHERE id = ?");
|
$stmt = db()->prepare("SELECT * FROM shipments WHERE id = ?");
|
||||||
$stmt->execute([$id]);
|
$stmt->execute([$id]);
|
||||||
$shipment = $stmt->fetch();
|
$shipment = $stmt->fetch();
|
||||||
|
|
||||||
if (!$shipment) {
|
if (!$shipment) {
|
||||||
|
if ($isAjax) {
|
||||||
|
echo json_encode(['success' => false, 'message' => 'Shipment not found']);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
header('Location: admin_shipments.php'); exit;
|
header('Location: admin_shipments.php'); exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -85,6 +95,12 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
|||||||
]);
|
]);
|
||||||
$flash = "Shipment updated successfully.";
|
$flash = "Shipment updated successfully.";
|
||||||
|
|
||||||
|
if ($isAjax) {
|
||||||
|
header('Content-Type: application/json');
|
||||||
|
echo json_encode(['success' => true, 'message' => $flash]);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
// Refresh data
|
// Refresh data
|
||||||
$stmt->execute([$id]);
|
$stmt->execute([$id]);
|
||||||
$shipment = $stmt->fetch();
|
$shipment = $stmt->fetch();
|
||||||
@ -107,9 +123,17 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
|||||||
$destination_cities_list = $stmt->fetchAll();
|
$destination_cities_list = $stmt->fetchAll();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($isAjax && $errors) {
|
||||||
|
header('Content-Type: application/json');
|
||||||
|
echo json_encode(['success' => false, 'message' => implode('<br>', $errors)]);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
render_header('Edit Shipment', 'admin', true);
|
// -- OUTPUT START --
|
||||||
|
if (!$isAjax):
|
||||||
|
render_header('Edit Shipment', 'admin', true);
|
||||||
?>
|
?>
|
||||||
|
|
||||||
<div class="row g-0">
|
<div class="row g-0">
|
||||||
@ -143,8 +167,21 @@ render_header('Edit Shipment', 'admin', true);
|
|||||||
</div>
|
</div>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
|
|
||||||
<div class="panel p-4">
|
<div class="panel">
|
||||||
<form method="post">
|
<div class="panel-heading">Shipment Details</div>
|
||||||
|
<div class="p-4">
|
||||||
|
<?php endif; // End non-ajax wrapper ?>
|
||||||
|
|
||||||
|
<form method="post" action="admin_shipment_edit.php?id=<?= $id ?><?= $isAjax ? '&ajax=1' : '' ?>" class="ajax-form">
|
||||||
|
<?php if ($isAjax): ?>
|
||||||
|
<div class="modal-header">
|
||||||
|
<h5 class="modal-title">Edit Shipment #<?= e((string)$shipment['id']) ?></h5>
|
||||||
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<div id="form-errors" class="alert alert-danger d-none"></div>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
<div class="row g-3">
|
<div class="row g-3">
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<label class="form-label">Shipper Name</label>
|
<label class="form-label">Shipper Name</label>
|
||||||
@ -250,20 +287,34 @@ render_header('Edit Shipment', 'admin', true);
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<?php if ($isAjax): ?>
|
||||||
|
</div> <!-- modal-body end -->
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
|
||||||
|
<button type="submit" class="btn btn-primary">Save Changes</button>
|
||||||
|
</div>
|
||||||
|
<?php else: ?>
|
||||||
<div class="mt-4 pt-3 border-top d-flex justify-content-end">
|
<div class="mt-4 pt-3 border-top d-flex justify-content-end">
|
||||||
<button type="submit" class="btn btn-primary">Save Changes</button>
|
<button type="submit" class="btn btn-primary">Save Changes</button>
|
||||||
</div>
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
|
<?php if (!$isAjax): ?>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
document.addEventListener('DOMContentLoaded', function() {
|
(function() {
|
||||||
function setupCityLoader(countrySelectId, citySelectId) {
|
function setupCityLoader(countrySelectId, citySelectId) {
|
||||||
const countrySelect = document.getElementById(countrySelectId);
|
const countrySelect = document.getElementById(countrySelectId);
|
||||||
const citySelect = document.getElementById(citySelectId);
|
const citySelect = document.getElementById(citySelectId);
|
||||||
|
|
||||||
|
if (!countrySelect || !citySelect) return;
|
||||||
|
|
||||||
countrySelect.addEventListener('change', function() {
|
countrySelect.addEventListener('change', function() {
|
||||||
const countryId = this.value;
|
const countryId = this.value;
|
||||||
citySelect.innerHTML = '<option value="">Loading...</option>';
|
citySelect.innerHTML = '<option value="">Loading...</option>';
|
||||||
@ -295,7 +346,7 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||||||
|
|
||||||
setupCityLoader('origin_country', 'origin_city');
|
setupCityLoader('origin_country', 'origin_city');
|
||||||
setupCityLoader('destination_country', 'destination_city');
|
setupCityLoader('destination_country', 'destination_city');
|
||||||
});
|
})();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<?php render_footer(); ?>
|
<?php if (!$isAjax) render_footer(); ?>
|
||||||
@ -164,24 +164,20 @@ render_header('Manage Shipments', 'admin', true);
|
|||||||
</td>
|
</td>
|
||||||
<td class="text-end pe-4">
|
<td class="text-end pe-4">
|
||||||
<div class="d-inline-flex gap-1 align-items-center">
|
<div class="d-inline-flex gap-1 align-items-center">
|
||||||
<a href="shipment_detail.php?id=<?= e((string)$shipment['id']) ?>" class="btn btn-sm btn-light border text-primary" title="View Shipment">
|
<a href="shipment_detail.php?id=<?= e((string)$shipment['id']) ?>" class="btn btn-sm p-1 border-0 bg-transparent text-primary" title="View Shipment">
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" fill="currentColor" class="bi bi-eye" viewBox="0 0 16 16">
|
<i class="bi bi-eye"></i>
|
||||||
<path d="M16 8s-3-5.5-8-5.5S0 8 0 8s3 5.5 8 5.5S16 8 16 8zM1.173 8a13.133 13.133 0 0 1 1.66-2.043C4.12 4.668 5.88 3.5 8 3.5c2.12 0 3.879 1.168 5.168 2.457A13.133 13.133 0 0 1 14.828 8c-.058.087-.122.183-.195.288-.335.48-.83 1.12-1.465 1.755C11.879 11.332 10.119 12.5 8 12.5c-2.12 0-3.879-1.168-5.168-2.457A13.134 13.134 0 0 1 1.172 8z"/>
|
|
||||||
<path d="M8 5.5a2.5 2.5 0 1 0 0 5 2.5 2.5 0 0 0 0-5zM4.5 8a3.5 3.5 0 1 1 7 0 3.5 3.5 0 0 1-7 0z"/>
|
|
||||||
</svg>
|
|
||||||
</a>
|
</a>
|
||||||
<a href="admin_shipment_edit.php?id=<?= e((string)$shipment['id']) ?>" class="btn btn-sm btn-light border text-primary" title="Edit Shipment">
|
<a href="admin_shipment_edit.php?id=<?= e((string)$shipment['id']) ?>"
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" fill="currentColor" class="bi bi-pencil" viewBox="0 0 16 16">
|
class="btn btn-sm p-1 border-0 bg-transparent text-primary ajax-modal-trigger"
|
||||||
<path d="M12.146.146a.5.5 0 0 1 .708 0l3 3a.5.5 0 0 1 0 .708l-10 10a.5.5 0 0 1-.168.11l-5 2a.5.5 0 0 1-.65-.65l2-5a.5.5 0 0 1 .11-.168zM11.207 2.5 13.5 4.793 14.793 3.5 12.5 1.207zm1.586 3L10.5 3.207 4 9.707V10h.5a.5.5 0 0 1 .5.5v.5h.5a.5.5 0 0 1 .5.5v.5h.293zm-9.761 5.175-.106.106-1.528 3.821 3.821-1.528.106-.106A.5.5 0 0 1 5 12.5V12h-.5a.5.5 0 0 1-.5-.5V11h-.5a.5.5 0 0 1-.468-.325"/>
|
data-bs-toggle="modal"
|
||||||
</svg>
|
data-bs-target="#editModal"
|
||||||
|
title="Edit Shipment">
|
||||||
|
<i class="bi bi-pencil"></i>
|
||||||
</a>
|
</a>
|
||||||
<form method="post" class="d-inline m-0 p-0">
|
<form method="post" class="d-inline m-0 p-0">
|
||||||
<input type="hidden" name="shipment_id" value="<?= e((string)$shipment['id']) ?>">
|
<input type="hidden" name="shipment_id" value="<?= e((string)$shipment['id']) ?>">
|
||||||
<button type="submit" name="action" value="delete" class="btn btn-sm btn-danger" onclick="return confirm('Delete this shipment?');" title="Delete">
|
<button type="submit" name="action" value="delete" class="btn btn-sm p-1 border-0 bg-transparent text-danger" onclick="return confirm('Delete this shipment?');" title="Delete">
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" fill="currentColor" class="bi bi-trash" viewBox="0 0 16 16">
|
<i class="bi bi-trash"></i>
|
||||||
<path d="M5.5 5.5A.5.5 0 0 1 6 6v6a.5.5 0 0 1-1 0V6a.5.5 0 0 1 .5-.5m2.5 0a.5.5 0 0 1 .5.5v6a.5.5 0 0 1-1 0V6a.5.5 0 0 1 .5-.5m3 .5a.5.5 0 0 0-1 0v6a.5.5 0 0 0 1 0z"/>
|
|
||||||
<path d="M14.5 3a1 1 0 0 1-1 1H13v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V4h-.5a1 1 0 0 1-1-1V2a1 1 0 0 1 1-1H6a1 1 0 0 1 1-1h2a1 1 0 0 1 1 1h3.5a1 1 0 0 1 1 1zM4.118 4 4 4.059V13a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1V4.059L11.882 4zM2.5 3h11V2h-11z"/>
|
|
||||||
</svg>
|
|
||||||
</button>
|
</button>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
@ -215,4 +211,109 @@ render_header('Manage Shipments', 'admin', true);
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- Edit Modal -->
|
||||||
|
<div class="modal fade" id="editModal" tabindex="-1" aria-labelledby="editModalLabel" aria-hidden="true">
|
||||||
|
<div class="modal-dialog modal-lg">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h5 class="modal-title" id="editModalLabel">Edit</h5>
|
||||||
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body text-center p-5">
|
||||||
|
<div class="spinner-border text-primary" role="status">
|
||||||
|
<span class="visually-hidden">Loading...</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
|
const editModal = document.getElementById('editModal');
|
||||||
|
if (!editModal) return;
|
||||||
|
|
||||||
|
editModal.addEventListener('show.bs.modal', function (event) {
|
||||||
|
const button = event.relatedTarget;
|
||||||
|
if (!button.classList.contains('ajax-modal-trigger')) return;
|
||||||
|
|
||||||
|
const url = button.getAttribute('href') + '&ajax=1';
|
||||||
|
const modalContent = editModal.querySelector('.modal-content');
|
||||||
|
|
||||||
|
modalContent.innerHTML = `
|
||||||
|
<div class="modal-header">
|
||||||
|
<h5 class="modal-title">Loading...</h5>
|
||||||
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body text-center p-5">
|
||||||
|
<div class="spinner-border text-primary" role="status"></div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
|
fetch(url)
|
||||||
|
.then(response => response.text())
|
||||||
|
.then(html => {
|
||||||
|
if (html.startsWith('{')) {
|
||||||
|
const data = JSON.parse(html);
|
||||||
|
modalContent.innerHTML = `<div class="modal-header"><button type="button" class="btn-close" data-bs-dismiss="modal"></button></div><div class="modal-body"><div class="alert alert-danger">${data.message}</div></div>`;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
modalContent.innerHTML = html;
|
||||||
|
|
||||||
|
modalContent.querySelectorAll('script').forEach(script => {
|
||||||
|
const newScript = document.createElement('script');
|
||||||
|
if (script.src) newScript.src = script.src;
|
||||||
|
newScript.textContent = script.textContent;
|
||||||
|
document.body.appendChild(newScript);
|
||||||
|
});
|
||||||
|
|
||||||
|
const form = modalContent.querySelector('form');
|
||||||
|
if (form) {
|
||||||
|
form.addEventListener('submit', function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
const submitBtn = form.querySelector('button[type="submit"]');
|
||||||
|
if(submitBtn) {
|
||||||
|
submitBtn.disabled = true;
|
||||||
|
submitBtn.innerHTML = '<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span> Saving...';
|
||||||
|
}
|
||||||
|
|
||||||
|
const formData = new FormData(form);
|
||||||
|
fetch(form.action, { method: 'POST', body: formData })
|
||||||
|
.then(res => res.json())
|
||||||
|
.then(data => {
|
||||||
|
if (data.success) {
|
||||||
|
location.reload();
|
||||||
|
} else {
|
||||||
|
if(submitBtn) {
|
||||||
|
submitBtn.disabled = false;
|
||||||
|
submitBtn.textContent = 'Save Changes';
|
||||||
|
}
|
||||||
|
const errDiv = form.querySelector('#form-errors');
|
||||||
|
if(errDiv) {
|
||||||
|
errDiv.classList.remove('d-none');
|
||||||
|
errDiv.innerHTML = data.message;
|
||||||
|
} else {
|
||||||
|
alert(data.message || 'An error occurred');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
console.error(err);
|
||||||
|
if(submitBtn) {
|
||||||
|
submitBtn.disabled = false;
|
||||||
|
submitBtn.textContent = 'Save Changes';
|
||||||
|
}
|
||||||
|
alert('An error occurred while saving.');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
modalContent.innerHTML = `<div class="modal-body text-danger">Failed to load form.</div>`;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
<?php render_footer(); ?>
|
<?php render_footer(); ?>
|
||||||
@ -4,7 +4,13 @@ declare(strict_types=1);
|
|||||||
require_once __DIR__ . '/includes/layout.php';
|
require_once __DIR__ . '/includes/layout.php';
|
||||||
|
|
||||||
$userId = (int)($_GET['id'] ?? 0);
|
$userId = (int)($_GET['id'] ?? 0);
|
||||||
|
$isAjax = isset($_GET['ajax']) && $_GET['ajax'] === '1';
|
||||||
|
|
||||||
if ($userId <= 0) {
|
if ($userId <= 0) {
|
||||||
|
if ($isAjax) {
|
||||||
|
echo json_encode(['success' => false, 'message' => 'Invalid ID']);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
header('Location: admin_shippers.php');
|
header('Location: admin_shippers.php');
|
||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
@ -24,6 +30,10 @@ $stmt->execute([$userId]);
|
|||||||
$shipper = $stmt->fetch();
|
$shipper = $stmt->fetch();
|
||||||
|
|
||||||
if (!$shipper) {
|
if (!$shipper) {
|
||||||
|
if ($isAjax) {
|
||||||
|
echo json_encode(['success' => false, 'message' => 'Shipper not found']);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
header('Location: admin_shippers.php');
|
header('Location: admin_shippers.php');
|
||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
@ -80,6 +90,12 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
|||||||
db()->commit();
|
db()->commit();
|
||||||
$flash = 'Shipper profile updated successfully.';
|
$flash = 'Shipper profile updated successfully.';
|
||||||
|
|
||||||
|
if ($isAjax) {
|
||||||
|
header('Content-Type: application/json');
|
||||||
|
echo json_encode(['success' => true, 'message' => $flash]);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
// Refresh data
|
// Refresh data
|
||||||
$shipper['full_name'] = $fullName;
|
$shipper['full_name'] = $fullName;
|
||||||
$shipper['email'] = $email;
|
$shipper['email'] = $email;
|
||||||
@ -99,9 +115,17 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($isAjax && $errors) {
|
||||||
|
header('Content-Type: application/json');
|
||||||
|
echo json_encode(['success' => false, 'message' => implode('<br>', $errors)]);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
render_header('Edit Shipper', 'admin', true);
|
// -- OUTPUT START --
|
||||||
|
if (!$isAjax):
|
||||||
|
render_header('Edit Shipper', 'admin', true);
|
||||||
?>
|
?>
|
||||||
|
|
||||||
<div class="row g-0">
|
<div class="row g-0">
|
||||||
@ -125,7 +149,18 @@ render_header('Edit Shipper', 'admin', true);
|
|||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
|
|
||||||
<div class="panel p-4">
|
<div class="panel p-4">
|
||||||
<form method="post">
|
<?php endif; // End non-ajax wrapper ?>
|
||||||
|
|
||||||
|
<form method="post" action="admin_shipper_edit.php?id=<?= $userId ?><?= $isAjax ? '&ajax=1' : '' ?>" class="ajax-form">
|
||||||
|
<?php if ($isAjax): ?>
|
||||||
|
<div class="modal-header">
|
||||||
|
<h5 class="modal-title">Edit Shipper: <?= e($shipper['full_name']) ?></h5>
|
||||||
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<div id="form-errors" class="alert alert-danger d-none"></div>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
<div class="row g-3">
|
<div class="row g-3">
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<label class="form-label" for="full_name">Full Name</label>
|
<label class="form-label" for="full_name">Full Name</label>
|
||||||
@ -169,7 +204,7 @@ render_header('Edit Shipper', 'admin', true);
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="col-md-3">
|
<div class="col-md-3">
|
||||||
<label class="form-label" for="password">Password <small class="text-muted">(leave blank to keep)</small></label>
|
<label class="form-label" for="password">Password <small class="text-muted">(leave blank)</small></label>
|
||||||
<input type="password" name="password" id="password" class="form-control" autocomplete="new-password">
|
<input type="password" name="password" id="password" class="form-control" autocomplete="new-password">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -182,22 +217,38 @@ render_header('Edit Shipper', 'admin', true);
|
|||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<?php if ($isAjax): ?>
|
||||||
|
</div> <!-- modal-body end -->
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
|
||||||
|
<button type="submit" class="btn btn-primary">Save Changes</button>
|
||||||
|
</div>
|
||||||
|
<?php else: ?>
|
||||||
<div class="col-12 mt-4">
|
<div class="col-12 mt-4">
|
||||||
<button type="submit" class="btn btn-primary">Save Changes</button>
|
<button type="submit" class="btn btn-primary">Save Changes</button>
|
||||||
<a href="admin_shippers.php" class="btn btn-outline-dark ms-2">Cancel</a>
|
<a href="admin_shippers.php" class="btn btn-outline-dark ms-2">Cancel</a>
|
||||||
</div>
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
|
<?php if (!$isAjax): ?>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
const allCities = <?= json_encode($cities, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) ?>;
|
(function() {
|
||||||
|
const allCities = <?= json_encode($cities, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) ?>;
|
||||||
|
const countrySelect = document.querySelector('#country_id');
|
||||||
|
const citySelect = document.querySelector('#city_id');
|
||||||
|
const lang = '<?= $lang ?>';
|
||||||
|
|
||||||
function syncCities() {
|
window.syncCities = function() {
|
||||||
const countryId = document.getElementById('country_id').value;
|
if (!countrySelect || !citySelect) return;
|
||||||
const citySelect = document.getElementById('city_id');
|
|
||||||
|
const countryId = countrySelect.value;
|
||||||
const selectedValue = citySelect.dataset.selected || '';
|
const selectedValue = citySelect.dataset.selected || '';
|
||||||
citySelect.innerHTML = '<option value="">Select city</option>';
|
citySelect.innerHTML = '<option value="">Select city</option>';
|
||||||
|
|
||||||
@ -207,16 +258,19 @@ function syncCities() {
|
|||||||
}
|
}
|
||||||
const option = document.createElement('option');
|
const option = document.createElement('option');
|
||||||
option.value = city.id;
|
option.value = city.id;
|
||||||
option.textContent = <?= $lang === 'ar' ? '(city.name_ar || city.name_en)' : '(city.name_en || city.name_ar)' ?>;
|
option.textContent = lang === 'ar' && city.name_ar ? city.name_ar : (city.name_en || city.name_ar);
|
||||||
if (String(city.id) === String(selectedValue)) {
|
if (String(city.id) === String(selectedValue)) {
|
||||||
option.selected = true;
|
option.selected = true;
|
||||||
}
|
}
|
||||||
citySelect.appendChild(option);
|
citySelect.appendChild(option);
|
||||||
});
|
});
|
||||||
// clear selected after first render
|
|
||||||
citySelect.dataset.selected = '';
|
citySelect.dataset.selected = '';
|
||||||
}
|
};
|
||||||
syncCities();
|
|
||||||
|
if (countrySelect && citySelect) {
|
||||||
|
syncCities();
|
||||||
|
}
|
||||||
|
})();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<?php render_footer(); ?>
|
<?php if (!$isAjax) render_footer(); ?>
|
||||||
@ -167,32 +167,27 @@ render_header('Manage Shippers', 'admin', true);
|
|||||||
</td>
|
</td>
|
||||||
<td class="text-end pe-4">
|
<td class="text-end pe-4">
|
||||||
<div class="d-inline-flex gap-1 align-items-center">
|
<div class="d-inline-flex gap-1 align-items-center">
|
||||||
<a href="admin_shipper_edit.php?id=<?= e((string)$shipper['id']) ?>" class="btn btn-sm btn-light border text-primary" title="Edit Shipper">
|
<a href="admin_shipper_edit.php?id=<?= e((string)$shipper['id']) ?>"
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" fill="currentColor" class="bi bi-pencil" viewBox="0 0 16 16">
|
class="btn btn-sm p-1 border-0 bg-transparent text-primary ajax-modal-trigger"
|
||||||
<path d="M12.146.146a.5.5 0 0 1 .708 0l3 3a.5.5 0 0 1 0 .708l-10 10a.5.5 0 0 1-.168.11l-5 2a.5.5 0 0 1-.65-.65l2-5a.5.5 0 0 1 .11-.168zM11.207 2.5 13.5 4.793 14.793 3.5 12.5 1.207zm1.586 3L10.5 3.207 4 9.707V10h.5a.5.5 0 0 1 .5.5v.5h.5a.5.5 0 0 1 .5.5v.5h.293zm-9.761 5.175-.106.106-1.528 3.821 3.821-1.528.106-.106A.5.5 0 0 1 5 12.5V12h-.5a.5.5 0 0 1-.5-.5V11h-.5a.5.5 0 0 1-.468-.325"/>
|
data-bs-toggle="modal"
|
||||||
</svg>
|
data-bs-target="#editModal"
|
||||||
|
title="Edit Shipper">
|
||||||
|
<i class="bi bi-pencil"></i>
|
||||||
</a>
|
</a>
|
||||||
<form method="post" class="d-inline m-0 p-0">
|
<form method="post" class="d-inline m-0 p-0">
|
||||||
<input type="hidden" name="user_id" value="<?= e((string)$shipper['id']) ?>">
|
<input type="hidden" name="user_id" value="<?= e((string)$shipper['id']) ?>">
|
||||||
<?php if ($shipper['status'] !== 'active'): ?>
|
<?php if ($shipper['status'] !== 'active'): ?>
|
||||||
<button type="submit" name="action" value="approve" class="btn btn-sm btn-success" title="Approve">
|
<button type="submit" name="action" value="approve" class="btn btn-sm p-1 border-0 bg-transparent text-success" title="Approve">
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" fill="currentColor" class="bi bi-check-lg" viewBox="0 0 16 16">
|
<i class="bi bi-check-lg"></i>
|
||||||
<path d="M12.736 3.97a.733.733 0 0 1 1.047 0c.286.289.29.756.01 1.05L7.88 12.01a.733.733 0 0 1-1.065.02L3.217 8.384a.757.757 0 0 1 0-1.06.733.733 0 0 1 1.047 0l3.052 3.093 5.4-6.425z"/>
|
|
||||||
</svg>
|
|
||||||
</button>
|
</button>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
<?php if ($shipper['status'] !== 'rejected'): ?>
|
<?php if ($shipper['status'] !== 'rejected'): ?>
|
||||||
<button type="submit" name="action" value="reject" class="btn btn-sm btn-warning" title="Reject">
|
<button type="submit" name="action" value="reject" class="btn btn-sm p-1 border-0 bg-transparent text-warning" title="Reject">
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" fill="currentColor" class="bi bi-x-lg" viewBox="0 0 16 16">
|
<i class="bi bi-x-lg"></i>
|
||||||
<path d="M2.146 2.854a.5.5 0 1 1 .708-.708L8 7.293l5.146-5.147a.5.5 0 0 1 .708.708L8.707 8l5.147 5.146a.5.5 0 0 1-.708.708L8 8.707l-5.146 5.147a.5.5 0 0 1-.708-.708L7.293 8z"/>
|
|
||||||
</svg>
|
|
||||||
</button>
|
</button>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
<button type="submit" name="action" value="delete" class="btn btn-sm btn-danger" onclick="return confirm('Delete this shipper forever?');" title="Delete">
|
<button type="submit" name="action" value="delete" class="btn btn-sm p-1 border-0 bg-transparent text-danger" onclick="return confirm('Delete this shipper forever?');" title="Delete">
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" fill="currentColor" class="bi bi-trash" viewBox="0 0 16 16">
|
<i class="bi bi-trash"></i>
|
||||||
<path d="M5.5 5.5A.5.5 0 0 1 6 6v6a.5.5 0 0 1-1 0V6a.5.5 0 0 1 .5-.5m2.5 0a.5.5 0 0 1 .5.5v6a.5.5 0 0 1-1 0V6a.5.5 0 0 1 .5-.5m3 .5a.5.5 0 0 0-1 0v6a.5.5 0 0 0 1 0z"/>
|
|
||||||
<path d="M14.5 3a1 1 0 0 1-1 1H13v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V4h-.5a1 1 0 0 1-1-1V2a1 1 0 0 1 1-1H6a1 1 0 0 1 1-1h2a1 1 0 0 1 1 1h3.5a1 1 0 0 1 1 1zM4.118 4 4 4.059V13a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1V4.059L11.882 4zM2.5 3h11V2h-11z"/>
|
|
||||||
</svg>
|
|
||||||
</button>
|
</button>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
@ -226,4 +221,109 @@ render_header('Manage Shippers', 'admin', true);
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- Edit Modal -->
|
||||||
|
<div class="modal fade" id="editModal" tabindex="-1" aria-labelledby="editModalLabel" aria-hidden="true">
|
||||||
|
<div class="modal-dialog modal-lg">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h5 class="modal-title" id="editModalLabel">Edit</h5>
|
||||||
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body text-center p-5">
|
||||||
|
<div class="spinner-border text-primary" role="status">
|
||||||
|
<span class="visually-hidden">Loading...</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
|
const editModal = document.getElementById('editModal');
|
||||||
|
if (!editModal) return;
|
||||||
|
|
||||||
|
editModal.addEventListener('show.bs.modal', function (event) {
|
||||||
|
const button = event.relatedTarget;
|
||||||
|
if (!button.classList.contains('ajax-modal-trigger')) return;
|
||||||
|
|
||||||
|
const url = button.getAttribute('href') + '&ajax=1';
|
||||||
|
const modalContent = editModal.querySelector('.modal-content');
|
||||||
|
|
||||||
|
modalContent.innerHTML = `
|
||||||
|
<div class="modal-header">
|
||||||
|
<h5 class="modal-title">Loading...</h5>
|
||||||
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body text-center p-5">
|
||||||
|
<div class="spinner-border text-primary" role="status"></div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
|
fetch(url)
|
||||||
|
.then(response => response.text())
|
||||||
|
.then(html => {
|
||||||
|
if (html.startsWith('{')) {
|
||||||
|
const data = JSON.parse(html);
|
||||||
|
modalContent.innerHTML = `<div class="modal-header"><button type="button" class="btn-close" data-bs-dismiss="modal"></button></div><div class="modal-body"><div class="alert alert-danger">${data.message}</div></div>`;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
modalContent.innerHTML = html;
|
||||||
|
|
||||||
|
modalContent.querySelectorAll('script').forEach(script => {
|
||||||
|
const newScript = document.createElement('script');
|
||||||
|
if (script.src) newScript.src = script.src;
|
||||||
|
newScript.textContent = script.textContent;
|
||||||
|
document.body.appendChild(newScript);
|
||||||
|
});
|
||||||
|
|
||||||
|
const form = modalContent.querySelector('form');
|
||||||
|
if (form) {
|
||||||
|
form.addEventListener('submit', function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
const submitBtn = form.querySelector('button[type="submit"]');
|
||||||
|
if(submitBtn) {
|
||||||
|
submitBtn.disabled = true;
|
||||||
|
submitBtn.innerHTML = '<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span> Saving...';
|
||||||
|
}
|
||||||
|
|
||||||
|
const formData = new FormData(form);
|
||||||
|
fetch(form.action, { method: 'POST', body: formData })
|
||||||
|
.then(res => res.json())
|
||||||
|
.then(data => {
|
||||||
|
if (data.success) {
|
||||||
|
location.reload();
|
||||||
|
} else {
|
||||||
|
if(submitBtn) {
|
||||||
|
submitBtn.disabled = false;
|
||||||
|
submitBtn.textContent = 'Save Changes';
|
||||||
|
}
|
||||||
|
const errDiv = form.querySelector('#form-errors');
|
||||||
|
if(errDiv) {
|
||||||
|
errDiv.classList.remove('d-none');
|
||||||
|
errDiv.innerHTML = data.message;
|
||||||
|
} else {
|
||||||
|
alert(data.message || 'An error occurred');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
console.error(err);
|
||||||
|
if(submitBtn) {
|
||||||
|
submitBtn.disabled = false;
|
||||||
|
submitBtn.textContent = 'Save Changes';
|
||||||
|
}
|
||||||
|
alert('An error occurred while saving.');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
modalContent.innerHTML = `<div class="modal-body text-danger">Failed to load form.</div>`;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
<?php render_footer(); ?>
|
<?php render_footer(); ?>
|
||||||
@ -4,7 +4,13 @@ declare(strict_types=1);
|
|||||||
require_once __DIR__ . '/includes/layout.php';
|
require_once __DIR__ . '/includes/layout.php';
|
||||||
|
|
||||||
$userId = (int)($_GET['id'] ?? 0);
|
$userId = (int)($_GET['id'] ?? 0);
|
||||||
|
$isAjax = isset($_GET['ajax']) && $_GET['ajax'] === '1';
|
||||||
|
|
||||||
if ($userId <= 0) {
|
if ($userId <= 0) {
|
||||||
|
if ($isAjax) {
|
||||||
|
echo json_encode(['success' => false, 'message' => 'Invalid ID']);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
header('Location: admin_truck_owners.php');
|
header('Location: admin_truck_owners.php');
|
||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
@ -26,6 +32,10 @@ $stmt->execute([$userId]);
|
|||||||
$owner = $stmt->fetch();
|
$owner = $stmt->fetch();
|
||||||
|
|
||||||
if (!$owner) {
|
if (!$owner) {
|
||||||
|
if ($isAjax) {
|
||||||
|
echo json_encode(['success' => false, 'message' => 'Owner not found']);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
header('Location: admin_truck_owners.php');
|
header('Location: admin_truck_owners.php');
|
||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
@ -96,7 +106,14 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
|||||||
db()->commit();
|
db()->commit();
|
||||||
$flash = 'Truck Owner profile updated successfully.';
|
$flash = 'Truck Owner profile updated successfully.';
|
||||||
|
|
||||||
// Refresh data
|
// If AJAX, return success immediately
|
||||||
|
if ($isAjax) {
|
||||||
|
header('Content-Type: application/json');
|
||||||
|
echo json_encode(['success' => true, 'message' => $flash]);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Refresh data for non-ajax
|
||||||
$owner['full_name'] = $fullName;
|
$owner['full_name'] = $fullName;
|
||||||
$owner['email'] = $email;
|
$owner['email'] = $email;
|
||||||
$owner['status'] = $status;
|
$owner['status'] = $status;
|
||||||
@ -120,13 +137,21 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($isAjax && $errors) {
|
||||||
|
header('Content-Type: application/json');
|
||||||
|
echo json_encode(['success' => false, 'message' => implode('<br>', $errors)]);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$idCards = json_decode($owner['id_card_path'] ?? '[]', true) ?: [];
|
$idCards = json_decode($owner['id_card_path'] ?? '[]', true) ?: [];
|
||||||
$regs = json_decode($owner['registration_path'] ?? '[]', true) ?: [];
|
$regs = json_decode($owner['registration_path'] ?? '[]', true) ?: [];
|
||||||
$pic = $owner['truck_pic_path'];
|
$pic = $owner['truck_pic_path'];
|
||||||
|
|
||||||
render_header('Edit Truck Owner', 'admin', true);
|
// -- OUTPUT START --
|
||||||
|
if (!$isAjax):
|
||||||
|
render_header('Edit Truck Owner', 'admin', true);
|
||||||
?>
|
?>
|
||||||
|
|
||||||
<div class="row g-0">
|
<div class="row g-0">
|
||||||
@ -150,8 +175,20 @@ render_header('Edit Truck Owner', 'admin', true);
|
|||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
|
|
||||||
<div class="panel p-4">
|
<div class="panel p-4">
|
||||||
<form method="post">
|
<?php endif; // End non-ajax wrapper ?>
|
||||||
<h5 class="mb-3">Personal Details</h5>
|
|
||||||
|
<!-- The Form (Shared) -->
|
||||||
|
<form method="post" action="admin_truck_owner_edit.php?id=<?= $userId ?><?= $isAjax ? '&ajax=1' : '' ?>" class="ajax-form">
|
||||||
|
<?php if ($isAjax): ?>
|
||||||
|
<div class="modal-header">
|
||||||
|
<h5 class="modal-title">Edit Truck Owner: <?= e($owner['full_name']) ?></h5>
|
||||||
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<div id="form-errors" class="alert alert-danger d-none"></div>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
|
<h5 class="mb-3 <?= $isAjax ? 'd-none' : '' ?>">Personal Details</h5>
|
||||||
<div class="row g-3 mb-4">
|
<div class="row g-3 mb-4">
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<label class="form-label" for="full_name">Full Name</label>
|
<label class="form-label" for="full_name">Full Name</label>
|
||||||
@ -166,7 +203,7 @@ render_header('Edit Truck Owner', 'admin', true);
|
|||||||
<input type="text" name="phone" id="phone" class="form-control" value="<?= e((string)$owner['phone']) ?>" required>
|
<input type="text" name="phone" id="phone" class="form-control" value="<?= e((string)$owner['phone']) ?>" required>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-4">
|
<div class="col-md-4">
|
||||||
<label class="form-label" for="password">Password <small class="text-muted">(leave blank to keep)</small></label>
|
<label class="form-label" for="password">Password <small class="text-muted">(leave blank)</small></label>
|
||||||
<input type="password" name="password" id="password" class="form-control" autocomplete="new-password">
|
<input type="password" name="password" id="password" class="form-control" autocomplete="new-password">
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-4">
|
<div class="col-md-4">
|
||||||
@ -220,7 +257,7 @@ render_header('Edit Truck Owner', 'admin', true);
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h5 class="mb-3 mt-5 border-top pt-4">Bank Details</h5>
|
<h5 class="mb-3 mt-4 border-top pt-3">Bank Details</h5>
|
||||||
<div class="row g-3 mb-4">
|
<div class="row g-3 mb-4">
|
||||||
<div class="col-md-4">
|
<div class="col-md-4">
|
||||||
<label class="form-label" for="bank_account">Bank Account / IBAN</label>
|
<label class="form-label" for="bank_account">Bank Account / IBAN</label>
|
||||||
@ -236,7 +273,8 @@ render_header('Edit Truck Owner', 'admin', true);
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h5 class="mb-3 mt-5 border-top pt-4">Uploaded Documents</h5>
|
<?php if (!$isAjax): // Hide heavy images in modal edit to keep it clean, or keep them? User said "big and long". Let's keep them but maybe minimized. Actually let's keep them, they are important. ?>
|
||||||
|
<h5 class="mb-3 mt-4 border-top pt-3">Uploaded Documents</h5>
|
||||||
<div class="row g-4 mb-4">
|
<div class="row g-4 mb-4">
|
||||||
<div class="col-md-4">
|
<div class="col-md-4">
|
||||||
<h6 class="text-muted mb-2">ID Card</h6>
|
<h6 class="text-muted mb-2">ID Card</h6>
|
||||||
@ -277,22 +315,40 @@ render_header('Edit Truck Owner', 'admin', true);
|
|||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
|
<?php if ($isAjax): ?>
|
||||||
|
</div> <!-- modal-body -->
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
|
||||||
|
<button type="submit" class="btn btn-primary">Save Changes</button>
|
||||||
|
</div>
|
||||||
|
<?php else: ?>
|
||||||
<div class="mt-4">
|
<div class="mt-4">
|
||||||
<button type="submit" class="btn btn-primary">Save Changes</button>
|
<button type="submit" class="btn btn-primary">Save Changes</button>
|
||||||
<a href="admin_truck_owners.php" class="btn btn-outline-dark ms-2">Cancel</a>
|
<a href="admin_truck_owners.php" class="btn btn-outline-dark ms-2">Cancel</a>
|
||||||
</div>
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
|
<?php if (!$isAjax): ?>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
const allCities = <?= json_encode($cities, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) ?>;
|
(function() {
|
||||||
|
const allCities = <?= json_encode($cities, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) ?>;
|
||||||
|
const countrySelect = document.querySelector('#country_id'); // Use querySelector to scope? No, IDs are unique.
|
||||||
|
const citySelect = document.querySelector('#city_id');
|
||||||
|
const lang = '<?= $lang ?>';
|
||||||
|
|
||||||
function syncCities() {
|
window.syncCities = function() { // Expose globally for onchange
|
||||||
const countryId = document.getElementById('country_id').value;
|
if (!countrySelect || !citySelect) return;
|
||||||
const citySelect = document.getElementById('city_id');
|
|
||||||
|
const countryId = countrySelect.value;
|
||||||
const selectedValue = citySelect.dataset.selected || '';
|
const selectedValue = citySelect.dataset.selected || '';
|
||||||
citySelect.innerHTML = '<option value="">Select city</option>';
|
citySelect.innerHTML = '<option value="">Select city</option>';
|
||||||
|
|
||||||
@ -302,16 +358,21 @@ function syncCities() {
|
|||||||
}
|
}
|
||||||
const option = document.createElement('option');
|
const option = document.createElement('option');
|
||||||
option.value = city.id;
|
option.value = city.id;
|
||||||
option.textContent = <?= $lang === 'ar' ? '(city.name_ar || city.name_en)' : '(city.name_en || city.name_ar)' ?>;
|
option.textContent = lang === 'ar' && city.name_ar ? city.name_ar : (city.name_en || city.name_ar);
|
||||||
if (String(city.id) === String(selectedValue)) {
|
if (String(city.id) === String(selectedValue)) {
|
||||||
option.selected = true;
|
option.selected = true;
|
||||||
}
|
}
|
||||||
citySelect.appendChild(option);
|
citySelect.appendChild(option);
|
||||||
});
|
});
|
||||||
// clear selected after first render
|
|
||||||
citySelect.dataset.selected = '';
|
citySelect.dataset.selected = '';
|
||||||
}
|
};
|
||||||
syncCities();
|
|
||||||
|
// Initialize
|
||||||
|
if (countrySelect && citySelect) {
|
||||||
|
syncCities();
|
||||||
|
// Re-bind change event if needed, but onchange in HTML handles it.
|
||||||
|
}
|
||||||
|
})();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<?php render_footer(); ?>
|
<?php if (!$isAjax) render_footer(); ?>
|
||||||
@ -175,32 +175,27 @@ render_header('Manage Truck Owners', 'admin', true);
|
|||||||
</td>
|
</td>
|
||||||
<td class="text-end pe-4">
|
<td class="text-end pe-4">
|
||||||
<div class="d-inline-flex gap-1 align-items-center">
|
<div class="d-inline-flex gap-1 align-items-center">
|
||||||
<a href="admin_truck_owner_edit.php?id=<?= e((string)$owner['id']) ?>" class="btn btn-sm btn-light border text-primary" title="Edit Owner">
|
<a href="admin_truck_owner_edit.php?id=<?= e((string)$owner['id']) ?>"
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" fill="currentColor" class="bi bi-pencil" viewBox="0 0 16 16">
|
class="btn btn-sm p-1 border-0 bg-transparent text-primary ajax-modal-trigger"
|
||||||
<path d="M12.146.146a.5.5 0 0 1 .708 0l3 3a.5.5 0 0 1 0 .708l-10 10a.5.5 0 0 1-.168.11l-5 2a.5.5 0 0 1-.65-.65l2-5a.5.5 0 0 1 .11-.168zM11.207 2.5 13.5 4.793 14.793 3.5 12.5 1.207zm1.586 3L10.5 3.207 4 9.707V10h.5a.5.5 0 0 1 .5.5v.5h.5a.5.5 0 0 1 .5.5v.5h.293zm-9.761 5.175-.106.106-1.528 3.821 3.821-1.528.106-.106A.5.5 0 0 1 5 12.5V12h-.5a.5.5 0 0 1-.5-.5V11h-.5a.5.5 0 0 1-.468-.325"/>
|
data-bs-toggle="modal"
|
||||||
</svg>
|
data-bs-target="#editModal"
|
||||||
|
title="Edit Owner">
|
||||||
|
<i class="bi bi-pencil"></i>
|
||||||
</a>
|
</a>
|
||||||
<form method="post" class="d-inline m-0 p-0">
|
<form method="post" class="d-inline m-0 p-0">
|
||||||
<input type="hidden" name="user_id" value="<?= e((string)$owner['id']) ?>">
|
<input type="hidden" name="user_id" value="<?= e((string)$owner['id']) ?>">
|
||||||
<?php if ($owner['status'] !== 'active'): ?>
|
<?php if ($owner['status'] !== 'active'): ?>
|
||||||
<button type="submit" name="action" value="approve" class="btn btn-sm btn-success" title="Approve">
|
<button type="submit" name="action" value="approve" class="btn btn-sm p-1 border-0 bg-transparent text-success" title="Approve">
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" fill="currentColor" class="bi bi-check-lg" viewBox="0 0 16 16">
|
<i class="bi bi-check-lg"></i>
|
||||||
<path d="M12.736 3.97a.733.733 0 0 1 1.047 0c.286.289.29.756.01 1.05L7.88 12.01a.733.733 0 0 1-1.065.02L3.217 8.384a.757.757 0 0 1 0-1.06.733.733 0 0 1 1.047 0l3.052 3.093 5.4-6.425z"/>
|
|
||||||
</svg>
|
|
||||||
</button>
|
</button>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
<?php if ($owner['status'] !== 'rejected'): ?>
|
<?php if ($owner['status'] !== 'rejected'): ?>
|
||||||
<button type="submit" name="action" value="reject" class="btn btn-sm btn-warning" title="Reject">
|
<button type="submit" name="action" value="reject" class="btn btn-sm p-1 border-0 bg-transparent text-warning" title="Reject">
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" fill="currentColor" class="bi bi-x-lg" viewBox="0 0 16 16">
|
<i class="bi bi-x-lg"></i>
|
||||||
<path d="M2.146 2.854a.5.5 0 1 1 .708-.708L8 7.293l5.146-5.147a.5.5 0 0 1 .708.708L8.707 8l5.147 5.146a.5.5 0 0 1-.708.708L8 8.707l-5.146 5.147a.5.5 0 0 1-.708-.708L7.293 8z"/>
|
|
||||||
</svg>
|
|
||||||
</button>
|
</button>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
<button type="submit" name="action" value="delete" class="btn btn-sm btn-danger" onclick="return confirm('Delete this truck owner forever?');" title="Delete">
|
<button type="submit" name="action" value="delete" class="btn btn-sm p-1 border-0 bg-transparent text-danger" onclick="return confirm('Delete this truck owner forever?');" title="Delete">
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" fill="currentColor" class="bi bi-trash" viewBox="0 0 16 16">
|
<i class="bi bi-trash"></i>
|
||||||
<path d="M5.5 5.5A.5.5 0 0 1 6 6v6a.5.5 0 0 1-1 0V6a.5.5 0 0 1 .5-.5m2.5 0a.5.5 0 0 1 .5.5v6a.5.5 0 0 1-1 0V6a.5.5 0 0 1 .5-.5m3 .5a.5.5 0 0 0-1 0v6a.5.5 0 0 0 1 0z"/>
|
|
||||||
<path d="M14.5 3a1 1 0 0 1-1 1H13v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V4h-.5a1 1 0 0 1-1-1V2a1 1 0 0 1 1-1H6a1 1 0 0 1 1-1h2a1 1 0 0 1 1 1h3.5a1 1 0 0 1 1 1zM4.118 4 4 4.059V13a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1V4.059L11.882 4zM2.5 3h11V2h-11z"/>
|
|
||||||
</svg>
|
|
||||||
</button>
|
</button>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
@ -234,6 +229,23 @@ render_header('Manage Truck Owners', 'admin', true);
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- Edit Modal Placeholder -->
|
||||||
|
<div class="modal fade" id="editModal" tabindex="-1" aria-labelledby="editModalLabel" aria-hidden="true">
|
||||||
|
<div class="modal-dialog modal-lg">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h5 class="modal-title" id="editModalLabel">Edit</h5>
|
||||||
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body text-center p-5">
|
||||||
|
<div class="spinner-border text-primary" role="status">
|
||||||
|
<span class="visually-hidden">Loading...</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<?php foreach ($owners as $owner): ?>
|
<?php foreach ($owners as $owner): ?>
|
||||||
<?php
|
<?php
|
||||||
$idCards = json_decode($owner['id_card_path'] ?? '[]', true) ?: [];
|
$idCards = json_decode($owner['id_card_path'] ?? '[]', true) ?: [];
|
||||||
@ -285,4 +297,106 @@ $pic = $owner['truck_pic_path'];
|
|||||||
</div>
|
</div>
|
||||||
<?php endforeach; ?>
|
<?php endforeach; ?>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
|
const editModal = document.getElementById('editModal');
|
||||||
|
if (!editModal) return;
|
||||||
|
|
||||||
|
editModal.addEventListener('show.bs.modal', function (event) {
|
||||||
|
const button = event.relatedTarget;
|
||||||
|
if (!button.classList.contains('ajax-modal-trigger')) return;
|
||||||
|
|
||||||
|
const url = button.getAttribute('href') + '&ajax=1';
|
||||||
|
const modalContent = editModal.querySelector('.modal-content');
|
||||||
|
|
||||||
|
// Reset to loading state
|
||||||
|
modalContent.innerHTML = `
|
||||||
|
<div class="modal-header">
|
||||||
|
<h5 class="modal-title">Loading...</h5>
|
||||||
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body text-center p-5">
|
||||||
|
<div class="spinner-border text-primary" role="status"></div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
|
fetch(url)
|
||||||
|
.then(response => response.text())
|
||||||
|
.then(html => {
|
||||||
|
// If the response is a JSON error (e.g. invalid ID), we should handle it.
|
||||||
|
// But simplified: assuming HTML partial.
|
||||||
|
if (html.startsWith('{')) {
|
||||||
|
const data = JSON.parse(html);
|
||||||
|
modalContent.innerHTML = `<div class="modal-header"><button type="button" class="btn-close" data-bs-dismiss="modal"></button></div><div class="modal-body"><div class="alert alert-danger">${data.message}</div></div>`;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Inject HTML
|
||||||
|
// We strip the outer .modal-content if the partial includes it?
|
||||||
|
// No, the partial returns the BODY and FOOTER usually.
|
||||||
|
// My partial in edit php returns: <form>...<modal-header>...<modal-body>...<modal-footer>...</form>
|
||||||
|
// So I should replace .modal-content content.
|
||||||
|
// Wait, <form> cannot be a child of <div class="modal-content"> directly if it contains modal-header/body/footer?
|
||||||
|
// Yes, it can. <div class="modal-content"><form>...</form></div> is valid.
|
||||||
|
|
||||||
|
modalContent.innerHTML = html;
|
||||||
|
|
||||||
|
// Execute scripts in the injected HTML
|
||||||
|
modalContent.querySelectorAll('script').forEach(script => {
|
||||||
|
const newScript = document.createElement('script');
|
||||||
|
if (script.src) newScript.src = script.src;
|
||||||
|
newScript.textContent = script.textContent;
|
||||||
|
document.body.appendChild(newScript);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Bind form submission
|
||||||
|
const form = modalContent.querySelector('form');
|
||||||
|
if (form) {
|
||||||
|
form.addEventListener('submit', function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
const submitBtn = form.querySelector('button[type="submit"]');
|
||||||
|
if(submitBtn) {
|
||||||
|
submitBtn.disabled = true;
|
||||||
|
submitBtn.innerHTML = '<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span> Saving...';
|
||||||
|
}
|
||||||
|
|
||||||
|
const formData = new FormData(form);
|
||||||
|
fetch(form.action, { method: 'POST', body: formData })
|
||||||
|
.then(res => res.json())
|
||||||
|
.then(data => {
|
||||||
|
if (data.success) {
|
||||||
|
// Refresh the page to show updates
|
||||||
|
location.reload();
|
||||||
|
} else {
|
||||||
|
if(submitBtn) {
|
||||||
|
submitBtn.disabled = false;
|
||||||
|
submitBtn.textContent = 'Save Changes';
|
||||||
|
}
|
||||||
|
const errDiv = form.querySelector('#form-errors');
|
||||||
|
if(errDiv) {
|
||||||
|
errDiv.classList.remove('d-none');
|
||||||
|
errDiv.innerHTML = data.message;
|
||||||
|
} else {
|
||||||
|
alert(data.message || 'An error occurred');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
console.error(err);
|
||||||
|
if(submitBtn) {
|
||||||
|
submitBtn.disabled = false;
|
||||||
|
submitBtn.textContent = 'Save Changes';
|
||||||
|
}
|
||||||
|
alert('An error occurred while saving.');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
modalContent.innerHTML = `<div class="modal-body text-danger">Failed to load form.</div>`;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
<?php render_footer(); ?>
|
<?php render_footer(); ?>
|
||||||
@ -10,6 +10,14 @@
|
|||||||
--success: #10b981;
|
--success: #10b981;
|
||||||
--warning: #f59e0b;
|
--warning: #f59e0b;
|
||||||
--shadow: 0 10px 30px rgba(15, 23, 42, 0.05);
|
--shadow: 0 10px 30px rgba(15, 23, 42, 0.05);
|
||||||
|
|
||||||
|
/* Sidebar Theme */
|
||||||
|
--sidebar-bg: #000080;
|
||||||
|
--sidebar-text: #ffffff;
|
||||||
|
--sidebar-text-hover: #e2e8f0;
|
||||||
|
--sidebar-active-bg: rgba(255, 255, 255, 0.15);
|
||||||
|
--sidebar-active-text: #ffffff;
|
||||||
|
--sidebar-border: rgba(255, 255, 255, 0.1);
|
||||||
}
|
}
|
||||||
|
|
||||||
body.app-body {
|
body.app-body {
|
||||||
@ -42,6 +50,18 @@ body.app-body {
|
|||||||
background: var(--surface);
|
background: var(--surface);
|
||||||
box-shadow: var(--shadow);
|
box-shadow: var(--shadow);
|
||||||
transition: transform 0.2s ease, box-shadow 0.2s ease;
|
transition: transform 0.2s ease, box-shadow 0.2s ease;
|
||||||
|
overflow: hidden; /* Ensure headers/footers are clipped */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* New Panel Header Style */
|
||||||
|
.panel-heading,
|
||||||
|
.card-header {
|
||||||
|
background-color: var(--sidebar-bg);
|
||||||
|
color: #ffffff;
|
||||||
|
padding: 16px 24px;
|
||||||
|
border-bottom: 1px solid var(--sidebar-border);
|
||||||
|
font-weight: 600;
|
||||||
|
font-size: 1.1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hero-section {
|
.hero-section {
|
||||||
@ -149,13 +169,24 @@ body.app-body {
|
|||||||
color: #9333ea;
|
color: #9333ea;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Update Table Headers to match Sidebar */
|
||||||
.table thead th {
|
.table thead th {
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
letter-spacing: 0.05em;
|
letter-spacing: 0.05em;
|
||||||
color: var(--muted);
|
color: var(--sidebar-text);
|
||||||
border-bottom: 2px solid #f1f5f9;
|
background-color: var(--sidebar-bg);
|
||||||
padding-bottom: 12px;
|
border-bottom: 2px solid var(--sidebar-border);
|
||||||
|
padding: 14px 16px; /* Increased padding */
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
/* Ensure first and last th have rounded corners if table is isolated?
|
||||||
|
Bootstrap tables usually handle this, but with custom bg we might need to be careful. */
|
||||||
|
.table thead th:first-child {
|
||||||
|
border-top-left-radius: 8px;
|
||||||
|
}
|
||||||
|
.table thead th:last-child {
|
||||||
|
border-top-right-radius: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.table tbody td {
|
.table tbody td {
|
||||||
@ -236,34 +267,78 @@ body.app-body {
|
|||||||
border-radius: 12px;
|
border-radius: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Sidebar Styles Updated */
|
||||||
.admin-sidebar {
|
.admin-sidebar {
|
||||||
|
background-color: var(--sidebar-bg);
|
||||||
|
color: var(--sidebar-text);
|
||||||
position: sticky;
|
position: sticky;
|
||||||
top: 76px;
|
top: 76px;
|
||||||
height: calc(100vh - 76px);
|
height: calc(100vh - 76px);
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
border-radius: 0;
|
border-radius: 0;
|
||||||
|
/* Ensure it covers the parent's white bg */
|
||||||
|
margin-right: -1px; /* Overlap border if needed */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Sidebar Headings */
|
||||||
|
.admin-sidebar h2 {
|
||||||
|
color: #ffffff !important; /* Force white for headings */
|
||||||
|
border-bottom: 1px solid var(--sidebar-border);
|
||||||
|
padding-bottom: 12px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
font-size: 1.1rem;
|
||||||
|
}
|
||||||
|
.admin-sidebar h2 i {
|
||||||
|
color: var(--sidebar-active-bg) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Sidebar Links */
|
||||||
.admin-nav-link {
|
.admin-nav-link {
|
||||||
display: block;
|
display: block;
|
||||||
padding: 12px 16px;
|
padding: 12px 16px;
|
||||||
border-radius: 12px;
|
border-radius: 8px; /* Slightly smaller radius for tighter list */
|
||||||
color: #475569;
|
color: var(--sidebar-text);
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
font-weight: 600;
|
font-weight: 500;
|
||||||
border: 1px solid transparent;
|
border: 1px solid transparent;
|
||||||
transition: all 0.2s ease;
|
transition: all 0.2s ease;
|
||||||
|
margin-bottom: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.admin-nav-link:hover {
|
.admin-nav-link:hover {
|
||||||
background: #f1f5f9;
|
background: rgba(255, 255, 255, 0.05);
|
||||||
color: #0f172a;
|
color: var(--sidebar-text-hover);
|
||||||
}
|
}
|
||||||
|
|
||||||
.admin-nav-link.active {
|
.admin-nav-link.active {
|
||||||
background: #eff6ff;
|
background: var(--sidebar-active-bg);
|
||||||
color: var(--primary);
|
color: var(--sidebar-active-text);
|
||||||
border-color: #bfdbfe;
|
border-color: transparent;
|
||||||
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Collapsible Toggles in Sidebar */
|
||||||
|
.admin-sidebar .nav-link {
|
||||||
|
color: var(--sidebar-text) !important;
|
||||||
|
}
|
||||||
|
.admin-sidebar .nav-link:hover {
|
||||||
|
color: var(--sidebar-text-hover) !important;
|
||||||
|
background: rgba(255, 255, 255, 0.05);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Sub-menus borders */
|
||||||
|
.admin-sidebar .border-start {
|
||||||
|
border-color: var(--sidebar-border) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Logout button in sidebar */
|
||||||
|
.admin-sidebar .btn-outline-danger {
|
||||||
|
border-color: #ef4444;
|
||||||
|
color: #ef4444;
|
||||||
|
}
|
||||||
|
.admin-sidebar .btn-outline-danger:hover {
|
||||||
|
background: #ef4444;
|
||||||
|
color: #ffffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
[dir="rtl"] .navbar .ms-auto {
|
[dir="rtl"] .navbar .ms-auto {
|
||||||
@ -293,5 +368,6 @@ body.app-body {
|
|||||||
position: static;
|
position: static;
|
||||||
height: auto;
|
height: auto;
|
||||||
overflow-y: visible;
|
overflow-y: visible;
|
||||||
|
background-color: var(--sidebar-bg); /* Keep dark on mobile too */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -193,6 +193,7 @@ $translations = [
|
|||||||
'total_offers' => 'Total Offers',
|
'total_offers' => 'Total Offers',
|
||||||
'won_shipments' => 'Won Shipments',
|
'won_shipments' => 'Won Shipments',
|
||||||
'nav_platform_users' => 'Platform Users',
|
'nav_platform_users' => 'Platform Users',
|
||||||
|
'notification_templates' => 'Notification Templates',
|
||||||
'manage_permissions' => 'Manage Permissions',
|
'manage_permissions' => 'Manage Permissions',
|
||||||
'create_user' => 'Create User',
|
'create_user' => 'Create User',
|
||||||
'edit_user' => 'Edit User',
|
'edit_user' => 'Edit User',
|
||||||
@ -313,7 +314,7 @@ $translations = [
|
|||||||
'user_registration' => 'تسجيل المستخدم',
|
'user_registration' => 'تسجيل المستخدم',
|
||||||
'pages' => 'الصفحات',
|
'pages' => 'الصفحات',
|
||||||
'faqs' => 'الأسئلة الشائعة',
|
'faqs' => 'الأسئلة الشائعة',
|
||||||
'landing_pages' => 'صفحات الهبوط',
|
'landing_pages' => 'إعدادات الصفحة الرئيسية',
|
||||||
'login_title' => 'مرحبًا بعودتك',
|
'login_title' => 'مرحبًا بعودتك',
|
||||||
'login_subtitle' => 'قم بتسجيل الدخول إلى حسابك للمتابعة',
|
'login_subtitle' => 'قم بتسجيل الدخول إلى حسابك للمتابعة',
|
||||||
'email_address' => 'البريد الإلكتروني',
|
'email_address' => 'البريد الإلكتروني',
|
||||||
@ -385,6 +386,7 @@ $translations = [
|
|||||||
'total_offers' => 'إجمالي العروض',
|
'total_offers' => 'إجمالي العروض',
|
||||||
'won_shipments' => 'الشحنات الفائزة',
|
'won_shipments' => 'الشحنات الفائزة',
|
||||||
'nav_platform_users' => 'مستخدمو المنصة',
|
'nav_platform_users' => 'مستخدمو المنصة',
|
||||||
|
'notification_templates' => 'قوالب الإشعارات',
|
||||||
'manage_permissions' => 'إدارة الصلاحيات',
|
'manage_permissions' => 'إدارة الصلاحيات',
|
||||||
'create_user' => 'إنشاء مستخدم',
|
'create_user' => 'إنشاء مستخدم',
|
||||||
'edit_user' => 'تعديل المستخدم',
|
'edit_user' => 'تعديل المستخدم',
|
||||||
|
|||||||
@ -224,12 +224,12 @@ function render_admin_sidebar(string $active = 'dashboard'): void
|
|||||||
<aside class="admin-sidebar d-flex flex-column h-100 py-4 px-3">
|
<aside class="admin-sidebar d-flex flex-column h-100 py-4 px-3">
|
||||||
<h2 class="h5 fw-bold mb-4 px-2"><i class="bi bi-shield-lock me-2 text-primary"></i><?= e(t('nav_admin')) ?></h2>
|
<h2 class="h5 fw-bold mb-4 px-2"><i class="bi bi-shield-lock me-2 text-primary"></i><?= e(t('nav_admin')) ?></h2>
|
||||||
<nav class="nav flex-column gap-1 flex-grow-1">
|
<nav class="nav flex-column gap-1 flex-grow-1">
|
||||||
<a class="admin-nav-link <?= $active === 'shipments' ? 'active' : '' ?>" href="<?= e(url_with_lang('admin_shipments.php')) ?>">
|
|
||||||
<i class="bi bi-box2-fill me-2"></i><?= e(t('shipments') ?: 'Shipments') ?>
|
|
||||||
</a>
|
|
||||||
<a class="admin-nav-link <?= $active === 'dashboard' ? 'active' : '' ?>" href="<?= e(url_with_lang('admin_dashboard.php')) ?>">
|
<a class="admin-nav-link <?= $active === 'dashboard' ? 'active' : '' ?>" href="<?= e(url_with_lang('admin_dashboard.php')) ?>">
|
||||||
<i class="bi bi-speedometer2 me-2"></i><?= e(t('dashboard')) ?>
|
<i class="bi bi-speedometer2 me-2"></i><?= e(t('dashboard')) ?>
|
||||||
</a>
|
</a>
|
||||||
|
<a class="admin-nav-link <?= $active === 'shipments' ? 'active' : '' ?>" href="<?= e(url_with_lang('admin_shipments.php')) ?>">
|
||||||
|
<i class="bi bi-box2-fill me-2"></i><?= e(t('shipments') ?: 'Shipments') ?>
|
||||||
|
</a>
|
||||||
|
|
||||||
<a class="nav-link fw-bold text-muted text-uppercase mt-2 d-flex justify-content-between align-items-center p-2 rounded" style="cursor: pointer; font-size: 0.85rem;" data-bs-toggle="collapse" data-bs-target="#collapseSettings" aria-expanded="<?= $settingsActive ? 'true' : 'false' ?>">
|
<a class="nav-link fw-bold text-muted text-uppercase mt-2 d-flex justify-content-between align-items-center p-2 rounded" style="cursor: pointer; font-size: 0.85rem;" data-bs-toggle="collapse" data-bs-target="#collapseSettings" aria-expanded="<?= $settingsActive ? 'true' : 'false' ?>">
|
||||||
<span><i class="bi bi-gear-fill me-2"></i><?= e(t('settings')) ?></span>
|
<span><i class="bi bi-gear-fill me-2"></i><?= e(t('settings')) ?></span>
|
||||||
|
|||||||
@ -180,6 +180,19 @@ $translations_en = [
|
|||||||
'welcome_back_owner' => 'Find loads and submit your best rate.',
|
'welcome_back_owner' => 'Find loads and submit your best rate.',
|
||||||
'total_offers' => 'Total Offers',
|
'total_offers' => 'Total Offers',
|
||||||
'won_shipments' => 'Won Shipments',
|
'won_shipments' => 'Won Shipments',
|
||||||
|
'nav_platform_users' => 'Platform Users',
|
||||||
|
'notification_templates' => 'Notification Templates',
|
||||||
|
'manage_permissions' => 'Manage Permissions',
|
||||||
|
'create_user' => 'Create User',
|
||||||
|
'edit_user' => 'Edit User',
|
||||||
|
'delete_user' => 'Delete User',
|
||||||
|
'confirm_delete' => 'Are you sure you want to delete this user?',
|
||||||
|
'permissions' => 'Permissions',
|
||||||
|
'no_users' => 'No platform users found.',
|
||||||
|
'user_created' => 'User created successfully.',
|
||||||
|
'user_updated' => 'User updated successfully.',
|
||||||
|
'user_deleted' => 'User deleted successfully.',
|
||||||
|
'error_email_exists' => 'Email already exists.'
|
||||||
];
|
];
|
||||||
|
|
||||||
$translations_ar = [
|
$translations_ar = [
|
||||||
@ -290,7 +303,7 @@ $translations_ar = [
|
|||||||
'user_registration' => 'تسجيل المستخدم',
|
'user_registration' => 'تسجيل المستخدم',
|
||||||
'pages' => 'الصفحات',
|
'pages' => 'الصفحات',
|
||||||
'faqs' => 'الأسئلة الشائعة',
|
'faqs' => 'الأسئلة الشائعة',
|
||||||
'landing_pages' => 'صفحات الهبوط',
|
'landing_pages' => 'إعدادات الصفحة الرئيسية',
|
||||||
'login_title' => 'مرحبًا بعودتك',
|
'login_title' => 'مرحبًا بعودتك',
|
||||||
'login_subtitle' => 'قم بتسجيل الدخول إلى حسابك للمتابعة',
|
'login_subtitle' => 'قم بتسجيل الدخول إلى حسابك للمتابعة',
|
||||||
'email_address' => 'البريد الإلكتروني',
|
'email_address' => 'البريد الإلكتروني',
|
||||||
|
|||||||
@ -291,8 +291,8 @@ $flash = get_flash();
|
|||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
</td>
|
</td>
|
||||||
<td class="text-end">
|
<td class="text-end">
|
||||||
<a class="btn btn-sm btn-outline-primary rounded-pill px-3" href="<?= e(url_with_lang('shipment_detail.php', ['id' => $row['id']])) ?>">
|
<a class="btn btn-sm p-1 border-0 bg-transparent text-primary" href="<?= e(url_with_lang('shipment_detail.php', ['id' => $row['id']])) ?>" title="<?= e(t('view')) ?>">
|
||||||
<?= e(t('view')) ?>
|
<i class="bi bi-eye"></i>
|
||||||
</a>
|
</a>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|||||||
@ -174,8 +174,8 @@ $flash = get_flash();
|
|||||||
<span class="input-group-text">$</span>
|
<span class="input-group-text">$</span>
|
||||||
<input class="form-control border-secondary shadow-none" name="offer_price" type="number" step="0.01" min="0.1" placeholder="<?= e(t('offer_price')) ?>" required>
|
<input class="form-control border-secondary shadow-none" name="offer_price" type="number" step="0.01" min="0.1" placeholder="<?= e(t('offer_price')) ?>" required>
|
||||||
</div>
|
</div>
|
||||||
<button class="btn btn-sm btn-primary rounded px-3" type="submit"><i class="bi bi-send-fill"></i></button>
|
<button class="btn btn-sm p-1 border-0 bg-transparent text-primary" type="submit" title="Submit Offer"><i class="bi bi-send-fill"></i></button>
|
||||||
<a class="btn btn-sm btn-outline-dark rounded ms-1" href="<?= e(url_with_lang('shipment_detail.php', ['id' => $row['id']])) ?>" title="<?= e(t('view')) ?>">
|
<a class="btn btn-sm p-1 border-0 bg-transparent text-primary ms-1" href="<?= e(url_with_lang('shipment_detail.php', ['id' => $row['id']])) ?>" title="<?= e(t('view')) ?>">
|
||||||
<i class="bi bi-eye"></i>
|
<i class="bi bi-eye"></i>
|
||||||
</a>
|
</a>
|
||||||
</form>
|
</form>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user