adding login and logout pages

This commit is contained in:
Flatlogic Bot 2026-03-08 02:38:30 +00:00
parent 9e5fb665e5
commit 890b723e72
13 changed files with 490 additions and 256 deletions

View File

@ -13,12 +13,14 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$companyEmail = trim($_POST['company_email'] ?? '');
$companyPhone = trim($_POST['company_phone'] ?? '');
$companyAddress = trim($_POST['company_address'] ?? '');
$platformCharge = trim($_POST['platform_charge_percentage'] ?? '0');
$updates = [
'company_name' => $companyName,
'company_email' => $companyEmail,
'company_phone' => $companyPhone,
'company_address' => $companyAddress,
'platform_charge_percentage' => $platformCharge,
];
// Handle file uploads
@ -73,6 +75,7 @@ $currentName = $settings['company_name'] ?? t('app_name');
$currentEmail = $settings['company_email'] ?? '';
$currentPhone = $settings['company_phone'] ?? '';
$currentAddress = $settings['company_address'] ?? '';
$currentPlatformCharge = $settings['platform_charge_percentage'] ?? '0';
$currentLogo = $settings['logo_path'] ?? '';
$currentFavicon = $settings['favicon_path'] ?? '';
@ -86,7 +89,7 @@ render_header('Company Profile', 'admin');
<div class="col-lg-9">
<div class="page-intro mb-4">
<h1 class="section-title mb-1">Company Profile</h1>
<p class="muted mb-0">Update your app name, logo, favicon, and contact details.</p>
<p class="muted mb-0">Update your app name, logo, favicon, contact details, and platform charge.</p>
</div>
<?php if ($success): ?>
@ -122,6 +125,19 @@ render_header('Company Profile', 'admin');
<div class="form-text">Displayed in the footer.</div>
</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): ?>
@ -152,4 +168,4 @@ render_header('Company Profile', 'admin');
</div>
</div>
<?php render_footer(); ?>
<?php render_footer(); ?>

View File

@ -16,7 +16,7 @@ $flash = null;
$stmt = db()->prepare("
SELECT u.id, u.email, u.full_name, u.status, u.role,
p.phone, p.address_line, p.country_id, p.city_id,
p.truck_type, p.load_capacity, p.plate_no,
p.truck_type, p.load_capacity, p.plate_no, p.bank_account, p.bank_name, p.bank_branch,
p.id_card_path, p.truck_pic_path, p.registration_path
FROM users u
LEFT JOIN truck_owner_profiles p ON u.id = p.user_id
@ -45,6 +45,9 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$loadCapacity = trim($_POST['load_capacity'] ?? '');
$plateNo = trim($_POST['plate_no'] ?? '');
$status = trim($_POST['status'] ?? '');
$bankAccount = trim($_POST['bank_account'] ?? '');
$bankName = trim($_POST['bank_name'] ?? '');
$bankBranch = trim($_POST['bank_branch'] ?? '');
if ($fullName === '') $errors[] = 'Full name is required.';
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) $errors[] = 'Valid email is required.';
@ -77,10 +80,11 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$stmtProfile = db()->prepare("
UPDATE truck_owner_profiles
SET phone = ?, address_line = ?, country_id = ?, city_id = ?,
truck_type = ?, load_capacity = ?, plate_no = ?
truck_type = ?, load_capacity = ?, plate_no = ?,
bank_account = ?, bank_name = ?, bank_branch = ?
WHERE user_id = ?
");
$stmtProfile->execute([$phone, $addressLine, $countryId, $cityId, $truckType, $loadCapacity, $plateNo, $userId]);
$stmtProfile->execute([$phone, $addressLine, $countryId, $cityId, $truckType, $loadCapacity, $plateNo, $bankAccount, $bankName, $bankBranch, $userId]);
db()->commit();
$flash = 'Truck Owner profile updated successfully.';
@ -96,6 +100,9 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$owner['truck_type'] = $truckType;
$owner['load_capacity'] = $loadCapacity;
$owner['plate_no'] = $plateNo;
$owner['bank_account'] = $bankAccount;
$owner['bank_name'] = $bankName;
$owner['bank_branch'] = $bankBranch;
} catch (Throwable $e) {
db()->rollBack();
@ -202,6 +209,22 @@ render_header('Edit Truck Owner', 'admin');
</div>
</div>
<h5 class="mb-3 mt-5 border-top pt-4">Bank Details</h5>
<div class="row g-3 mb-4">
<div class="col-md-4">
<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((string)($owner['bank_account'] ?? '')) ?>">
</div>
<div class="col-md-4">
<label class="form-label" for="bank_name">Bank Name</label>
<input type="text" name="bank_name" id="bank_name" class="form-control" value="<?= e((string)($owner['bank_name'] ?? '')) ?>">
</div>
<div class="col-md-4">
<label class="form-label" for="bank_branch">Bank Branch</label>
<input type="text" name="bank_branch" id="bank_branch" class="form-control" value="<?= e((string)($owner['bank_branch'] ?? '')) ?>">
</div>
</div>
<h5 class="mb-3 mt-5 border-top pt-4">Uploaded Documents</h5>
<div class="row g-4 mb-4">
<div class="col-md-4">

View File

@ -0,0 +1,15 @@
<?php
require_once __DIR__ . '/../config.php';
$pdo = db();
try {
$pdo->exec("ALTER TABLE users ADD COLUMN profile_picture VARCHAR(255) NULL AFTER full_name");
echo "Added profile_picture column to users table.\n";
} catch (PDOException $e) {
if ($e->getCode() == '42S21') {
echo "profile_picture column already exists.\n";
} else {
echo "Error: " . $e->getMessage() . "\n";
}
}

View File

@ -12,11 +12,11 @@ try {
('company_email', 'info@example.com'),
('company_phone', '+1234567890'),
('company_address', '123 Transport St, City, Country'),
('platform_charge_percentage', '0'),
('logo_path', ''),
('favicon_path', '');
");
echo "Settings table created.\n";
echo "Settings table created/updated.\n";
} catch (Exception $e) {
echo "Error: " . $e->getMessage() . "\n";
}
}

