Autosave: 20260307-182614
This commit is contained in:
parent
890ce0acd2
commit
9e5fb665e5
256
admin_faqs.php
Normal file
256
admin_faqs.php
Normal file
@ -0,0 +1,256 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
require_once __DIR__ . '/includes/layout.php';
|
||||
|
||||
$errors = [];
|
||||
$flash = null;
|
||||
$editFaqId = isset($_GET['edit_faq']) ? (int)$_GET['edit_faq'] : 0;
|
||||
|
||||
db()->exec("
|
||||
CREATE TABLE IF NOT EXISTS faqs (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
question_en VARCHAR(255) NOT NULL,
|
||||
answer_en TEXT NOT NULL,
|
||||
question_ar VARCHAR(255) DEFAULT NULL,
|
||||
answer_ar TEXT DEFAULT NULL,
|
||||
sort_order INT DEFAULT 0,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
");
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
if (isset($_POST['add_faq'])) {
|
||||
$questionEn = trim($_POST['question_en'] ?? '');
|
||||
$answerEn = trim($_POST['answer_en'] ?? '');
|
||||
$questionAr = trim($_POST['question_ar'] ?? '');
|
||||
$answerAr = trim($_POST['answer_ar'] ?? '');
|
||||
$sortOrder = (int)($_POST['sort_order'] ?? 0);
|
||||
|
||||
if ($questionEn === '' || $answerEn === '') {
|
||||
$errors[] = 'Question and Answer (English) are required.';
|
||||
} else {
|
||||
try {
|
||||
$stmt = db()->prepare("INSERT INTO faqs (question_en, answer_en, question_ar, answer_ar, sort_order) VALUES (?, ?, ?, ?, ?)");
|
||||
$stmt->execute([
|
||||
$questionEn,
|
||||
$answerEn,
|
||||
$questionAr !== '' ? $questionAr : null,
|
||||
$answerAr !== '' ? $answerAr : null,
|
||||
$sortOrder
|
||||
]);
|
||||
$flash = 'FAQ added successfully.';
|
||||
} catch (Throwable $e) {
|
||||
$errors[] = 'Failed to add FAQ: ' . $e->getMessage();
|
||||
}
|
||||
}
|
||||
} elseif (isset($_POST['update_faq'])) {
|
||||
$faqId = (int)($_POST['faq_id'] ?? 0);
|
||||
$questionEn = trim($_POST['question_en'] ?? '');
|
||||
$answerEn = trim($_POST['answer_en'] ?? '');
|
||||
$questionAr = trim($_POST['question_ar'] ?? '');
|
||||
$answerAr = trim($_POST['answer_ar'] ?? '');
|
||||
$sortOrder = (int)($_POST['sort_order'] ?? 0);
|
||||
|
||||
if ($faqId <= 0 || $questionEn === '' || $answerEn === '') {
|
||||
$errors[] = 'FAQ ID, Question, and Answer (English) are required.';
|
||||
} else {
|
||||
try {
|
||||
$stmt = db()->prepare("UPDATE faqs SET question_en = ?, answer_en = ?, question_ar = ?, answer_ar = ?, sort_order = ? WHERE id = ?");
|
||||
$stmt->execute([
|
||||
$questionEn,
|
||||
$answerEn,
|
||||
$questionAr !== '' ? $questionAr : null,
|
||||
$answerAr !== '' ? $answerAr : null,
|
||||
$sortOrder,
|
||||
$faqId
|
||||
]);
|
||||
$flash = 'FAQ updated successfully.';
|
||||
$editFaqId = 0;
|
||||
} catch (Throwable $e) {
|
||||
$errors[] = 'Failed to update FAQ: ' . $e->getMessage();
|
||||
}
|
||||
}
|
||||
} elseif (isset($_POST['delete_faq'])) {
|
||||
$faqId = (int)($_POST['faq_id'] ?? 0);
|
||||
if ($faqId <= 0) {
|
||||
$errors[] = 'Invalid FAQ selected.';
|
||||
} else {
|
||||
try {
|
||||
$stmt = db()->prepare("DELETE FROM faqs WHERE id = ?");
|
||||
$stmt->execute([$faqId]);
|
||||
$flash = 'FAQ deleted successfully.';
|
||||
$editFaqId = 0;
|
||||
} catch (Throwable $e) {
|
||||
$errors[] = 'Failed to delete FAQ: ' . $e->getMessage();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$faqs = db()->query("SELECT * FROM faqs ORDER BY sort_order ASC, id DESC")->fetchAll();
|
||||
|
||||
$editingFaq = null;
|
||||
if ($editFaqId > 0) {
|
||||
foreach ($faqs as $faq) {
|
||||
if ((int)$faq['id'] === $editFaqId) {
|
||||
$editingFaq = $faq;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
render_header('Manage FAQs', 'admin');
|
||||
?>
|
||||
|
||||
<div class="row g-4">
|
||||
<div class="col-lg-3">
|
||||
<?php render_admin_sidebar('faqs'); ?>
|
||||
</div>
|
||||
<div class="col-lg-9">
|
||||
<div class="page-intro mb-4">
|
||||
<h1 class="h3 mb-1">Frequently Asked Questions</h1>
|
||||
<p class="text-muted mb-0">Manage the Q&A list displayed on the public FAQ page.</p>
|
||||
</div>
|
||||
|
||||
<?php if ($flash): ?>
|
||||
<div class="alert alert-success alert-dismissible fade show" role="alert">
|
||||
<?= e($flash) ?>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<?php if ($errors): ?>
|
||||
<div class="alert alert-warning alert-dismissible fade show" role="alert">
|
||||
<?= e(implode(' ', $errors)) ?>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if ($editingFaq): ?>
|
||||
<div class="card border-0 shadow-sm mb-4">
|
||||
<div class="card-header bg-white border-bottom-0 pt-4 pb-0">
|
||||
<h5 class="mb-0">Edit FAQ</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<form method="post" class="row g-3">
|
||||
<input type="hidden" name="faq_id" value="<?= e((string)$editingFaq['id']) ?>">
|
||||
|
||||
<div class="col-md-6">
|
||||
<label class="form-label" for="edit_question_en">Question (EN) <span class="text-danger">*</span></label>
|
||||
<input id="edit_question_en" type="text" name="question_en" class="form-control" value="<?= e($editingFaq['question_en']) ?>" required>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label class="form-label" for="edit_question_ar">Question (AR)</label>
|
||||
<input id="edit_question_ar" type="text" name="question_ar" class="form-control" value="<?= e((string)($editingFaq['question_ar'] ?? '')) ?>" dir="auto">
|
||||
</div>
|
||||
|
||||
<div class="col-md-6">
|
||||
<label class="form-label" for="edit_answer_en">Answer (EN) <span class="text-danger">*</span></label>
|
||||
<textarea id="edit_answer_en" name="answer_en" class="form-control" rows="4" required><?= e($editingFaq['answer_en']) ?></textarea>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label class="form-label" for="edit_answer_ar">Answer (AR)</label>
|
||||
<textarea id="edit_answer_ar" name="answer_ar" class="form-control" rows="4" dir="auto"><?= e((string)($editingFaq['answer_ar'] ?? '')) ?></textarea>
|
||||
</div>
|
||||
|
||||
<div class="col-md-4">
|
||||
<label class="form-label" for="edit_sort_order">Sort Order</label>
|
||||
<input id="edit_sort_order" type="number" name="sort_order" class="form-control" value="<?= e((string)$editingFaq['sort_order']) ?>">
|
||||
</div>
|
||||
|
||||
<div class="col-12 mt-4">
|
||||
<button type="submit" name="update_faq" class="btn btn-primary px-4 me-2">Save Changes</button>
|
||||
<a class="btn btn-outline-secondary px-4" href="<?= e(url_with_lang('admin_faqs.php')) ?>">Cancel</a>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<?php else: ?>
|
||||
<div class="card border-0 shadow-sm mb-4">
|
||||
<div class="card-header bg-white border-bottom-0 pt-4 pb-0">
|
||||
<h5 class="mb-0">Add New FAQ</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<form method="post" class="row g-3">
|
||||
<div class="col-md-6">
|
||||
<label class="form-label" for="question_en">Question (EN) <span class="text-danger">*</span></label>
|
||||
<input id="question_en" type="text" name="question_en" class="form-control" required>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label class="form-label" for="question_ar">Question (AR)</label>
|
||||
<input id="question_ar" type="text" name="question_ar" class="form-control" dir="auto">
|
||||
</div>
|
||||
|
||||
<div class="col-md-6">
|
||||
<label class="form-label" for="answer_en">Answer (EN) <span class="text-danger">*</span></label>
|
||||
<textarea id="answer_en" name="answer_en" class="form-control" rows="3" required></textarea>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label class="form-label" for="answer_ar">Answer (AR)</label>
|
||||
<textarea id="answer_ar" name="answer_ar" class="form-control" rows="3" dir="auto"></textarea>
|
||||
</div>
|
||||
|
||||
<div class="col-md-4">
|
||||
<label class="form-label" for="sort_order">Sort Order (Optional)</label>
|
||||
<input id="sort_order" type="number" name="sort_order" class="form-control" value="0">
|
||||
</div>
|
||||
|
||||
<div class="col-12 mt-4">
|
||||
<button type="submit" name="add_faq" class="btn btn-primary px-4"><i class="bi bi-plus-circle me-2"></i>Add FAQ</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="card border-0 shadow-sm">
|
||||
<div class="card-header bg-white border-bottom-0 pt-4 pb-3">
|
||||
<h5 class="mb-0">Current FAQs</h5>
|
||||
</div>
|
||||
<div class="card-body p-0">
|
||||
<?php if (!$faqs): ?>
|
||||
<div class="text-center p-5 text-muted">
|
||||
<i class="bi bi-question-circle display-4 mb-3 d-block text-secondary opacity-50"></i>
|
||||
<p class="mb-0">No FAQs added yet.</p>
|
||||
</div>
|
||||
<?php else: ?>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-hover align-middle mb-0">
|
||||
<thead class="table-light">
|
||||
<tr>
|
||||
<th class="ps-4">Sort</th>
|
||||
<th>Question (EN)</th>
|
||||
<th>Answer Extract</th>
|
||||
<th class="text-end pe-4">Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($faqs as $faq): ?>
|
||||
<tr>
|
||||
<td class="ps-4 text-muted"><small><?= e((string)$faq['sort_order']) ?></small></td>
|
||||
<td class="fw-medium"><?= e($faq['question_en']) ?></td>
|
||||
<td class="text-muted"><small><?= e(mb_strimwidth($faq['answer_en'], 0, 50, '...')) ?></small></td>
|
||||
<td class="text-end pe-4">
|
||||
<a class="btn btn-sm btn-light border me-1" href="<?= e(url_with_lang('admin_faqs.php', ['edit_faq' => (int)$faq['id']])) ?>" title="Edit">
|
||||
<i class="bi bi-pencil"></i>
|
||||
</a>
|
||||
<form method="post" class="d-inline" onsubmit="return confirm('Are you sure you want to delete this FAQ?');">
|
||||
<input type="hidden" name="faq_id" value="<?= e((string)$faq['id']) ?>">
|
||||
<button type="submit" name="delete_faq" class="btn btn-sm btn-light border text-danger" title="Delete">
|
||||
<i class="bi bi-trash"></i>
|
||||
</button>
|
||||
</form>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php render_footer(); ?>
|
||||
@ -16,6 +16,13 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
'wablas_domain' => trim($_POST['wablas_domain'] ?? ''),
|
||||
'wablas_api_token' => trim($_POST['wablas_api_token'] ?? ''),
|
||||
'wablas_secret_key' => trim($_POST['wablas_secret_key'] ?? ''),
|
||||
'smtp_host' => trim($_POST['smtp_host'] ?? ''),
|
||||
'smtp_port' => trim($_POST['smtp_port'] ?? ''),
|
||||
'smtp_secure' => trim($_POST['smtp_secure'] ?? ''),
|
||||
'smtp_user' => trim($_POST['smtp_user'] ?? ''),
|
||||
'smtp_pass' => trim($_POST['smtp_pass'] ?? ''),
|
||||
'mail_from' => trim($_POST['mail_from'] ?? ''),
|
||||
'mail_from_name' => trim($_POST['mail_from_name'] ?? ''),
|
||||
];
|
||||
|
||||
if (empty($errors)) {
|
||||
@ -35,6 +42,13 @@ $thawaniEnv = $settings['thawani_environment'] ?? 'test';
|
||||
$wablasDomain = $settings['wablas_domain'] ?? '';
|
||||
$wablasToken = $settings['wablas_api_token'] ?? '';
|
||||
$wablasSecret = $settings['wablas_secret_key'] ?? '';
|
||||
$smtpHost = $settings['smtp_host'] ?? '';
|
||||
$smtpPort = $settings['smtp_port'] ?? '587';
|
||||
$smtpSecure = $settings['smtp_secure'] ?? 'tls';
|
||||
$smtpUser = $settings['smtp_user'] ?? '';
|
||||
$smtpPass = $settings['smtp_pass'] ?? '';
|
||||
$mailFrom = $settings['mail_from'] ?? '';
|
||||
$mailFromName = $settings['mail_from_name'] ?? '';
|
||||
|
||||
render_header('Integrations', 'admin');
|
||||
?>
|
||||
@ -120,6 +134,58 @@ render_header('Integrations', 'admin');
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- SMTP Mail Gateway 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-envelope me-2 text-danger" 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-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>
|
||||
SMTP Mail Settings
|
||||
</h3>
|
||||
<p class="text-muted small mb-4">Configure your SMTP server to send emails and system notifications.</p>
|
||||
|
||||
<div class="row g-4">
|
||||
<div class="col-md-6">
|
||||
<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">
|
||||
</div>
|
||||
|
||||
<div class="col-md-3">
|
||||
<label class="form-label fw-bold">SMTP Port</label>
|
||||
<input type="number" name="smtp_port" class="form-control" value="<?= e($smtpPort) ?>" placeholder="587">
|
||||
</div>
|
||||
|
||||
<div class="col-md-3">
|
||||
<label class="form-label fw-bold">Security</label>
|
||||
<select name="smtp_secure" class="form-select">
|
||||
<option value="tls" <?= $smtpSecure === 'tls' ? 'selected' : '' ?>>TLS</option>
|
||||
<option value="ssl" <?= $smtpSecure === 'ssl' ? 'selected' : '' ?>>SSL</option>
|
||||
<option value="none" <?= $smtpSecure === 'none' || $smtpSecure === '' ? 'selected' : '' ?>>None</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6">
|
||||
<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">
|
||||
</div>
|
||||
|
||||
<div class="col-md-6">
|
||||
<label class="form-label fw-bold">SMTP Password</label>
|
||||
<input type="password" name="smtp_pass" class="form-control" value="<?= e($smtpPass) ?>" placeholder="••••••••">
|
||||
</div>
|
||||
|
||||
<div class="col-md-6">
|
||||
<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">
|
||||
</div>
|
||||
|
||||
<div class="col-md-6">
|
||||
<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">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="d-flex justify-content-end">
|
||||
<button type="submit" class="btn btn-primary px-5">Save Integrations</button>
|
||||
</div>
|
||||
|
||||
12
db/migrations/add_bank_fields.php
Normal file
12
db/migrations/add_bank_fields.php
Normal file
@ -0,0 +1,12 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/../config.php';
|
||||
try {
|
||||
$pdo = db();
|
||||
$pdo->exec("ALTER TABLE truck_owner_profiles ADD COLUMN bank_account VARCHAR(100) NULL AFTER plate_no;");
|
||||
$pdo->exec("ALTER TABLE truck_owner_profiles ADD COLUMN bank_name VARCHAR(100) NULL AFTER bank_account;");
|
||||
$pdo->exec("ALTER TABLE truck_owner_profiles ADD COLUMN bank_branch VARCHAR(100) NULL AFTER bank_name;");
|
||||
echo "Columns added.\n";
|
||||
} catch (Exception $e) {
|
||||
echo "Error: " . $e->getMessage() . "\n";
|
||||
}
|
||||
|
||||
64
faq.php
Normal file
64
faq.php
Normal file
@ -0,0 +1,64 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
require_once __DIR__ . '/includes/layout.php';
|
||||
|
||||
try {
|
||||
// Check if table exists to avoid errors on first load before admin visits it
|
||||
$tableExists = db()->query("SHOW TABLES LIKE 'faqs'")->rowCount() > 0;
|
||||
|
||||
if ($tableExists) {
|
||||
$faqs = db()->query("SELECT * FROM faqs ORDER BY sort_order ASC, id DESC")->fetchAll();
|
||||
} else {
|
||||
$faqs = [];
|
||||
}
|
||||
} catch (Throwable $e) {
|
||||
$faqs = [];
|
||||
}
|
||||
|
||||
render_header('Frequently Asked Questions', 'home');
|
||||
?>
|
||||
|
||||
<div class="container py-5">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-lg-8 text-center mb-5">
|
||||
<h1 class="display-5 fw-bold mb-3">Frequently Asked Questions</h1>
|
||||
<p class="lead text-muted">Find answers to common questions about our platform and services.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-lg-9">
|
||||
<?php if (empty($faqs)): ?>
|
||||
<div class="text-center p-5 bg-white rounded shadow-sm">
|
||||
<i class="bi bi-info-circle display-4 text-muted mb-3 d-block"></i>
|
||||
<p class="text-muted mb-0">No FAQs are currently available. Please check back later.</p>
|
||||
</div>
|
||||
<?php else: ?>
|
||||
<div class="accordion accordion-flush shadow-sm bg-white rounded-3 p-3" id="faqAccordion">
|
||||
<?php foreach ($faqs as $index => $faq):
|
||||
$question = $lang === 'ar' && !empty($faq['question_ar']) ? $faq['question_ar'] : $faq['question_en'];
|
||||
$answer = $lang === 'ar' && !empty($faq['answer_ar']) ? $faq['answer_ar'] : $faq['answer_en'];
|
||||
$collapseId = 'collapse' . $faq['id'];
|
||||
$headingId = 'heading' . $faq['id'];
|
||||
?>
|
||||
<div class="accordion-item border-0 border-bottom mb-2">
|
||||
<h2 class="accordion-header" id="<?= e($headingId) ?>">
|
||||
<button class="accordion-button collapsed fw-semibold fs-5 bg-transparent" type="button" data-bs-toggle="collapse" data-bs-target="#<?= e($collapseId) ?>" aria-expanded="false" aria-controls="<?= e($collapseId) ?>">
|
||||
<?= e($question) ?>
|
||||
</button>
|
||||
</h2>
|
||||
<div id="<?= e($collapseId) ?>" class="accordion-collapse collapse" aria-labelledby="<?= e($headingId) ?>" data-bs-parent="#faqAccordion">
|
||||
<div class="accordion-body text-muted lh-lg">
|
||||
<?= nl2br(e($answer)) ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php render_footer(); ?>
|
||||
@ -223,6 +223,9 @@ SQL;
|
||||
truck_type VARCHAR(120) NOT NULL,
|
||||
load_capacity DECIMAL(10,2) NOT NULL,
|
||||
plate_no VARCHAR(80) NOT NULL,
|
||||
bank_account VARCHAR(100) NULL,
|
||||
bank_name VARCHAR(100) NULL,
|
||||
bank_branch VARCHAR(100) NULL,
|
||||
id_card_path TEXT NOT NULL,
|
||||
truck_pic_path VARCHAR(255) NOT NULL,
|
||||
registration_path TEXT NOT NULL,
|
||||
|
||||
@ -58,6 +58,11 @@ function render_header(string $title, string $active = ''): void
|
||||
<?= e(t('nav_home')) ?>
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link <?= $active === 'faq' ? 'active text-primary' : '' ?>" href="<?= e(url_with_lang('faq.php')) ?>">
|
||||
FAQ
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="d-flex align-items-center gap-3">
|
||||
<div class="dropdown">
|
||||
@ -151,7 +156,7 @@ function render_footer(): void
|
||||
<div class="col-md-2">
|
||||
<h6 class="fw-bold mb-3">Resources</h6>
|
||||
<ul class="list-unstyled text-muted small">
|
||||
<li class="mb-2"><a href="#" class="text-decoration-none text-muted">Help Center</a></li>
|
||||
<li class="mb-2"><a href="<?= e(url_with_lang('faq.php')) ?>" class="text-decoration-none text-muted">Help Center / FAQ</a></li>
|
||||
<li class="mb-2"><a href="#" class="text-decoration-none text-muted">Terms of Service</a></li>
|
||||
<li class="mb-2"><a href="#" class="text-decoration-none text-muted">Privacy Policy</a></li>
|
||||
</ul>
|
||||
@ -184,6 +189,7 @@ function render_admin_sidebar(string $active = 'dashboard'): void
|
||||
$settingsActive = in_array($active, ['company_profile', 'integrations']);
|
||||
$locationsActive = in_array($active, ['countries', 'cities']);
|
||||
$usersActive = in_array($active, ['shippers', 'truck_owners', 'register']);
|
||||
$pagesActive = in_array($active, ['faqs']);
|
||||
?>
|
||||
<aside class="admin-sidebar panel p-4 shadow-sm border-0">
|
||||
<h2 class="h5 fw-bold mb-4"><i class="bi bi-shield-lock me-2 text-primary"></i>Admin Panel</h2>
|
||||
@ -239,6 +245,19 @@ function render_admin_sidebar(string $active = 'dashboard'): void
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<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="#collapsePages" aria-expanded="<?= $pagesActive ? 'true' : 'false' ?>">
|
||||
<span><i class="bi bi-file-earmark-text-fill me-2"></i>Pages</span>
|
||||
<i class="bi bi-chevron-down small"></i>
|
||||
</a>
|
||||
<div class="collapse <?= $pagesActive ? 'show' : '' ?>" id="collapsePages">
|
||||
<div class="nav flex-column gap-1 ms-3 border-start ps-2 border-2">
|
||||
<a class="admin-nav-link <?= $active === 'faqs' ? 'active' : '' ?>" href="<?= e(url_with_lang('admin_faqs.php')) ?>">
|
||||
<i class="bi bi-question-square me-2"></i>FAQs
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</nav>
|
||||
</aside>
|
||||
<?php
|
||||
|
||||
10
index.php
10
index.php
@ -216,6 +216,16 @@ render_header(t('app_name'), 'home');
|
||||
</section>
|
||||
<?php endif; ?>
|
||||
|
||||
<section class="mb-5 text-center">
|
||||
<div class="panel p-5 border-0 shadow-sm rounded-4" style="background-color: #f8f9fa;">
|
||||
<h2 class="display-6 fw-bold mb-3">Have Questions?</h2>
|
||||
<p class="text-muted fs-5 mb-4 mx-auto" style="max-width: 600px;">Check out our Frequently Asked Questions to learn more about how our platform works.</p>
|
||||
<a href="<?= e(url_with_lang('faq.php')) ?>" class="btn btn-primary btn-lg px-4 rounded-pill shadow-sm">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor" class="bi bi-question-circle me-2" viewBox="0 0 16 16"><path d="M8 15A7 7 0 1 1 8 1a7 7 0 0 1 0 14m0 1A8 8 0 1 0 8 0a8 8 0 0 0 0 16"/><path d="M5.255 5.786a.237.237 0 0 0 .241.247h.825c.138 0 .248-.113.266-.25.09-.656.54-1.134 1.342-1.134.686 0 1.314.343 1.314 1.168 0 .635-.374.927-.965 1.371-.673.489-1.206 1.06-1.168 1.987l.003.217a.25.25 0 0 0 .25.246h.811a.25.25 0 0 0 .25-.25v-.105c0-.718.273-.927 1.01-1.486.609-.463 1.244-.977 1.244-2.056 0-1.511-1.276-2.241-2.673-2.241-1.267 0-2.655.59-2.75 2.286zm1.557 5.763c0 .533.425.927 1.01.927.609 0 1.028-.394 1.028-.927 0-.552-.42-.94-1.029-.94-.584 0-1.009.388-1.009.94z"/></svg>View FAQ
|
||||
</a>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<div class="motivation-box mb-5">
|
||||
<h3 class="display-6 fw-bold mb-3">Ready to transform your logistics?</h3>
|
||||
<p class="fs-5 text-white-50 mb-4 mx-auto" style="max-width: 600px;">Join our platform today to find reliable trucks or secure the best shipments in the market.</p>
|
||||
|
||||
@ -1,15 +1,12 @@
|
||||
<?php
|
||||
// Mail configuration sourced from environment variables.
|
||||
// No secrets are stored here; the file just maps env -> config array for MailService.
|
||||
// Mail configuration sourced from environment variables,
|
||||
// falling back to database settings if configured.
|
||||
|
||||
function env_val(string $key, $default = null) {
|
||||
$v = getenv($key);
|
||||
return ($v === false || $v === null || $v === '') ? $default : $v;
|
||||
}
|
||||
|
||||
// Fallback: if critical vars are missing from process env, try to parse executor/.env
|
||||
// This helps in web/Apache contexts where .env is not exported.
|
||||
// Supports simple KEY=VALUE lines; ignores quotes and comments.
|
||||
function load_dotenv_if_needed(array $keys): void {
|
||||
$missing = array_filter($keys, fn($k) => getenv($k) === false || getenv($k) === '');
|
||||
if (empty($missing)) return;
|
||||
@ -22,9 +19,7 @@ function load_dotenv_if_needed(array $keys): void {
|
||||
if ($line[0] === '#' || trim($line) === '') continue;
|
||||
if (!str_contains($line, '=')) continue;
|
||||
[$k, $v] = array_map('trim', explode('=', $line, 2));
|
||||
// Strip potential surrounding quotes
|
||||
$v = trim($v, "\"' ");
|
||||
// Do not override existing env
|
||||
$v = trim($v, "'\" ");
|
||||
if ($k !== '' && (getenv($k) === false || getenv($k) === '')) {
|
||||
putenv("{$k}={$v}");
|
||||
}
|
||||
@ -39,15 +34,43 @@ load_dotenv_if_needed([
|
||||
'DKIM_DOMAIN','DKIM_SELECTOR','DKIM_PRIVATE_KEY_PATH'
|
||||
]);
|
||||
|
||||
$transport = env_val('MAIL_TRANSPORT', 'smtp');
|
||||
$smtp_host = env_val('SMTP_HOST');
|
||||
$smtp_port = (int) env_val('SMTP_PORT', 587);
|
||||
$smtp_secure = env_val('SMTP_SECURE', 'tls'); // tls | ssl | null
|
||||
$smtp_user = env_val('SMTP_USER');
|
||||
$smtp_pass = env_val('SMTP_PASS');
|
||||
// Attempt to load settings from DB safely
|
||||
function get_mail_db_settings(): array {
|
||||
$settings = [];
|
||||
$dbPath = __DIR__ . '/../db/config.php';
|
||||
if (file_exists($dbPath)) {
|
||||
require_once $dbPath;
|
||||
if (function_exists('db')) {
|
||||
try {
|
||||
$stmt = db()->query("SELECT setting_key, setting_value FROM settings");
|
||||
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
|
||||
$settings[$row['setting_key']] = $row['setting_value'];
|
||||
}
|
||||
} catch (Throwable $e) {
|
||||
// Ignore DB errors if not initialized
|
||||
}
|
||||
}
|
||||
}
|
||||
return $settings;
|
||||
}
|
||||
|
||||
$from_email = env_val('MAIL_FROM', 'no-reply@localhost');
|
||||
$from_name = env_val('MAIL_FROM_NAME', 'App');
|
||||
$dbSettings = get_mail_db_settings();
|
||||
|
||||
$transport = env_val('MAIL_TRANSPORT', 'smtp');
|
||||
|
||||
$smtp_host = !empty($dbSettings['smtp_host']) ? $dbSettings['smtp_host'] : env_val('SMTP_HOST');
|
||||
$smtp_port = !empty($dbSettings['smtp_port']) ? (int)$dbSettings['smtp_port'] : (int) env_val('SMTP_PORT', 587);
|
||||
$smtp_secure = isset($dbSettings['smtp_secure']) && $dbSettings['smtp_secure'] !== '' ? $dbSettings['smtp_secure'] : env_val('SMTP_SECURE', 'tls');
|
||||
if (isset($dbSettings['smtp_secure']) && $dbSettings['smtp_secure'] === 'none') {
|
||||
$smtp_secure = '';
|
||||
}
|
||||
if ($smtp_secure === 'none') $smtp_secure = ''; // Normalize None to empty for PHPMailer
|
||||
|
||||
$smtp_user = !empty($dbSettings['smtp_user']) ? $dbSettings['smtp_user'] : env_val('SMTP_USER');
|
||||
$smtp_pass = !empty($dbSettings['smtp_pass']) ? $dbSettings['smtp_pass'] : env_val('SMTP_PASS');
|
||||
|
||||
$from_email = !empty($dbSettings['mail_from']) ? $dbSettings['mail_from'] : env_val('MAIL_FROM', 'no-reply@localhost');
|
||||
$from_name = !empty($dbSettings['mail_from_name']) ? $dbSettings['mail_from_name'] : env_val('MAIL_FROM_NAME', 'App');
|
||||
$reply_to = env_val('MAIL_REPLY_TO');
|
||||
|
||||
$dkim_domain = env_val('DKIM_DOMAIN');
|
||||
@ -56,21 +79,15 @@ $dkim_private_key_path = env_val('DKIM_PRIVATE_KEY_PATH');
|
||||
|
||||
return [
|
||||
'transport' => $transport,
|
||||
|
||||
// SMTP
|
||||
'smtp_host' => $smtp_host,
|
||||
'smtp_port' => $smtp_port,
|
||||
'smtp_secure' => $smtp_secure,
|
||||
'smtp_user' => $smtp_user,
|
||||
'smtp_pass' => $smtp_pass,
|
||||
|
||||
// From / Reply-To
|
||||
'from_email' => $from_email,
|
||||
'from_name' => $from_name,
|
||||
'reply_to' => $reply_to,
|
||||
|
||||
// DKIM (optional)
|
||||
'dkim_domain' => $dkim_domain,
|
||||
'dkim_selector' => $dkim_selector,
|
||||
'dkim_private_key_path' => $dkim_private_key_path,
|
||||
];
|
||||
];
|
||||
100
patch.py
Normal file
100
patch.py
Normal file
@ -0,0 +1,100 @@
|
||||
import re
|
||||
|
||||
with open('register.php', 'r') as f:
|
||||
content = f.read()
|
||||
|
||||
# 1
|
||||
content = content.replace(" 'plate_no' => '',", " 'plate_no' => '',\n 'bank_account' => '',\n 'bank_name' => '',\n 'bank_branch' => '',")
|
||||
|
||||
# 2
|
||||
content = content.replace(" 'plate_no' => trim($_POST['plate_no'] ?? ''),", " 'plate_no' => trim($_POST['plate_no'] ?? ''),\n 'bank_account' => trim($_POST['bank_account'] ?? ''),\n 'bank_name' => trim($_POST['bank_name'] ?? ''),\n 'bank_branch' => trim($_POST['bank_branch'] ?? ''),")
|
||||
|
||||
# 3
|
||||
content = content.replace(" $plateNo = trim($_POST['plate_no'] ?? '');", " $plateNo = trim($_POST['plate_no'] ?? '');\n $bankAccount = trim($_POST['bank_account'] ?? '');\n $bankName = trim($_POST['bank_name'] ?? '');\n $bankBranch = trim($_POST['bank_branch'] ?? '');")
|
||||
|
||||
# 4
|
||||
s4 = " if ($truckType === '' || $loadCapacity === '' || $plateNo === '') {\n $errors[] = 'Please complete truck details.';\n } elseif (!is_numeric($loadCapacity) || (float)$loadCapacity <= 0) {"
|
||||
r4 = " if ($truckType === '' || $loadCapacity === '' || $plateNo === '') {\n $errors[] = 'Please complete truck details.';\n } elseif ($bankAccount === '' || $bankName === '' || $bankBranch === '') {\n $errors[] = 'Please complete bank account details.';\n } elseif (!is_numeric($loadCapacity) || (float)$loadCapacity <= 0) {"
|
||||
content = content.replace(s4, r4)
|
||||
|
||||
# 5
|
||||
s5 = " $ownerStmt = $pdo->prepare(
|
||||
\"INSERT INTO truck_owner_profiles (user_id, phone, country_id, city_id, address_line, truck_type, load_capacity, plate_no, id_card_path, truck_pic_path, registration_path)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\"
|
||||
);
|
||||
$ownerStmt->execute([
|
||||
$userId,
|
||||
$phone,
|
||||
$countryId,
|
||||
$cityId,
|
||||
$addressLine,
|
||||
$truckType,
|
||||
$loadCapacity,
|
||||
$plateNo,
|
||||
json_encode($idCardPaths, JSON_UNESCAPED_SLASHES),
|
||||
$truckPic,
|
||||
json_encode($regPaths, JSON_UNESCAPED_SLASHES),
|
||||
]);"
|
||||
r5 = " $ownerStmt = $pdo->prepare(
|
||||
\"INSERT INTO truck_owner_profiles (user_id, phone, country_id, city_id, address_line, truck_type, load_capacity, plate_no, bank_account, bank_name, bank_branch, id_card_path, truck_pic_path, registration_path)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\"
|
||||
);
|
||||
$ownerStmt->execute([
|
||||
$userId,
|
||||
$phone,
|
||||
$countryId,
|
||||
$cityId,
|
||||
$addressLine,
|
||||
$truckType,
|
||||
$loadCapacity,
|
||||
$plateNo,
|
||||
$bankAccount,
|
||||
$bankName,
|
||||
$bankBranch,
|
||||
json_encode($idCardPaths, JSON_UNESCAPED_SLASHES),
|
||||
$truckPic,
|
||||
json_encode($regPaths, JSON_UNESCAPED_SLASHES),
|
||||
]);"
|
||||
content = content.replace(s5, r5)
|
||||
|
||||
# 6
|
||||
s6 = " 'plate_no' => '',"
|
||||
r6 = " 'plate_no' => '',\n 'bank_account' => '',\n 'bank_name' => '',\n 'bank_branch' => '',"
|
||||
# careful not to replace the first one again
|
||||
parts = content.split(s6)
|
||||
if len(parts) == 3:
|
||||
content = parts[0] + s6 + parts[1] + r6 + parts[2]
|
||||
elif len(parts) == 2:
|
||||
# meaning the first one was already replaced by s1/r1 (which is the same search string!)
|
||||
# wait, s1 and s6 are exactly the same?
|
||||
# No, s1 is " 'plate_no' => ''," and s6 is " 'plate_no' => ''," (more spaces)
|
||||
content = parts[0] + r6 + parts[1]
|
||||
|
||||
|
||||
# 7
|
||||
s7 = " <div class=\"col-md-4\">
|
||||
<label class=\"form-label\" for=\"plate_no\">Plate number</label>
|
||||
<input type=\"text\" name=\"plate_no\" id=\"plate_no\" class=\"form-control\" value=\"<?= e($values['plate_no']) ?>\">
|
||||
</div>"
|
||||
r7 = " <div class=\"col-md-4\">
|
||||
<label class=\"form-label\" for=\"plate_no\">Plate number</label>
|
||||
<input type=\"text\" name=\"plate_no\" id=\"plate_no\" class=\"form-control\" value=\"<?= e($values['plate_no']) ?>\">
|
||||
</div>
|
||||
|
||||
<h3 class=\"h6 mt-4 w-100\">Bank Details for Payouts</h3>
|
||||
<div class=\"col-md-4 mt-2\">
|
||||
<label class=\"form-label\" for=\"bank_account\">Bank Account / IBAN</label>
|
||||
<input type=\"text\" name=\"bank_account\" id=\"bank_account\" class=\"form-control\" value=\"<?= e($values['bank_account']) ?>\" required>
|
||||
</div>
|
||||
<div class=\"col-md-4 mt-2\">
|
||||
<label class=\"form-label\" for=\"bank_name\">Bank Name</label>
|
||||
<input type=\"text\" name=\"bank_name\" id=\"bank_name\" class=\"form-control\" value=\"<?= e($values['bank_name']) ?>\" required>
|
||||
</div>
|
||||
<div class=\"col-md-4 mt-2\">
|
||||
<label class=\"form-label\" for=\"bank_branch\">Branch</label>
|
||||
<input type=\"text\" name=\"bank_branch\" id=\"bank_branch\" class=\"form-control\" value=\"<?= e($values['bank_branch']) ?>\" required>
|
||||
</div>"
|
||||
content = content.replace(s7, r7)
|
||||
|
||||
with open('register.php', 'w') as f:
|
||||
f.write(content)
|
||||
|
||||
print("Replaced in register.php")
|
||||
16
tmp_edit.php
Normal file
16
tmp_edit.php
Normal file
@ -0,0 +1,16 @@
|
||||
<?php
|
||||
$content = file_get_contents('includes/app.php');
|
||||
$search = " plate_no VARCHAR(80) NOT NULL,
|
||||
id_card_path TEXT NOT NULL,";
|
||||
$replace = " plate_no VARCHAR(80) NOT NULL,
|
||||
bank_account VARCHAR(100) NULL,
|
||||
bank_name VARCHAR(100) NULL,
|
||||
bank_branch VARCHAR(100) NULL,
|
||||
id_card_path TEXT NOT NULL,";
|
||||
if (strpos($content, $search) !== false) {
|
||||
file_put_contents('includes/app.php', str_replace($search, $replace, $content));
|
||||
echo "Replaced in includes/app.php\n";
|
||||
} else {
|
||||
echo "Search string not found\n";
|
||||
}
|
||||
|
||||
105
tmp_reg_edit.php
Normal file
105
tmp_reg_edit.php
Normal file
@ -0,0 +1,105 @@
|
||||
<?php
|
||||
$content = file_get_contents('register.php');
|
||||
|
||||
$s1 = " 'plate_no' => '',";
|
||||
$r1 = " 'plate_no' => '',\n 'bank_account' => '',\n 'bank_name' => '',\n 'bank_branch' => '',";
|
||||
|
||||
$s2 = " 'plate_no' => trim(\"
|
||||
$_POST['plate_no'] ?? ''\"),";
|
||||
$r2 = " 'plate_no' => trim(\"
|
||||
$_POST['plate_no'] ?? ''\"),\n 'bank_account' => trim(\"
|
||||
$_POST['bank_account'] ?? ''\"),\n 'bank_name' => trim(\"
|
||||
$_POST['bank_name'] ?? ''\"),\n 'bank_branch' => trim(\"
|
||||
$_POST['bank_branch'] ?? ''\"),";
|
||||
|
||||
$s3 = " $plateNo = trim(\"
|
||||
$_POST['plate_no'] ?? ''\");";
|
||||
$r3 = " $plateNo = trim(\"
|
||||
$_POST['plate_no'] ?? ''\");\n $bankAccount = trim(\"
|
||||
$_POST['bank_account'] ?? ''\");\n $bankName = trim(\"
|
||||
$_POST['bank_name'] ?? ''\");\n $bankBranch = trim(\"
|
||||
$_POST['bank_branch'] ?? ''\");";
|
||||
|
||||
$s4 = " if ($truckType === '' || $loadCapacity === '' || $plateNo === '') {\n $errors[] = 'Please complete truck details.';\n } elseif (!is_numeric($loadCapacity) || (float)$loadCapacity <= 0) {";
|
||||
$r4 = " if ($truckType === '' || $loadCapacity === '' || $plateNo === '') {\n $errors[] = 'Please complete truck details.';\n } elseif ($bankAccount === '' || $bankName === '' || $bankBranch === '') {\n $errors[] = 'Please complete bank account details.';\n } elseif (!is_numeric($loadCapacity) || (float)$loadCapacity <= 0) {";
|
||||
|
||||
$s5 = <<<PHP
|
||||
$ownerStmt = $pdo->prepare(
|
||||
"INSERT INTO truck_owner_profiles (user_id, phone, country_id, city_id, address_line, truck_type, load_capacity, plate_no, id_card_path, truck_pic_path, registration_path)"
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"
|
||||
);
|
||||
$ownerStmt->execute([
|
||||
$userId,
|
||||
$phone,
|
||||
$countryId,
|
||||
$cityId,
|
||||
$addressLine,
|
||||
$truckType,
|
||||
$loadCapacity,
|
||||
$plateNo,
|
||||
json_encode($idCardPaths, JSON_UNESCAPED_SLASHES),
|
||||
$truckPic,
|
||||
json_encode($regPaths, JSON_UNESCAPED_SLASHES),
|
||||
]);
|
||||
PHP;
|
||||
$r5 = <<<PHP
|
||||
$ownerStmt = $pdo->prepare(
|
||||
"INSERT INTO truck_owner_profiles (user_id, phone, country_id, city_id, address_line, truck_type, load_capacity, plate_no, bank_account, bank_name, bank_branch, id_card_path, truck_pic_path, registration_path)"
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"
|
||||
);
|
||||
$ownerStmt->execute([
|
||||
$userId,
|
||||
$phone,
|
||||
$countryId,
|
||||
$cityId,
|
||||
$addressLine,
|
||||
$truckType,
|
||||
$loadCapacity,
|
||||
$plateNo,
|
||||
$bankAccount,
|
||||
$bankName,
|
||||
$bankBranch,
|
||||
json_encode($idCardPaths, JSON_UNESCAPED_SLASHES),
|
||||
$truckPic,
|
||||
json_encode($regPaths, JSON_UNESCAPED_SLASHES),
|
||||
]);
|
||||
PHP;
|
||||
|
||||
$s7 = <<<HTML
|
||||
<div class="col-md-4">
|
||||
<label class="form-label" for="plate_no">Plate number</label>
|
||||
<input type="text" name="plate_no" id="plate_no" class="form-control" value="<?= e($values['plate_no']) ?>">
|
||||
</div>
|
||||
HTML;
|
||||
|
||||
$r7 = <<<HTML
|
||||
<div class="col-md-4">
|
||||
<label class="form-label" for="plate_no">Plate number</label>
|
||||
<input type="text" name="plate_no" id="plate_no" class="form-control" value="<?= e($values['plate_no']) ?>">
|
||||
</div>
|
||||
|
||||
<h3 class="h6 mt-4 mb-2 w-100">Bank Details for Payouts</h3>
|
||||
<div class="col-md-4 mt-2">
|
||||
<label class="form-label" for="bank_account">Bank Account / IBAN</label>
|
||||
<input type="text" name="bank_account" id="bank_account" class="form-control" value="<?= e($values['bank_account']) ?>">
|
||||
</div>
|
||||
<div class="col-md-4 mt-2">
|
||||
<label class="form-label" for="bank_name">Bank Name</label>
|
||||
<input type="text" name="bank_name" id="bank_name" class="form-control" value="<?= e($values['bank_name']) ?>">
|
||||
</div>
|
||||
<div class="col-md-4 mt-2">
|
||||
<label class="form-label" for="bank_branch">Branch</label>
|
||||
<input type="text" name="bank_branch" id="bank_branch" class="form-control" value="<?= e($values['bank_branch']) ?>">
|
||||
</div>
|
||||
HTML;
|
||||
|
||||
$content = str_replace($s1, $r1, $content);
|
||||
$content = str_replace($s2, $r2, $content);
|
||||
$content = str_replace($s3, $r3, $content);
|
||||
$content = str_replace($s4, $r4, $content);
|
||||
$content = str_replace($s5, $r5, $content);
|
||||
$content = str_replace($s7, $r7, $content);
|
||||
|
||||
file_put_contents('register.php', $content);
|
||||
echo "Replaced in register.php\n";
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user