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,88 +109,120 @@ 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">
|
||||||
<div class="col-md-6">
|
<li class="nav-item" role="presentation">
|
||||||
<label class="form-label fw-bold">Company / App Name</label>
|
<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">
|
||||||
<input type="text" name="company_name" class="form-control" value="<?= e($currentName) ?>" required>
|
<i class="bi bi-building me-2"></i>Company Setting
|
||||||
</div>
|
</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="col-md-6">
|
<div class="tab-content" id="companySettingsTabContent">
|
||||||
<label class="form-label fw-bold">Contact Email</label>
|
<!-- Tab 1: Company Setting -->
|
||||||
<input type="email" name="company_email" class="form-control" value="<?= e($currentEmail) ?>">
|
<div class="tab-pane fade show active" id="company" role="tabpanel" aria-labelledby="company-tab">
|
||||||
<div class="form-text">Displayed in the footer.</div>
|
<div class="row g-3">
|
||||||
</div>
|
<div class="col-md-6">
|
||||||
|
<label class="form-label fw-bold">Company / App Name</label>
|
||||||
|
<input type="text" name="company_name" class="form-control" value="<?= e($currentName) ?>" required>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<label class="form-label fw-bold">Contact Phone</label>
|
<label class="form-label fw-bold">Contact Email</label>
|
||||||
<input type="text" name="company_phone" class="form-control" value="<?= e($currentPhone) ?>">
|
<input type="email" name="company_email" class="form-control" value="<?= e($currentEmail) ?>">
|
||||||
<div class="form-text">Displayed in the footer.</div>
|
<div class="form-text">Displayed in the footer.</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<label class="form-label fw-bold">Address</label>
|
<label class="form-label fw-bold">Contact Phone</label>
|
||||||
<input type="text" name="company_address" class="form-control" value="<?= e($currentAddress) ?>">
|
<input type="text" name="company_phone" class="form-control" value="<?= e($currentPhone) ?>">
|
||||||
<div class="form-text">Displayed in the footer.</div>
|
<div class="form-text">Displayed in the footer.</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<label class="form-label fw-bold">Platform Charge (%)</label>
|
<label class="form-label fw-bold">Address</label>
|
||||||
<div class="input-group">
|
<input type="text" name="company_address" class="form-control" value="<?= e($currentAddress) ?>">
|
||||||
<input type="number" step="0.01" min="0" max="100" name="platform_charge_percentage" class="form-control" value="<?= e($currentPlatformCharge) ?>">
|
<div class="form-text">Displayed in the footer.</div>
|
||||||
<span class="input-group-text">%</span>
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-6">
|
||||||
|
<label class="form-label fw-bold">Platform Charge (%)</label>
|
||||||
|
<div class="input-group">
|
||||||
|
<input type="number" step="0.01" min="0" max="100" name="platform_charge_percentage" class="form-control" value="<?= e($currentPlatformCharge) ?>">
|
||||||
|
<span class="input-group-text">%</span>
|
||||||
|
</div>
|
||||||
|
<div class="form-text">Percentage applied as a platform fee.</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-12">
|
||||||
|
<hr class="my-2">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-6">
|
||||||
|
<label class="form-label fw-bold">Company Logo</label>
|
||||||
|
<?php if ($currentLogo): ?>
|
||||||
|
<div class="mb-2">
|
||||||
|
<img src="<?= e($currentLogo) ?>" alt="Logo" height="40" class="border rounded p-1">
|
||||||
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
<input type="file" name="logo_file" class="form-control" accept="image/*">
|
||||||
|
<div class="form-text">Recommended size: 150x40px (PNG, JPG, SVG). Leave empty to keep current.</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-6">
|
||||||
|
<label class="form-label fw-bold">Favicon</label>
|
||||||
|
<?php if ($currentFavicon): ?>
|
||||||
|
<div class="mb-2">
|
||||||
|
<img src="<?= e($currentFavicon) ?>" alt="Favicon" height="32" class="border rounded p-1">
|
||||||
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
<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>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-text">Percentage applied as a platform fee.</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="col-md-12">
|
<!-- Tab 2: Legal & Policies -->
|
||||||
<hr class="my-2">
|
<div class="tab-pane fade" id="legal" role="tabpanel" aria-labelledby="legal-tab">
|
||||||
</div>
|
<div class="row g-3">
|
||||||
|
<div class="col-12">
|
||||||
<div class="col-md-6">
|
<h5 class="fw-bold mb-3">Terms of Service</h5>
|
||||||
<label class="form-label fw-bold">Company Logo</label>
|
|
||||||
<?php if ($currentLogo): ?>
|
|
||||||
<div class="mb-2">
|
|
||||||
<img src="<?= e($currentLogo) ?>" alt="Logo" height="40" class="border rounded p-1">
|
|
||||||
</div>
|
</div>
|
||||||
<?php endif; ?>
|
<div class="col-md-6">
|
||||||
<input type="file" name="logo_file" class="form-control" accept="image/*">
|
<label class="form-label fw-bold">English</label>
|
||||||
<div class="form-text">Recommended size: 150x40px (PNG, JPG, SVG). Leave empty to keep current.</div>
|
<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">Favicon</label>
|
|
||||||
<?php if ($currentFavicon): ?>
|
|
||||||
<div class="mb-2">
|
|
||||||
<img src="<?= e($currentFavicon) ?>" alt="Favicon" height="32" class="border rounded p-1">
|
|
||||||
</div>
|
</div>
|
||||||
<?php endif; ?>
|
<div class="col-md-6">
|
||||||
<input type="file" name="favicon_file" class="form-control" accept="image/png, image/x-icon, image/svg+xml">
|
<label class="form-label fw-bold">Arabic</label>
|
||||||
<div class="form-text">Recommended size: 32x32px (ICO, PNG, SVG). Leave empty to keep current.</div>
|
<textarea name="terms_ar" class="form-control" rows="10" dir="rtl" placeholder="أدخل شروط الخدمة باللغة العربية..."><?= e($currentTermsAr) ?></textarea>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="col-md-12">
|
<!-- Tab 3: Privacy Policy -->
|
||||||
<hr class="my-2">
|
<div class="tab-pane fade" id="privacy" role="tabpanel" aria-labelledby="privacy-tab">
|
||||||
<h5 class="fw-bold mb-3">Legal & Policies</h5>
|
<div class="row g-3">
|
||||||
</div>
|
<div class="col-12">
|
||||||
|
<h5 class="fw-bold mb-3">Privacy Policy</h5>
|
||||||
<div class="col-md-6">
|
</div>
|
||||||
<label class="form-label fw-bold">Terms of Service (English)</label>
|
<div class="col-md-6">
|
||||||
<textarea name="terms_en" class="form-control" rows="5" placeholder="Enter Terms of Service in English..."><?= e($currentTermsEn) ?></textarea>
|
<label class="form-label fw-bold">English</label>
|
||||||
</div>
|
<textarea name="privacy_en" class="form-control" rows="10" placeholder="Enter Privacy Policy in English..."><?= e($currentPrivacyEn) ?></textarea>
|
||||||
|
</div>
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<label class="form-label fw-bold">Terms of Service (Arabic)</label>
|
<label class="form-label fw-bold">Arabic</label>
|
||||||
<textarea name="terms_ar" class="form-control" rows="5" dir="rtl" placeholder="أدخل شروط الخدمة باللغة العربية..."><?= e($currentTermsAr) ?></textarea>
|
<textarea name="privacy_ar" class="form-control" rows="10" dir="rtl" placeholder="أدخل سياسة الخصوصية باللغة العربية..."><?= e($currentPrivacyAr) ?></textarea>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
<div class="col-md-6">
|
|
||||||
<label class="form-label fw-bold">Privacy Policy (English)</label>
|
|
||||||
<textarea name="privacy_en" class="form-control" rows="5" placeholder="Enter Privacy Policy in English..."><?= e($currentPrivacyEn) ?></textarea>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="col-md-6">
|
|
||||||
<label class="form-label fw-bold">Privacy Policy (Arabic)</label>
|
|
||||||
<textarea name="privacy_ar" class="form-control" rows="5" dir="rtl" placeholder="أدخل سياسة الخصوصية باللغة العربية..."><?= e($currentPrivacyAr) ?></textarea>
|
|
||||||
</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,107 +85,113 @@ 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>
|
||||||
<?php if ($flash): ?>
|
<div class="p-4 flex-grow-1 d-flex flex-column">
|
||||||
<div class="alert alert-success" data-auto-dismiss="true"><?= e($flash['message']) ?></div>
|
<?php if ($flash): ?>
|
||||||
<?php endif; ?>
|
<div class="alert alert-success" data-auto-dismiss="true"><?= e($flash['message']) ?></div>
|
||||||
<?php if ($errors): ?>
|
<?php endif; ?>
|
||||||
<div class="alert alert-warning"><?= e(implode(' ', $errors)) ?></div>
|
<?php if ($errors): ?>
|
||||||
<?php endif; ?>
|
<div class="alert alert-warning"><?= e(implode(' ', $errors)) ?></div>
|
||||||
<?php if (!$shipments): ?>
|
<?php endif; ?>
|
||||||
<div class="text-center p-5 text-muted flex-grow-1 d-flex flex-column justify-content-center">
|
<?php if (!$shipments): ?>
|
||||||
<i class="bi bi-inbox fs-1 mb-3 d-block opacity-50"></i>
|
<div class="text-center p-5 text-muted flex-grow-1 d-flex flex-column justify-content-center">
|
||||||
<p class="mb-0"><?= e(t('no_shipments')) ?></p>
|
<i class="bi bi-inbox fs-1 mb-3 d-block opacity-50"></i>
|
||||||
</div>
|
<p class="mb-0"><?= e(t('no_shipments')) ?></p>
|
||||||
<?php else: ?>
|
</div>
|
||||||
<div class="table-responsive flex-grow-1">
|
<?php else: ?>
|
||||||
<table class="table align-middle mb-0">
|
<div class="table-responsive flex-grow-1">
|
||||||
<thead>
|
<table class="table align-middle mb-0">
|
||||||
<tr>
|
<thead>
|
||||||
<th class="text-uppercase small text-muted border-top-0">Shipment</th>
|
|
||||||
<th class="text-uppercase small text-muted border-top-0">Route</th>
|
|
||||||
<th class="text-uppercase small text-muted border-top-0"><?= e(t('status')) ?></th>
|
|
||||||
<th class="text-uppercase small text-muted border-top-0 text-end">Action</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<?php foreach ($shipments as $row): ?>
|
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<th class="text-uppercase small text-muted border-top-0">Shipment</th>
|
||||||
<div class="fw-bold"><?= e($row['shipper_company']) ?></div>
|
<th class="text-uppercase small text-muted border-top-0">Route</th>
|
||||||
<small class="text-muted"><?= e($row['payment_method'] === 'bank_transfer' ? t('payment_bank') : t('payment_thawani')) ?></small>
|
<th class="text-uppercase small text-muted border-top-0"><?= e(t('status')) ?></th>
|
||||||
</td>
|
<th class="text-uppercase small text-muted border-top-0 text-end">Action</th>
|
||||||
<td>
|
|
||||||
<div class="d-flex align-items-center gap-2">
|
|
||||||
<span class="fw-medium"><?= e($row['origin_city']) ?></span>
|
|
||||||
<i class="bi bi-arrow-right text-muted small"></i>
|
|
||||||
<span class="fw-medium"><?= e($row['destination_city']) ?></span>
|
|
||||||
</div>
|
|
||||||
</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">
|
|
||||||
<a href="<?= e(url_with_lang('shipment_detail.php', ['id' => $row['id']])) ?>" class="btn btn-sm btn-outline-primary rounded-pill px-3">
|
|
||||||
View Details
|
|
||||||
</a>
|
|
||||||
</td>
|
|
||||||
</tr>
|
</tr>
|
||||||
<?php endforeach; ?>
|
</thead>
|
||||||
</tbody>
|
<tbody>
|
||||||
</table>
|
<?php foreach ($shipments as $row): ?>
|
||||||
</div>
|
<tr>
|
||||||
<?php endif; ?>
|
<td>
|
||||||
|
<div class="fw-bold"><?= e($row['shipper_company']) ?></div>
|
||||||
|
<small class="text-muted"><?= e($row['payment_method'] === 'bank_transfer' ? t('payment_bank') : t('payment_thawani')) ?></small>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div class="d-flex align-items-center gap-2">
|
||||||
|
<span class="fw-medium"><?= e($row['origin_city']) ?></span>
|
||||||
|
<i class="bi bi-arrow-right text-muted small"></i>
|
||||||
|
<span class="fw-medium"><?= e($row['destination_city']) ?></span>
|
||||||
|
</div>
|
||||||
|
</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">
|
||||||
|
<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">
|
||||||
|
<i class="bi bi-eye"></i>
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<?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">
|
||||||
<div class="list-group list-group-flush bg-transparent">
|
<h2 class="h5 mb-0 fw-bold text-white"><i class="bi bi-lightning-charge text-warning me-2"></i>Quick Links</h2>
|
||||||
<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>
|
||||||
<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="p-4">
|
||||||
<div>
|
<div class="list-group list-group-flush bg-transparent">
|
||||||
<h6 class="mb-1 fw-bold">Manage Countries</h6>
|
<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">
|
||||||
<small class="text-muted d-block line-height-sm">Add or remove supported countries</small>
|
<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>
|
<div>
|
||||||
<i class="bi bi-chevron-right ms-auto text-muted small"></i>
|
<h6 class="mb-1 fw-bold">Manage Countries</h6>
|
||||||
</a>
|
<small class="text-muted d-block line-height-sm">Add or remove supported countries</small>
|
||||||
<a href="<?= e(url_with_lang('admin_cities.php')) ?>" class="list-group-item list-group-item-action bg-transparent border-bottom d-flex align-items-center py-3 px-0">
|
</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-pin-map fs-5"></i></div>
|
<i class="bi bi-chevron-right ms-auto text-muted small"></i>
|
||||||
<div>
|
</a>
|
||||||
<h6 class="mb-1 fw-bold">Manage Cities</h6>
|
<a href="<?= e(url_with_lang('admin_cities.php')) ?>" class="list-group-item list-group-item-action bg-transparent border-bottom d-flex align-items-center py-3 px-0">
|
||||||
<small class="text-muted d-block line-height-sm">Configure cities for routing</small>
|
<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-pin-map fs-5"></i></div>
|
||||||
</div>
|
<div>
|
||||||
<i class="bi bi-chevron-right ms-auto text-muted small"></i>
|
<h6 class="mb-1 fw-bold">Manage Cities</h6>
|
||||||
</a>
|
<small class="text-muted d-block line-height-sm">Configure cities for routing</small>
|
||||||
<a href="<?= e(url_with_lang('register.php')) ?>" class="list-group-item list-group-item-action bg-transparent border-bottom d-flex align-items-center py-3 px-0">
|
</div>
|
||||||
<div class="bg-white rounded p-3 shadow-sm me-3 text-success d-flex align-items-center justify-content-center" style="width: 48px; height: 48px;"><i class="bi bi-person-plus fs-5"></i></div>
|
<i class="bi bi-chevron-right ms-auto text-muted small"></i>
|
||||||
<div>
|
</a>
|
||||||
<h6 class="mb-1 fw-bold">Register User</h6>
|
<a href="<?= e(url_with_lang('register.php')) ?>" class="list-group-item list-group-item-action bg-transparent border-bottom d-flex align-items-center py-3 px-0">
|
||||||
<small class="text-muted d-block line-height-sm">Manually onboard a new user</small>
|
<div class="bg-white rounded p-3 shadow-sm me-3 text-success d-flex align-items-center justify-content-center" style="width: 48px; height: 48px;"><i class="bi bi-person-plus fs-5"></i></div>
|
||||||
</div>
|
<div>
|
||||||
<i class="bi bi-chevron-right ms-auto text-muted small"></i>
|
<h6 class="mb-1 fw-bold">Register User</h6>
|
||||||
</a>
|
<small class="text-muted d-block line-height-sm">Manually onboard a new user</small>
|
||||||
<a href="<?= e(url_with_lang('admin_company_profile.php')) ?>" class="list-group-item list-group-item-action bg-transparent border-bottom d-flex align-items-center py-3 px-0">
|
</div>
|
||||||
<div class="bg-white rounded p-3 shadow-sm me-3 text-secondary d-flex align-items-center justify-content-center" style="width: 48px; height: 48px;"><i class="bi bi-buildings fs-5"></i></div>
|
<i class="bi bi-chevron-right ms-auto text-muted small"></i>
|
||||||
<div>
|
</a>
|
||||||
<h6 class="mb-1 fw-bold">Company Profile</h6>
|
<a href="<?= e(url_with_lang('admin_company_profile.php')) ?>" class="list-group-item list-group-item-action bg-transparent border-bottom d-flex align-items-center py-3 px-0">
|
||||||
<small class="text-muted d-block line-height-sm">Update platform branding</small>
|
<div class="bg-white rounded p-3 shadow-sm me-3 text-secondary d-flex align-items-center justify-content-center" style="width: 48px; height: 48px;"><i class="bi bi-buildings fs-5"></i></div>
|
||||||
</div>
|
<div>
|
||||||
<i class="bi bi-chevron-right ms-auto text-muted small"></i>
|
<h6 class="mb-1 fw-bold">Company Profile</h6>
|
||||||
</a>
|
<small class="text-muted d-block line-height-sm">Update platform branding</small>
|
||||||
<a href="<?= e(url_with_lang('admin_landing_pages.php')) ?>" class="list-group-item list-group-item-action bg-transparent d-flex align-items-center py-3 px-0">
|
</div>
|
||||||
<div class="bg-white rounded p-3 shadow-sm me-3 text-info d-flex align-items-center justify-content-center" style="width: 48px; height: 48px;"><i class="bi bi-layout-text-window-reverse fs-5"></i></div>
|
<i class="bi bi-chevron-right ms-auto text-muted small"></i>
|
||||||
<div>
|
</a>
|
||||||
<h6 class="mb-1 fw-bold">Landing Pages</h6>
|
<a href="<?= e(url_with_lang('admin_landing_pages.php')) ?>" class="list-group-item list-group-item-action bg-transparent d-flex align-items-center py-3 px-0">
|
||||||
<small class="text-muted d-block line-height-sm">Edit homepage content and sections</small>
|
<div class="bg-white rounded p-3 shadow-sm me-3 text-info d-flex align-items-center justify-content-center" style="width: 48px; height: 48px;"><i class="bi bi-layout-text-window-reverse fs-5"></i></div>
|
||||||
</div>
|
<div>
|
||||||
<i class="bi bi-chevron-right ms-auto text-muted small"></i>
|
<h6 class="mb-1 fw-bold">Landing Pages</h6>
|
||||||
</a>
|
<small class="text-muted d-block line-height-sm">Edit homepage content and sections</small>
|
||||||
|
</div>
|
||||||
|
<i class="bi bi-chevron-right ms-auto text-muted small"></i>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -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,129 +73,158 @@ render_header('Integrations', 'admin', true);
|
|||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
|
|
||||||
<form method="post">
|
<form method="post">
|
||||||
<!-- Thawani Payments Panel -->
|
|
||||||
<div class="panel p-4 mb-4">
|
|
||||||
<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">
|
|
||||||
<path d="M0 4a2 2 0 0 1 2-2h12a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2zm2-1a1 1 0 0 0-1 1v1h14V4a1 1 0 0 0-1-1zm13 4H1v5a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1z"/>
|
|
||||||
<path d="M2 10a1 1 0 0 1 1-1h1a1 1 0 0 1 1 1v1a1 1 0 0 1-1 1H3a1 1 0 0 1-1-1z"/>
|
|
||||||
</svg>
|
|
||||||
Thawani Payments Gateway
|
|
||||||
</h3>
|
|
||||||
<p class="text-muted small mb-4">Configure your Oman-based Thawani Pay integration to process shipment payments.</p>
|
|
||||||
|
|
||||||
<div class="row g-0">
|
<ul class="nav nav-tabs mb-4" id="integrationsTab" role="tablist">
|
||||||
<div class="col-md-6">
|
<li class="nav-item" role="presentation">
|
||||||
<label class="form-label fw-bold">Environment</label>
|
<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">
|
||||||
<select name="thawani_environment" class="form-select">
|
Thawani Gateway
|
||||||
<option value="test" <?= $thawaniEnv === 'test' ? 'selected' : '' ?>>Test / Sandbox</option>
|
</button>
|
||||||
<option value="live" <?= $thawaniEnv === 'live' ? 'selected' : '' ?>>Live / Production</option>
|
</li>
|
||||||
</select>
|
<li class="nav-item" role="presentation">
|
||||||
</div>
|
<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">
|
||||||
<div class="col-md-6"></div>
|
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="col-md-6">
|
<div class="tab-content" id="integrationsTabContent">
|
||||||
<label class="form-label fw-bold">Publishable Key</label>
|
|
||||||
<input type="text" name="thawani_publishable_key" class="form-control" value="<?= e($thawaniPub) ?>" placeholder="pk_test_...">
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="col-md-6">
|
<!-- Thawani Payments Panel -->
|
||||||
<label class="form-label fw-bold">Secret Key</label>
|
<div class="tab-pane fade show active" id="thawani" role="tabpanel" aria-labelledby="thawani-tab">
|
||||||
<input type="password" name="thawani_secret_key" class="form-control" value="<?= e($thawaniSec) ?>" placeholder="sk_test_...">
|
<div class="panel p-4 mb-4">
|
||||||
</div>
|
<h3 class="h5 fw-bold mb-3 d-flex align-items-center">
|
||||||
</div>
|
<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">
|
||||||
</div>
|
<path d="M0 4a2 2 0 0 1 2-2h12a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2zm2-1a1 1 0 0 0-1 1v1h14V4a1 1 0 0 0-1-1zm13 4H1v5a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1z"/>
|
||||||
|
<path d="M2 10a1 1 0 0 1 1-1h1a1 1 0 0 1 1 1v1a1 1 0 0 1-1 1H3a1 1 0 0 1-1-1z"/>
|
||||||
|
</svg>
|
||||||
|
Thawani Payments Gateway
|
||||||
|
</h3>
|
||||||
|
<p class="text-muted small mb-4">Configure your Oman-based Thawani Pay integration to process shipment payments.</p>
|
||||||
|
|
||||||
<!-- Wablas WhatsApp Gateway Panel -->
|
<div class="row g-0">
|
||||||
<div class="panel p-4 mb-4">
|
<div class="col-md-6">
|
||||||
<h3 class="h5 fw-bold mb-3 d-flex align-items-center">
|
<label class="form-label fw-bold">Environment</label>
|
||||||
<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">
|
<select name="thawani_environment" class="form-select">
|
||||||
<path d="M13.601 2.326A7.85 7.85 0 0 0 7.994 0C3.627 0 .068 3.558.064 7.926c0 1.399.366 2.76 1.057 3.965L0 16l4.204-1.102a7.9 7.9 0 0 0 3.79.965h.004c4.368 0 7.926-3.558 7.93-7.93A7.9 7.9 0 0 0 13.6 2.326zM7.994 14.521a6.6 6.6 0 0 1-3.356-.92l-.24-.144-2.494.654.666-2.433-.156-.251a6.56 6.56 0 0 1-1.007-3.505c0-3.626 2.957-6.584 6.591-6.584a6.56 6.56 0 0 1 4.66 1.931 6.56 6.56 0 0 1 1.928 4.66c-.004 3.639-2.961 6.592-6.592 6.592m3.615-4.934c-.197-.099-1.17-.578-1.353-.646-.182-.065-.315-.099-.445.099-.133.197-.513.646-.627.775-.114.133-.232.148-.43.05-.197-.1-.836-.308-1.592-.985-.59-.525-.985-1.175-1.103-1.372-.114-.198-.011-.304.088-.403.087-.088.197-.232.296-.346.1-.114.133-.198.198-.33.065-.134.034-.248-.015-.347-.05-.099-.445-1.076-.612-1.47-.16-.389-.323-.335-.445-.34-.114-.007-.247-.007-.38-.007a.73.73 0 0 0-.529.247c-.182.198-.691.677-.691 1.654s.71 1.916.81 2.049c.098.133 1.394 2.132 3.383 2.992.47.205.84.326 1.129.418.475.152.904.129 1.246.08.38-.058 1.171-.48 1.338-.943.164-.464.164-.86.114-.943-.049-.084-.182-.133-.38-.232"/>
|
<option value="test" <?= $thawaniEnv === 'test' ? 'selected' : '' ?>>Test / Sandbox</option>
|
||||||
</svg>
|
<option value="live" <?= $thawaniEnv === 'live' ? 'selected' : '' ?>>Live / Production</option>
|
||||||
Wablas WhatsApp Gateway
|
</select>
|
||||||
</h3>
|
</div>
|
||||||
<p class="text-muted small mb-4">Connect Wablas to automatically send WhatsApp notifications to Shippers and Truck Owners.</p>
|
<div class="col-md-6"></div>
|
||||||
|
|
||||||
<div class="row g-0">
|
<div class="col-md-6">
|
||||||
<div class="col-12 mb-3">
|
<label class="form-label fw-bold">Publishable Key</label>
|
||||||
<div class="form-check form-switch">
|
<input type="text" name="thawani_publishable_key" class="form-control" value="<?= e($thawaniPub) ?>" placeholder="pk_test_...">
|
||||||
<input class="form-check-input" type="checkbox" name="whatsapp_enabled" id="whatsapp_enabled" value="1" <?= $whatsappEnabled === '1' ? 'checked' : '' ?>>
|
</div>
|
||||||
<label class="form-check-label fw-bold" for="whatsapp_enabled">Enable WhatsApp Notifications</label>
|
|
||||||
|
<div class="col-md-6">
|
||||||
|
<label class="form-label fw-bold">Secret Key</label>
|
||||||
|
<input type="password" name="thawani_secret_key" class="form-control" value="<?= e($thawaniSec) ?>" placeholder="sk_test_...">
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="col-md-6">
|
<!-- Wablas WhatsApp Gateway Panel -->
|
||||||
<label class="form-label fw-bold">Wablas Server Domain</label>
|
<div class="tab-pane fade" id="whatsapp" role="tabpanel" aria-labelledby="whatsapp-tab">
|
||||||
<input type="text" name="wablas_domain" class="form-control" value="<?= e($wablasDomain) ?>" placeholder="e.g. https://solo.wablas.com">
|
<div class="panel p-4 mb-4">
|
||||||
<div class="form-text">Your assigned server node from the Wablas dashboard.</div>
|
<h3 class="h5 fw-bold mb-3 d-flex align-items-center">
|
||||||
</div>
|
<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">
|
||||||
|
<path d="M13.601 2.326A7.85 7.85 0 0 0 7.994 0C3.627 0 .068 3.558.064 7.926c0 1.399.366 2.76 1.057 3.965L0 16l4.204-1.102a7.9 7.9 0 0 0 3.79.965h.004c4.368 0 7.926-3.558 7.93-7.93A7.9 7.9 0 0 0 13.6 2.326zM7.994 14.521a6.6 6.6 0 0 1-3.356-.92l-.24-.144-2.494.654.666-2.433-.156-.251a6.56 6.56 0 0 1-1.007-3.505c0-3.626 2.957-6.584 6.591-6.584a6.56 6.56 0 0 1 4.66 1.931 6.56 6.56 0 0 1 1.928 4.66c-.004 3.639-2.961 6.592-6.592 6.592m3.615-4.934c-.197-.099-1.17-.578-1.353-.646-.182-.065-.315-.099-.445.099-.133.197-.513.646-.627.775-.114.133-.232.148-.43.05-.197-.1-.836-.308-1.592-.985-.59-.525-.985-1.175-1.103-1.372-.114-.198-.011-.304.088-.403.087-.088.197-.232.296-.346.1-.114.133-.198.198-.33.065-.134.034-.248-.015-.347-.05-.099-.445-1.076-.612-1.47-.16-.389-.323-.335-.445-.34-.114-.007-.247-.007-.38-.007a.73.73 0 0 0-.529.247c-.182.198-.691.677-.691 1.654s.71 1.916.81 2.049c.098.133 1.394 2.132 3.383 2.992.47.205.84.326 1.129.418.475.152.904.129 1.246.08.38-.058 1.171-.48 1.338-.943.164-.464.164-.86.114-.943-.049-.084-.182-.133-.38-.232"/>
|
||||||
|
</svg>
|
||||||
|
Wablas WhatsApp Gateway
|
||||||
|
</h3>
|
||||||
|
<p class="text-muted small mb-4">Connect Wablas to automatically send WhatsApp notifications to Shippers and Truck Owners.</p>
|
||||||
|
|
||||||
<div class="col-md-6">
|
<div class="row g-0">
|
||||||
<label class="form-label fw-bold">API Token</label>
|
<div class="col-12 mb-3">
|
||||||
<input type="password" name="wablas_api_token" class="form-control" value="<?= e($wablasToken) ?>" placeholder="API Token">
|
<div class="form-check form-switch">
|
||||||
</div>
|
<input class="form-check-input" type="checkbox" name="whatsapp_enabled" id="whatsapp_enabled" value="1" <?= $whatsappEnabled === '1' ? 'checked' : '' ?>>
|
||||||
|
<label class="form-check-label fw-bold" for="whatsapp_enabled">Enable WhatsApp Notifications</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<label class="form-label fw-bold">Secret Key</label>
|
<label class="form-label fw-bold">Wablas Server Domain</label>
|
||||||
<input type="password" name="wablas_secret_key" class="form-control" value="<?= e($wablasSecret) ?>" placeholder="Secret Key">
|
<input type="text" name="wablas_domain" class="form-control" value="<?= e($wablasDomain) ?>" placeholder="e.g. https://solo.wablas.com">
|
||||||
<div class="form-text">Optional. Provide if your Wablas webhooks require signature verification.</div>
|
<div class="form-text">Your assigned server node from the Wablas dashboard.</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-6">
|
||||||
|
<label class="form-label fw-bold">API Token</label>
|
||||||
|
<input type="password" name="wablas_api_token" class="form-control" value="<?= e($wablasToken) ?>" placeholder="API Token">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-6">
|
||||||
|
<label class="form-label fw-bold">Secret Key</label>
|
||||||
|
<input type="password" name="wablas_secret_key" class="form-control" value="<?= e($wablasSecret) ?>" placeholder="Secret Key">
|
||||||
|
<div class="form-text">Optional. Provide if your Wablas webhooks require signature verification.</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- SMTP Mail Gateway Panel -->
|
<!-- SMTP Mail Gateway Panel -->
|
||||||
<div class="panel p-4 mb-4">
|
<div class="tab-pane fade" id="smtp" role="tabpanel" aria-labelledby="smtp-tab">
|
||||||
<h3 class="h5 fw-bold mb-3 d-flex align-items-center">
|
<div class="panel p-4 mb-4">
|
||||||
<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">
|
<h3 class="h5 fw-bold mb-3 d-flex align-items-center">
|
||||||
<path d="M0 4a2 2 0 0 1 2-2h12a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2V4Zm2-1a1 1 0 0 0-1 1v.217l7 4.2 7-4.2V4a1 1 0 0 0-1-1H2Zm13 2.383-4.708 2.825L15 11.105V5.383Zm-.034 6.876-5.64-3.471L8 9.583l-1.326-.795-5.64 3.47A1 1 0 0 0 2 13h12a1 1 0 0 0 .966-.741ZM1 11.105l4.708-2.897L1 5.383v5.722Z"/>
|
<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>
|
<path d="M0 4a2 2 0 0 1 2-2h12a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2V4Zm2-1a1 1 0 0 0-1 1v.217l7 4.2 7-4.2V4a1 1 0 0 0-1-1H2Zm13 2.383-4.708 2.825L15 11.105V5.383Zm-.034 6.876-5.64-3.471L8 9.583l-1.326-.795-5.64 3.47A1 1 0 0 0 2 13h12a1 1 0 0 0 .966-.741ZM1 11.105l4.708-2.897L1 5.383v5.722Z"/>
|
||||||
SMTP Mail Settings
|
</svg>
|
||||||
</h3>
|
SMTP Mail Settings
|
||||||
<p class="text-muted small mb-4">Configure your SMTP server to send emails and system notifications.</p>
|
</h3>
|
||||||
|
<p class="text-muted small mb-4">Configure your SMTP server to send emails and system notifications.</p>
|
||||||
|
|
||||||
<div class="row g-0">
|
<div class="row g-0">
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<label class="form-label fw-bold">SMTP Host</label>
|
<label class="form-label fw-bold">SMTP Host</label>
|
||||||
<input type="text" name="smtp_host" class="form-control" value="<?= e($smtpHost) ?>" placeholder="smtp.example.com">
|
<input type="text" name="smtp_host" class="form-control" value="<?= e($smtpHost) ?>" placeholder="smtp.example.com">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="col-md-3">
|
<div class="col-md-3">
|
||||||
<label class="form-label fw-bold">SMTP Port</label>
|
<label class="form-label fw-bold">SMTP Port</label>
|
||||||
<input type="number" name="smtp_port" class="form-control" value="<?= e($smtpPort) ?>" placeholder="587">
|
<input type="number" name="smtp_port" class="form-control" value="<?= e($smtpPort) ?>" placeholder="587">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="col-md-3">
|
<div class="col-md-3">
|
||||||
<label class="form-label fw-bold">Security</label>
|
<label class="form-label fw-bold">Security</label>
|
||||||
<select name="smtp_secure" class="form-select">
|
<select name="smtp_secure" class="form-select">
|
||||||
<option value="tls" <?= $smtpSecure === 'tls' ? 'selected' : '' ?>>TLS</option>
|
<option value="tls" <?= $smtpSecure === 'tls' ? 'selected' : '' ?>>TLS</option>
|
||||||
<option value="ssl" <?= $smtpSecure === 'ssl' ? 'selected' : '' ?>>SSL</option>
|
<option value="ssl" <?= $smtpSecure === 'ssl' ? 'selected' : '' ?>>SSL</option>
|
||||||
<option value="none" <?= $smtpSecure === 'none' || $smtpSecure === '' ? 'selected' : '' ?>>None</option>
|
<option value="none" <?= $smtpSecure === 'none' || $smtpSecure === '' ? 'selected' : '' ?>>None</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<label class="form-label fw-bold">SMTP Username</label>
|
<label class="form-label fw-bold">SMTP Username</label>
|
||||||
<input type="text" name="smtp_user" class="form-control" value="<?= e($smtpUser) ?>" placeholder="user@example.com">
|
<input type="text" name="smtp_user" class="form-control" value="<?= e($smtpUser) ?>" placeholder="user@example.com">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<label class="form-label fw-bold">SMTP Password</label>
|
<label class="form-label fw-bold">SMTP Password</label>
|
||||||
<input type="password" name="smtp_pass" class="form-control" value="<?= e($smtpPass) ?>" placeholder="••••••••">
|
<input type="password" name="smtp_pass" class="form-control" value="<?= e($smtpPass) ?>" placeholder="••••••••">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<label class="form-label fw-bold">Mail From Address</label>
|
<label class="form-label fw-bold">Mail From Address</label>
|
||||||
<input type="email" name="mail_from" class="form-control" value="<?= e($mailFrom) ?>" placeholder="noreply@example.com">
|
<input type="email" name="mail_from" class="form-control" value="<?= e($mailFrom) ?>" placeholder="noreply@example.com">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<label class="form-label fw-bold">Mail From Name</label>
|
<label class="form-label fw-bold">Mail From Name</label>
|
||||||
<input type="text" name="mail_from_name" class="form-control" value="<?= e($mailFromName) ?>" placeholder="CargoLink System">
|
<input type="text" name="mail_from_name" class="form-control" value="<?= e($mailFromName) ?>" placeholder="CargoLink System">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="d-flex justify-content-end">
|
<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,127 +167,154 @@ 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="row g-3">
|
<div class="p-4">
|
||||||
<div class="col-md-6">
|
<?php endif; // End non-ajax wrapper ?>
|
||||||
<label class="form-label">Shipper Name</label>
|
|
||||||
<input type="text" name="shipper_name" class="form-control" value="<?= e($shipment['shipper_name']) ?>" required>
|
<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>
|
||||||
<div class="col-md-6">
|
<div class="modal-body">
|
||||||
<label class="form-label">Shipper Company</label>
|
<div id="form-errors" class="alert alert-danger d-none"></div>
|
||||||
<input type="text" name="shipper_company" class="form-control" value="<?= e((string)$shipment['shipper_company']) ?>">
|
<?php endif; ?>
|
||||||
|
|
||||||
|
<div class="row g-3">
|
||||||
|
<div class="col-md-6">
|
||||||
|
<label class="form-label">Shipper Name</label>
|
||||||
|
<input type="text" name="shipper_name" class="form-control" value="<?= e($shipment['shipper_name']) ?>" required>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6">
|
||||||
|
<label class="form-label">Shipper Company</label>
|
||||||
|
<input type="text" name="shipper_company" class="form-control" value="<?= e((string)$shipment['shipper_company']) ?>">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Origin Selection -->
|
||||||
|
<div class="col-md-6">
|
||||||
|
<label class="form-label">Origin Country</label>
|
||||||
|
<select class="form-select" id="origin_country">
|
||||||
|
<option value="">Select Country</option>
|
||||||
|
<?php foreach ($countries as $c): ?>
|
||||||
|
<option value="<?= e($c['id']) ?>" <?= $c['id'] == $origin_country_id ? 'selected' : '' ?>>
|
||||||
|
<?= e($c['name_en']) ?>
|
||||||
|
</option>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6">
|
||||||
|
<label class="form-label">Origin City</label>
|
||||||
|
<select class="form-select" name="origin_city" id="origin_city" required>
|
||||||
|
<option value="">Select City</option>
|
||||||
|
<!-- If shipment has a city but we couldn't match a country, preserve the value as a fallback option -->
|
||||||
|
<?php if (!$origin_country_id && $shipment['origin_city']): ?>
|
||||||
|
<option value="<?= e($shipment['origin_city']) ?>" selected><?= e($shipment['origin_city']) ?></option>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
|
<?php foreach ($origin_cities_list as $city): ?>
|
||||||
|
<option value="<?= e($city['name_en']) ?>" <?= $city['name_en'] === $shipment['origin_city'] ? 'selected' : '' ?>>
|
||||||
|
<?= e($city['name_en']) ?>
|
||||||
|
</option>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Destination Selection -->
|
||||||
|
<div class="col-md-6">
|
||||||
|
<label class="form-label">Destination Country</label>
|
||||||
|
<select class="form-select" id="destination_country">
|
||||||
|
<option value="">Select Country</option>
|
||||||
|
<?php foreach ($countries as $c): ?>
|
||||||
|
<option value="<?= e($c['id']) ?>" <?= $c['id'] == $destination_country_id ? 'selected' : '' ?>>
|
||||||
|
<?= e($c['name_en']) ?>
|
||||||
|
</option>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6">
|
||||||
|
<label class="form-label">Destination City</label>
|
||||||
|
<select class="form-select" name="destination_city" id="destination_city" required>
|
||||||
|
<option value="">Select City</option>
|
||||||
|
<!-- Fallback for unmapped city -->
|
||||||
|
<?php if (!$destination_country_id && $shipment['destination_city']): ?>
|
||||||
|
<option value="<?= e($shipment['destination_city']) ?>" selected><?= e($shipment['destination_city']) ?></option>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
|
<?php foreach ($destination_cities_list as $city): ?>
|
||||||
|
<option value="<?= e($city['name_en']) ?>" <?= $city['name_en'] === $shipment['destination_city'] ? 'selected' : '' ?>>
|
||||||
|
<?= e($city['name_en']) ?>
|
||||||
|
</option>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-12">
|
||||||
|
<label class="form-label">Cargo Description</label>
|
||||||
|
<input type="text" name="cargo_description" class="form-control" value="<?= e((string)$shipment['cargo_description']) ?>">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-4">
|
||||||
|
<label class="form-label">Weight (Tons)</label>
|
||||||
|
<input type="number" step="0.1" name="weight_tons" class="form-control" value="<?= e((string)$shipment['weight_tons']) ?>">
|
||||||
|
</div>
|
||||||
|
<div class="col-md-4">
|
||||||
|
<label class="form-label">Pickup Date</label>
|
||||||
|
<input type="date" name="pickup_date" class="form-control" value="<?= e((string)$shipment['pickup_date']) ?>">
|
||||||
|
</div>
|
||||||
|
<div class="col-md-4">
|
||||||
|
<label class="form-label">Delivery Date</label>
|
||||||
|
<input type="date" name="delivery_date" class="form-control" value="<?= e((string)$shipment['delivery_date']) ?>">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-6">
|
||||||
|
<label class="form-label">Payment Method</label>
|
||||||
|
<select name="payment_method" class="form-select">
|
||||||
|
<option value="thawani" <?= $shipment['payment_method'] === 'thawani' ? 'selected' : '' ?>>Thawani</option>
|
||||||
|
<option value="bank_transfer" <?= $shipment['payment_method'] === 'bank_transfer' ? 'selected' : '' ?>>Bank Transfer</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6">
|
||||||
|
<label class="form-label">Status</label>
|
||||||
|
<select name="status" class="form-select">
|
||||||
|
<option value="posted" <?= $shipment['status'] === 'posted' ? 'selected' : '' ?>>Posted</option>
|
||||||
|
<option value="offered" <?= $shipment['status'] === 'offered' ? 'selected' : '' ?>>Offered</option>
|
||||||
|
<option value="confirmed" <?= $shipment['status'] === 'confirmed' ? 'selected' : '' ?>>Confirmed</option>
|
||||||
|
<option value="in_transit" <?= $shipment['status'] === 'in_transit' ? 'selected' : '' ?>>In Transit</option>
|
||||||
|
<option value="delivered" <?= $shipment['status'] === 'delivered' ? 'selected' : '' ?>>Delivered</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Origin Selection -->
|
<?php if ($isAjax): ?>
|
||||||
<div class="col-md-6">
|
</div> <!-- modal-body end -->
|
||||||
<label class="form-label">Origin Country</label>
|
<div class="modal-footer">
|
||||||
<select class="form-select" id="origin_country">
|
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
|
||||||
<option value="">Select Country</option>
|
<button type="submit" class="btn btn-primary">Save Changes</button>
|
||||||
<?php foreach ($countries as $c): ?>
|
|
||||||
<option value="<?= e($c['id']) ?>" <?= $c['id'] == $origin_country_id ? 'selected' : '' ?>>
|
|
||||||
<?= e($c['name_en']) ?>
|
|
||||||
</option>
|
|
||||||
<?php endforeach; ?>
|
|
||||||
</select>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-6">
|
<?php else: ?>
|
||||||
<label class="form-label">Origin City</label>
|
<div class="mt-4 pt-3 border-top d-flex justify-content-end">
|
||||||
<select class="form-select" name="origin_city" id="origin_city" required>
|
<button type="submit" class="btn btn-primary">Save Changes</button>
|
||||||
<option value="">Select City</option>
|
</div>
|
||||||
<!-- If shipment has a city but we couldn't match a country, preserve the value as a fallback option -->
|
<?php endif; ?>
|
||||||
<?php if (!$origin_country_id && $shipment['origin_city']): ?>
|
</form>
|
||||||
<option value="<?= e($shipment['origin_city']) ?>" selected><?= e($shipment['origin_city']) ?></option>
|
|
||||||
<?php endif; ?>
|
|
||||||
|
|
||||||
<?php foreach ($origin_cities_list as $city): ?>
|
<?php if (!$isAjax): ?>
|
||||||
<option value="<?= e($city['name_en']) ?>" <?= $city['name_en'] === $shipment['origin_city'] ? 'selected' : '' ?>>
|
</div>
|
||||||
<?= e($city['name_en']) ?>
|
|
||||||
</option>
|
|
||||||
<?php endforeach; ?>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Destination Selection -->
|
|
||||||
<div class="col-md-6">
|
|
||||||
<label class="form-label">Destination Country</label>
|
|
||||||
<select class="form-select" id="destination_country">
|
|
||||||
<option value="">Select Country</option>
|
|
||||||
<?php foreach ($countries as $c): ?>
|
|
||||||
<option value="<?= e($c['id']) ?>" <?= $c['id'] == $destination_country_id ? 'selected' : '' ?>>
|
|
||||||
<?= e($c['name_en']) ?>
|
|
||||||
</option>
|
|
||||||
<?php endforeach; ?>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
<div class="col-md-6">
|
|
||||||
<label class="form-label">Destination City</label>
|
|
||||||
<select class="form-select" name="destination_city" id="destination_city" required>
|
|
||||||
<option value="">Select City</option>
|
|
||||||
<!-- Fallback for unmapped city -->
|
|
||||||
<?php if (!$destination_country_id && $shipment['destination_city']): ?>
|
|
||||||
<option value="<?= e($shipment['destination_city']) ?>" selected><?= e($shipment['destination_city']) ?></option>
|
|
||||||
<?php endif; ?>
|
|
||||||
|
|
||||||
<?php foreach ($destination_cities_list as $city): ?>
|
|
||||||
<option value="<?= e($city['name_en']) ?>" <?= $city['name_en'] === $shipment['destination_city'] ? 'selected' : '' ?>>
|
|
||||||
<?= e($city['name_en']) ?>
|
|
||||||
</option>
|
|
||||||
<?php endforeach; ?>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="col-md-12">
|
|
||||||
<label class="form-label">Cargo Description</label>
|
|
||||||
<input type="text" name="cargo_description" class="form-control" value="<?= e((string)$shipment['cargo_description']) ?>">
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="col-md-4">
|
|
||||||
<label class="form-label">Weight (Tons)</label>
|
|
||||||
<input type="number" step="0.1" name="weight_tons" class="form-control" value="<?= e((string)$shipment['weight_tons']) ?>">
|
|
||||||
</div>
|
|
||||||
<div class="col-md-4">
|
|
||||||
<label class="form-label">Pickup Date</label>
|
|
||||||
<input type="date" name="pickup_date" class="form-control" value="<?= e((string)$shipment['pickup_date']) ?>">
|
|
||||||
</div>
|
|
||||||
<div class="col-md-4">
|
|
||||||
<label class="form-label">Delivery Date</label>
|
|
||||||
<input type="date" name="delivery_date" class="form-control" value="<?= e((string)$shipment['delivery_date']) ?>">
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="col-md-6">
|
|
||||||
<label class="form-label">Payment Method</label>
|
|
||||||
<select name="payment_method" class="form-select">
|
|
||||||
<option value="thawani" <?= $shipment['payment_method'] === 'thawani' ? 'selected' : '' ?>>Thawani</option>
|
|
||||||
<option value="bank_transfer" <?= $shipment['payment_method'] === 'bank_transfer' ? 'selected' : '' ?>>Bank Transfer</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
<div class="col-md-6">
|
|
||||||
<label class="form-label">Status</label>
|
|
||||||
<select name="status" class="form-select">
|
|
||||||
<option value="posted" <?= $shipment['status'] === 'posted' ? 'selected' : '' ?>>Posted</option>
|
|
||||||
<option value="offered" <?= $shipment['status'] === 'offered' ? 'selected' : '' ?>>Offered</option>
|
|
||||||
<option value="confirmed" <?= $shipment['status'] === 'confirmed' ? 'selected' : '' ?>>Confirmed</option>
|
|
||||||
<option value="in_transit" <?= $shipment['status'] === 'in_transit' ? 'selected' : '' ?>>In Transit</option>
|
|
||||||
<option value="delivered" <?= $shipment['status'] === 'delivered' ? 'selected' : '' ?>>Delivered</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="mt-4 pt-3 border-top d-flex justify-content-end">
|
|
||||||
<button type="submit" class="btn btn-primary">Save Changes</button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</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,41 +217,60 @@ 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 selectedValue = citySelect.dataset.selected || '';
|
|
||||||
citySelect.innerHTML = '<option value="">Select city</option>';
|
|
||||||
|
|
||||||
allCities.forEach((city) => {
|
const countryId = countrySelect.value;
|
||||||
if (String(city.country_id) !== String(countryId)) {
|
const selectedValue = citySelect.dataset.selected || '';
|
||||||
return;
|
citySelect.innerHTML = '<option value="">Select city</option>';
|
||||||
}
|
|
||||||
const option = document.createElement('option');
|
allCities.forEach((city) => {
|
||||||
option.value = city.id;
|
if (String(city.country_id) !== String(countryId)) {
|
||||||
option.textContent = <?= $lang === 'ar' ? '(city.name_ar || city.name_en)' : '(city.name_en || city.name_ar)' ?>;
|
return;
|
||||||
if (String(city.id) === String(selectedValue)) {
|
}
|
||||||
option.selected = true;
|
const option = document.createElement('option');
|
||||||
}
|
option.value = city.id;
|
||||||
citySelect.appendChild(option);
|
option.textContent = lang === 'ar' && city.name_ar ? city.name_ar : (city.name_en || city.name_ar);
|
||||||
});
|
if (String(city.id) === String(selectedValue)) {
|
||||||
// clear selected after first render
|
option.selected = true;
|
||||||
citySelect.dataset.selected = '';
|
}
|
||||||
}
|
citySelect.appendChild(option);
|
||||||
syncCities();
|
});
|
||||||
|
citySelect.dataset.selected = '';
|
||||||
|
};
|
||||||
|
|
||||||
|
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,41 +315,64 @@ 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 selectedValue = citySelect.dataset.selected || '';
|
|
||||||
citySelect.innerHTML = '<option value="">Select city</option>';
|
|
||||||
|
|
||||||
allCities.forEach((city) => {
|
const countryId = countrySelect.value;
|
||||||
if (String(city.country_id) !== String(countryId)) {
|
const selectedValue = citySelect.dataset.selected || '';
|
||||||
return;
|
citySelect.innerHTML = '<option value="">Select city</option>';
|
||||||
}
|
|
||||||
const option = document.createElement('option');
|
allCities.forEach((city) => {
|
||||||
option.value = city.id;
|
if (String(city.country_id) !== String(countryId)) {
|
||||||
option.textContent = <?= $lang === 'ar' ? '(city.name_ar || city.name_en)' : '(city.name_en || city.name_ar)' ?>;
|
return;
|
||||||
if (String(city.id) === String(selectedValue)) {
|
}
|
||||||
option.selected = true;
|
const option = document.createElement('option');
|
||||||
}
|
option.value = city.id;
|
||||||
citySelect.appendChild(option);
|
option.textContent = lang === 'ar' && city.name_ar ? city.name_ar : (city.name_en || city.name_ar);
|
||||||
});
|
if (String(city.id) === String(selectedValue)) {
|
||||||
// clear selected after first render
|
option.selected = true;
|
||||||
citySelect.dataset.selected = '';
|
}
|
||||||
}
|
citySelect.appendChild(option);
|
||||||
syncCities();
|
});
|
||||||
|
citySelect.dataset.selected = '';
|
||||||
|
};
|
||||||
|
|
||||||
|
// 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