View File

@ -184,6 +184,7 @@ CREATE TABLE IF NOT EXISTS shipments (
SQL;
db()->exec($sql);
try { db()->exec("ALTER TABLE users ADD COLUMN status ENUM('pending','active','rejected') NOT NULL DEFAULT 'active'"); } catch (Exception $e) {}
try { db()->exec("ALTER TABLE users ADD COLUMN profile_picture VARCHAR(255) NULL AFTER full_name"); } catch (Exception $e) {}
db()->exec(
@ -194,6 +195,7 @@ SQL;
full_name VARCHAR(255) NOT NULL,
role ENUM('admin','shipper','truck_owner') NOT NULL,
status ENUM('pending','active','rejected') NOT NULL DEFAULT 'active',
profile_picture VARCHAR(255) NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4"
);

View File

@ -66,36 +66,58 @@ function render_header(string $title, string $active = ''): void
</ul>
<div class="d-flex align-items-center gap-3">
<div class="dropdown">
<a class="text-decoration-none text-muted fw-semibold dropdown-toggle" href="#" id="loginDropdown" role="button" data-bs-toggle="dropdown" aria-expanded="false">
Demo Login
</a>
<ul class="dropdown-menu dropdown-menu-end shadow-sm border-0 mt-3" aria-labelledby="loginDropdown" style="border-radius: 12px;">
<li>
<a class="dropdown-item py-2 <?= $active === 'shipper' ? 'active' : '' ?>" href="<?= e(url_with_lang('shipper_dashboard.php')) ?>">
<?= e(t('nav_shipper')) ?>
</a>
</li>
<li>
<a class="dropdown-item py-2 <?= $active === 'owner' ? 'active' : '' ?>" href="<?= e(url_with_lang('truck_owner_dashboard.php')) ?>">
<?= e(t('nav_owner')) ?>
</a>
</li>
<li><hr class="dropdown-divider"></li>
<li>
<a class="dropdown-item py-2 <?= $active === 'admin' ? 'active' : '' ?>" href="<?= e(url_with_lang('admin_dashboard.php')) ?>">
<?= e(t('nav_admin')) ?>
</a>
</li>
</ul>
<?php if (isset($_SESSION['user_id'])): ?>
<a class="text-decoration-none text-muted fw-semibold dropdown-toggle" href="#" id="loginDropdown" role="button" data-bs-toggle="dropdown" aria-expanded="false">
Account
</a>
<ul class="dropdown-menu dropdown-menu-end shadow-sm border-0 mt-3" aria-labelledby="loginDropdown" style="border-radius: 12px;">
<li>
<a class="dropdown-item py-2 <?= $active === 'profile' ? 'active' : '' ?>" href="<?= e(url_with_lang('profile.php')) ?>">
<i class="bi bi-person-circle text-primary me-2"></i>My Profile
</a>
</li>
<?php if (($_SESSION['user_role'] ?? '') === 'shipper'): ?>
<li>
<a class="dropdown-item py-2 <?= $active === 'shipper' ? 'active' : '' ?>" href="<?= e(url_with_lang('shipper_dashboard.php')) ?>">
<i class="bi bi-box-seam text-primary me-2"></i><?= e(t('nav_shipper')) ?>
</a>
</li>
<?php elseif (($_SESSION['user_role'] ?? '') === 'truck_owner'): ?>
<li>
<a class="dropdown-item py-2 <?= $active === 'owner' ? 'active' : '' ?>" href="<?= e(url_with_lang('truck_owner_dashboard.php')) ?>">
<i class="bi bi-truck text-primary me-2"></i><?= e(t('nav_owner')) ?>
</a>
</li>
<?php elseif (($_SESSION['user_role'] ?? '') === 'admin'): ?>
<li>
<a class="dropdown-item py-2 <?= $active === 'admin' ? 'active' : '' ?>" href="<?= e(url_with_lang('admin_dashboard.php')) ?>">
<i class="bi bi-speedometer2 text-primary me-2"></i><?= e(t('nav_admin')) ?>
</a>
</li>
<?php endif; ?>
<li><hr class="dropdown-divider"></li>
<li>
<a class="dropdown-item py-2 text-danger" href="<?= e(url_with_lang('logout.php')) ?>">
<i class="bi bi-box-arrow-right me-2"></i>Logout
</a>
</li>
</ul>
<?php else: ?>
<a class="text-decoration-none text-muted fw-semibold" href="<?= e(url_with_lang('login.php')) ?>">
Login
</a>
<?php endif; ?>
</div>
<a class="btn btn-sm btn-outline-dark rounded-pill px-3 fw-bold" href="<?= e(current_url_with_lang($toggleLang)) ?>">
<?= e($toggleLabel) ?>
</a>
<a class="btn btn-primary btn-sm rounded-pill px-4 fw-bold shadow-sm d-none d-lg-block" href="<?= e(url_with_lang('register.php', ['role' => 'shipper'])) ?>">
Get Started
</a>
<?php if (!isset($_SESSION['user_id'])): ?>
<a class="btn btn-primary btn-sm rounded-pill px-4 fw-bold shadow-sm d-none d-lg-block" href="<?= e(url_with_lang('register.php', ['role' => 'shipper'])) ?>">
Get Started
</a>
<?php endif; ?>
</div>
</div>
</div>
@ -261,4 +283,4 @@ function render_admin_sidebar(string $active = 'dashboard'): void
</nav>
</aside>
<?php
}
}

