diff --git a/admin_company_profile.php b/admin_company_profile.php index 128f35c..95efdff 100644 --- a/admin_company_profile.php +++ b/admin_company_profile.php @@ -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');

Company Profile

-

Update your app name, logo, favicon, and contact details.

+

Update your app name, logo, favicon, contact details, and platform charge.

@@ -122,6 +125,19 @@ render_header('Company Profile', 'admin');
Displayed in the footer.
+
+ +
+ + % +
+
Percentage applied as a platform fee.
+
+ +
+
+
+
@@ -152,4 +168,4 @@ render_header('Company Profile', 'admin');
- + \ No newline at end of file diff --git a/admin_truck_owner_edit.php b/admin_truck_owner_edit.php index dd2929c..13750e8 100644 --- a/admin_truck_owner_edit.php +++ b/admin_truck_owner_edit.php @@ -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'); +
Bank Details
+
+
+ + +
+
+ + +
+
+ + +
+
+
Uploaded Documents
diff --git a/db/migrations/add_profile_picture_to_users.php b/db/migrations/add_profile_picture_to_users.php new file mode 100644 index 0000000..678759a --- /dev/null +++ b/db/migrations/add_profile_picture_to_users.php @@ -0,0 +1,15 @@ +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"; + } +} + diff --git a/db/migrations/add_settings_table.php b/db/migrations/add_settings_table.php index 3b53e07..d4dbd5a 100644 --- a/db/migrations/add_settings_table.php +++ b/db/migrations/add_settings_table.php @@ -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"; -} - +} \ No newline at end of file diff --git a/includes/app.php b/includes/app.php index d811604..1af88b7 100644 --- a/includes/app.php +++ b/includes/app.php @@ -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" ); diff --git a/includes/layout.php b/includes/layout.php index 8fad3c6..45a1ef9 100644 --- a/includes/layout.php +++ b/includes/layout.php @@ -66,36 +66,58 @@ function render_header(string $title, string $active = ''): void
@@ -261,4 +283,4 @@ function render_admin_sidebar(string $active = 'dashboard'): void 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'); +?> +
+
+ + +
+
    + +
  • + +
+
+ + + +
+ +
+ + +
+
+
+

Welcome Back

+

Sign in to your account to continue

+
+ +
+ + +
+ + +
+ +
+
+ + Forgot password? +
+ +
+ + + +
+

Don't have an account? Register now

+
+
+
+
+ +
+
+
+

Reset Password

+

Enter your email and we'll send you a link to reset your password

+
+ +
+ + +
+ + +
+ + + + +
+
+
+ +
+
+ + \ No newline at end of file diff --git a/logout.php b/logout.php new file mode 100644 index 0000000..5681bf3 --- /dev/null +++ b/logout.php @@ -0,0 +1,23 @@ + '',", " '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 = "
- - \"> -
" -r7 = "
- - \"> -
- -

Bank Details for Payouts

-
- - \" required> -
-
- - \" required> -
-
- - \" required> -
" -content = content.replace(s7, r7) - -with open('register.php', 'w') as f: - f.write(content) - -print("Replaced in register.php") diff --git a/profile.php b/profile.php new file mode 100644 index 0000000..c45c4a4 --- /dev/null +++ b/profile.php @@ -0,0 +1,176 @@ +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(); +?> + +
+
+
+
+ +

My Profile

+
+ + +
+ +
+ + + +
+
    + +
  • + +
+
+ + +
+ + +
+
+ + Profile Picture + +
+ +
+ + + +
+ +
JPG, PNG, or GIF up to 5MB
+
+ +
+ + +
+ +
+ + +
Email address cannot be changed.
+
+ +
+ + +
+ + +
+
+
+
+ + + + diff --git a/register.php b/register.php index e61dc27..bc94614 100644 --- a/register.php +++ b/register.php @@ -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'); +
+ + +
+
+ + +
+
+ + +
+
diff --git a/tmp_edit.php b/tmp_edit.php deleted file mode 100644 index db9d736..0000000 --- a/tmp_edit.php +++ /dev/null @@ -1,16 +0,0 @@ - '',"; -$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 = <<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 = <<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; - -$r7 = << - - - - -

Bank Details for Payouts

-
- - -
-
- - -
-
- - -
-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"; -