156
login.php Normal file
View File

@ -0,0 +1,156 @@
<?php
declare(strict_types=1);
require_once __DIR__ . '/includes/layout.php';
ensure_schema();
$errors = [];
$successMessage = '';
// If logged in, redirect home
if (isset($_SESSION['user_id'])) {
header('Location: index.php');
exit;
}
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
if (isset($_POST['action']) && $_POST['action'] === 'login') {
$email = trim($_POST['email'] ?? '');
$password = (string)($_POST['password'] ?? '');
if ($email === '' || $password === '') {
$errors[] = 'Please enter both email and password.';
} else {
$stmt = db()->prepare("SELECT id, password, role, status FROM users WHERE email = ? LIMIT 1");
$stmt->execute([$email]);
$user = $stmt->fetch();
if ($user && password_verify($password, $user['password'])) {
if ($user['status'] === 'pending') {
$errors[] = 'Your account is pending approval.';
} elseif ($user['status'] === 'rejected') {
$errors[] = 'Your account has been rejected.';
} elseif ($user['status'] === 'suspended') {
$errors[] = 'Your account has been suspended.';
} else {
// Login successful
$_SESSION['user_id'] = $user['id'];
$_SESSION['user_role'] = $user['role'];
// Redirect based on role
if ($user['role'] === 'admin') {
header('Location: ' . url_with_lang('admin_dashboard.php'));
} elseif ($user['role'] === 'shipper') {
header('Location: ' . url_with_lang('shipper_dashboard.php'));
} else {
header('Location: ' . url_with_lang('truck_owner_dashboard.php'));
}
exit;
}
} else {
$errors[] = 'Invalid email or password.';
}
}
} elseif (isset($_POST['action']) && $_POST['action'] === 'reset_password') {
$email = trim($_POST['reset_email'] ?? '');
if ($email === '') {
$errors[] = 'Please enter your email to reset password.';
} elseif (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
$errors[] = 'Please enter a valid email address.';
} else {
$stmt = db()->prepare("SELECT id FROM users WHERE email = ? LIMIT 1");
$stmt->execute([$email]);
if ($stmt->fetch()) {
// In a real app we'd send an email with a reset token here.
// Since this is a demo, we will just show a success message.
$successMessage = 'A password reset link has been sent to your email address (simulated).';
} else {
// To prevent email enumeration, still say a link was sent.
$successMessage = 'A password reset link has been sent to your email address (simulated).';
}
}
}
}
render_header('Login / Reset Password', 'login');
?>
<div class="row justify-content-center">
<div class="col-md-6 col-lg-5">
<?php if ($errors): ?>
<div class="alert alert-danger shadow-sm rounded-4 border-0 mb-4">
<ul class="mb-0">
<?php foreach ($errors as $e): ?>
<li><?= e($e) ?></li>
<?php endforeach; ?>
</ul>
</div>
<?php endif; ?>
<?php if ($successMessage): ?>
<div class="alert alert-success shadow-sm rounded-4 border-0 mb-4">
<?= e($successMessage) ?>
</div>
<?php endif; ?>
<div class="card shadow-sm border-0 rounded-4 mb-4" id="loginFormCard">
<div class="card-body p-4 p-md-5">
<div class="text-center mb-4">
<h2 class="fw-bold text-dark">Welcome Back</h2>
<p class="text-muted">Sign in to your account to continue</p>
</div>
<form method="post" action="">
<input type="hidden" name="action" value="login">
<div class="mb-3">
<label for="email" class="form-label fw-bold">Email address</label>
<input type="email" class="form-control form-control-lg bg-light border-0 rounded-3" id="email" name="email" required autofocus placeholder="name@example.com">
</div>
<div class="mb-4">
<div class="d-flex justify-content-between align-items-center mb-1">
<label for="password" class="form-label fw-bold mb-0">Password</label>
<a href="#" class="small text-decoration-none text-primary" onclick="document.getElementById('loginFormCard').classList.add('d-none'); document.getElementById('resetFormCard').classList.remove('d-none'); return false;">Forgot password?</a>
</div>
<input type="password" class="form-control form-control-lg bg-light border-0 rounded-3" id="password" name="password" required placeholder="Enter your password">
</div>
<button type="submit" class="btn btn-primary btn-lg w-100 rounded-pill fw-bold shadow-sm">Sign In</button>
<div class="text-center mt-4">
<p class="text-muted small mb-0">Don't have an account? <a href="<?= e(url_with_lang('register.php')) ?>" class="text-decoration-none text-primary fw-bold">Register now</a></p>
</div>
</form>
</div>
</div>
<div class="card shadow-sm border-0 rounded-4 mb-4 d-none" id="resetFormCard">
<div class="card-body p-4 p-md-5">
<div class="text-center mb-4">
<h2 class="fw-bold text-dark">Reset Password</h2>
<p class="text-muted">Enter your email and we'll send you a link to reset your password</p>
</div>
<form method="post" action="">
<input type="hidden" name="action" value="reset_password">
<div class="mb-4">
<label for="reset_email" class="form-label fw-bold">Email address</label>
<input type="email" class="form-control form-control-lg bg-light border-0 rounded-3" id="reset_email" name="reset_email" required placeholder="name@example.com">
</div>
<button type="submit" class="btn btn-primary btn-lg w-100 rounded-pill fw-bold shadow-sm mb-3">Send Reset Link</button>
<div class="text-center">
<a href="#" class="text-decoration-none text-muted small fw-bold" onclick="document.getElementById('resetFormCard').classList.add('d-none'); document.getElementById('loginFormCard').classList.remove('d-none'); return false;"><i class="bi bi-arrow-left me-1"></i>Back to login</a>
</div>
</form>
</div>
</div>
</div>
</div>
<?php render_footer(); ?>

23
logout.php Normal file
View File

@ -0,0 +1,23 @@
<?php
declare(strict_types=1);
require_once __DIR__ . '/includes/app.php';
// Unset all session variables
$_SESSION = [];
// Destroy the session cookie
if (ini_get("session.use_cookies")) {
$params = session_get_cookie_params();
setcookie(session_name(), '', time() - 42000,
$params["path"], $params["domain"],
$params["secure"], $params["httponly"]
);
}
// Destroy the session
session_destroy();
// Redirect to home page
header('Location: index.php');
exit;

100
patch.py
View File

@ -1,100 +0,0 @@
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")

176
profile.php Normal file
View File

@ -0,0 +1,176 @@
<?php
declare(strict_types=1);
require_once __DIR__ . '/includes/layout.php';
ensure_schema();
// Demo auth: if not logged in, pretend to be user 1
$userId = $_SESSION['user_id'] ?? 1;
$errors = [];
// Fetch current user data
try {
$stmt = db()->prepare("SELECT * FROM users WHERE id = :id");
$stmt->execute([':id' => $userId]);
$user = $stmt->fetch();
if (!$user) {
die("Demo user not found. Please register an account first.");
}
} catch (Throwable $e) {
die("Database error: " . $e->getMessage());
}
if ($_SERVER['REQUEST_METHOD'] === 'POST' && ($_POST['action'] ?? '') === 'update_profile') {
$fullName = trim($_POST['full_name'] ?? '');
if ($fullName === '') {
$errors[] = t('error_required');
}
$profilePicPath = $user['profile_picture'];
// Handle file upload
if (isset($_FILES['profile_picture']) && $_FILES['profile_picture']['error'] === UPLOAD_ERR_OK) {
$allowedTypes = ['image/jpeg', 'image/png', 'image/gif', 'image/webp'];
$fileInfo = finfo_open(FILEINFO_MIME_TYPE);
$mimeType = finfo_file($fileInfo, $_FILES['profile_picture']['tmp_name']);
finfo_close($fileInfo);
if (!in_array($mimeType, $allowedTypes)) {
$errors[] = "Invalid image format. Please upload JPG, PNG, GIF, or WEBP.";
} else {
$uploadDir = __DIR__ . '/uploads/profiles/';
if (!is_dir($uploadDir)) {
mkdir($uploadDir, 0775, true);
}
$extension = pathinfo($_FILES['profile_picture']['name'], PATHINFO_EXTENSION);
$filename = 'profile_' . $userId . '_' . time() . '.' . $extension;
$destination = $uploadDir . $filename;
if (move_uploaded_file($_FILES['profile_picture']['tmp_name'], $destination)) {
$profilePicPath = '/uploads/profiles/' . $filename;
} else {
$errors[] = "Failed to save uploaded file.";
}
}
}
if (!$errors) {
try {
$updateStmt = db()->prepare("UPDATE users SET full_name = :name, profile_picture = :pic WHERE id = :id");
$updateStmt->execute([
':name' => $fullName,
':pic' => $profilePicPath,
':id' => $userId
]);
set_flash('success', "Profile updated successfully.");
header("Location: " . url_with_lang('profile.php'));
exit;
} catch (Throwable $e) {
$errors[] = "Database update failed: " . $e->getMessage();
}
}
}
render_header('My Profile', 'profile');
$flash = get_flash();
?>
<div class="row justify-content-center">
<div class="col-md-8 col-lg-6">
<div class="panel p-4 p-md-5">
<div class="d-flex align-items-center mb-4">
<i class="bi bi-person-badge fs-2 text-primary me-3"></i>
<h2 class="section-title mb-0">My Profile</h2>
</div>
<?php if ($flash): ?>
<div class="alert alert-<?= $flash['type'] === 'error' ? 'danger' : 'success' ?> mb-4" data-auto-dismiss="true">
<?= e($flash['message']) ?>
</div>
<?php endif; ?>
<?php if ($errors): ?>
<div class="alert alert-danger mb-4">
<ul class="mb-0">
<?php foreach ($errors as $err): ?>
<li><?= e($err) ?></li>
<?php endforeach; ?>
</ul>
</div>
<?php endif; ?>
<form method="post" enctype="multipart/form-data">
<input type="hidden" name="action" value="update_profile">
<div class="text-center mb-4">
<div class="position-relative d-inline-block">
<?php if (!empty($user['profile_picture'])): ?>
<img src="<?= e($user['profile_picture']) ?>" alt="Profile Picture" class="rounded-circle shadow-sm object-fit-cover" style="width: 120px; height: 120px;">
<?php else: ?>
<div class="rounded-circle bg-light d-flex align-items-center justify-content-center shadow-sm" style="width: 120px; height: 120px;">
<i class="bi bi-person text-secondary" style="font-size: 4rem;"></i>
</div>
<?php endif; ?>
<label for="profile_picture" class="position-absolute bottom-0 end-0 bg-primary text-white rounded-circle p-2 cursor-pointer shadow" style="cursor: pointer;" title="Change Picture">
<i class="bi bi-camera-fill"></i>
</label>
</div>
<input type="file" id="profile_picture" name="profile_picture" class="d-none" accept="image/jpeg,image/png,image/gif,image/webp" onchange="previewImage(this)">
<div class="small text-muted mt-2">JPG, PNG, or GIF up to 5MB</div>
</div>
<div class="mb-3">
<label class="form-label fw-bold">Full Name</label>
<input type="text" class="form-control form-control-lg" name="full_name" value="<?= e($user['full_name'] ?? '') ?>" required>
</div>
<div class="mb-3">
<label class="form-label fw-bold">Email Address</label>
<input type="email" class="form-control form-control-lg bg-light" value="<?= e($user['email'] ?? '') ?>" readonly disabled>
<div class="form-text">Email address cannot be changed.</div>
</div>
<div class="mb-4">
<label class="form-label fw-bold">Account Role</label>
<input type="text" class="form-control form-control-lg bg-light text-capitalize" value="<?= e($user['role'] ?? '') ?>" readonly disabled>
</div>
<button type="submit" class="btn btn-primary btn-lg w-100 shadow-sm rounded-pill fw-bold">
Save Changes
</button>
</form>
</div>
</div>
</div>
<script>
function previewImage(input) {
if (input.files && input.files[0]) {
var reader = new FileReader();
reader.onload = function(e) {
var imgContainer = input.previousElementSibling;
if (imgContainer.querySelector('img')) {
imgContainer.querySelector('img').src = e.target.result;
} else {
var newImg = document.createElement('img');
newImg.src = e.target.result;
newImg.className = 'rounded-circle shadow-sm object-fit-cover';
newImg.style.width = '120px';
newImg.style.height = '120px';
var iconDiv = imgContainer.querySelector('div');
if (iconDiv) {
iconDiv.replaceWith(newImg);
}
}
}
reader.readAsDataURL(input.files[0]);
}
}
</script>
<?php render_footer(); ?>

View File

@ -19,6 +19,9 @@ $values = [
'truck_type' => '',
'load_capacity' => '',
'plate_no' => '',
'bank_account' => '',
'bank_name' => '',
'bank_branch' => '',
];
$countries = db()->query("SELECT id, name_en, name_ar FROM countries ORDER BY name_en ASC")->fetchAll();
@ -165,8 +168,8 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
if (!$errors) {
$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 (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"
"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,
@ -177,6 +180,9 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$truckType,
$loadCapacity,
$plateNo,
$bankAccount,
$bankName,
$bankBranch,
json_encode($idCardPaths, JSON_UNESCAPED_SLASHES),
$truckPic,
json_encode($regPaths, JSON_UNESCAPED_SLASHES),
@ -202,6 +208,9 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
'truck_type' => '',
'load_capacity' => '',
'plate_no' => '',
'bank_account' => '',
'bank_name' => '',
'bank_branch' => '',
];
}
} catch (Throwable $e) {
@ -311,6 +320,19 @@ render_header('Shipper & Truck Owner Registration');
<input type="text" name="plate_no" id="plate_no" class="form-control" value="<?= e($values['plate_no']) ?>">
</div>
<div class="col-md-4 mt-3">
<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-3">
<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-3">
<label class="form-label" for="bank_branch">Bank Branch</label>
<input type="text" name="bank_branch" id="bank_branch" class="form-control" value="<?= e($values['bank_branch']) ?>">
</div>
<div class="col-md-6 mt-3">
<label class="form-label" for="id_card_front">ID card (Front Face)</label>
<input type="file" name="id_card_front" id="id_card_front" class="form-control" accept="image/png,image/jpeg,image/webp">

View File

@ -1,16 +0,0 @@
<?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";
}

View File

@ -1,105 +0,0 @@
<?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";