Compare commits

..

No commits in common. "ai-dev" and "master" have entirely different histories.

71 changed files with 183 additions and 4396 deletions

View File

@ -1,132 +0,0 @@
# Comprehensive Project Monograph: Advanced Vehicle Marketplace System
## 1. Introduction
This document serves as a complete technical monograph for the Vehicle Marketplace System, a full-stack web application designed for the educational sector and general vehicle trading. This system provides a robust platform for users to list vehicles, manage sales, and for buyers to submit purchase requests through a secure, modern interface.
## 2. System Architecture
The application follows a modular LAMP (Linux, Apache, MySQL/MariaDB, PHP) architecture. It is designed to be scalable, secure, and user-centric.
### 2.1 Backend Layer
- **Language:** PHP 8.x (Vanilla PHP for maximum performance and compatibility).
- **Database Interaction:** PDO (PHP Data Objects) with prepared statements to prevent SQL injection.
- **Session Management:** Secure PHP sessions for user authentication and role-based access control.
### 2.2 Frontend Layer
- **HTML5 & CSS3:** Modern semantic markup and advanced styling.
- **Design Paradigm:** Sophisticated Dark Theme with Glassmorphism effects.
- **Typography:** Inter font family for high legibility and professional aesthetics.
- **Responsive Design:** Mobile-first approach using CSS Grid and Flexbox.
### 2.3 Database Layer
- **Engine:** MariaDB/MySQL.
- **Schema Design:** Normalized relational structure with foreign key constraints.
## 3. Technology Stack Detail
### 3.1 PHP (Hypertext Preprocessor)
Used for all server-side logic, including:
- User registration and authentication.
- CRUD operations for vehicle listings.
- Purchase request processing.
- Admin panel logic.
- Email notifications via `MailService.php`.
### 3.2 MariaDB
The database stores all critical information:
- **users table:** Stores user credentials, contact info (phone, address), and roles.
- **cars table:** Stores vehicle details (brand, model, price, description, status).
- **car_images table:** Manages multiple images per vehicle with a primary image flag.
- **purchases table:** Tracks buying requests, bank transaction IDs, and status (pending/approved/rejected).
- **messages table:** Stores contact form submissions.
### 3.3 CSS (Cascading Style Sheets)
The styling is centralized in `assets/css/style.css`, featuring:
- **Custom Variables:** `--primary-color` (Gold), `--bg-color` (Deep Slate), etc.
- **Glassmorphism:** Using `backdrop-filter: blur()` and semi-transparent backgrounds for a premium feel.
- **Animations:** Smooth transitions (`cubic-bezier`) for interactive elements.
## 4. Database Schema Specification
### 4.1 Table: users
| Column | Type | Description |
|---|---|---|
| id | INT | Primary Key, Auto-increment |
| username | VARCHAR(50) | Unique username |
| password | VARCHAR(255) | Hashed password |
| email | VARCHAR(100) | Unique email |
| phone | VARCHAR(20) | User contact number |
| address | TEXT | User physical address |
| role | ENUM | 'user' or 'admin' |
| created_at | TIMESTAMP | Account creation date |
### 4.2 Table: cars
| Column | Type | Description |
|---|---|---|
| id | INT | Primary Key |
| user_id | INT | Foreign Key to users |
| brand | VARCHAR(50) | Vehicle brand |
| model | VARCHAR(50) | Vehicle model |
| year | INT | Manufacturing year |
| price | DECIMAL | Listing price |
| city | VARCHAR(50) | Location |
| description | TEXT | Detailed info |
| status | ENUM | 'pending', 'approved', 'rejected', 'sold' |
### 4.3 Table: purchases
| Column | Type | Description |
|---|---|---|
| id | INT | Primary Key |
| car_id | INT | Foreign Key to cars |
| user_id | INT | Foreign Key to users |
| bank_id | VARCHAR(100) | Transaction reference |
| personal_info| TEXT | Buyer's additional info |
| status | ENUM | 'pending', 'approved', 'rejected' |
## 5. Functional Walkthrough
### 5.1 User Experience (UX)
The user journey starts at the landing page (`index.php`), featuring a high-impact hero section. Users can browse vehicles in `cars.php` with advanced filtering.
### 5.2 Seller Workflow
1. **Login/Register:** Secure entry point.
2. **Dashboard:** Overview of listings.
3. **Add Car:** Upload vehicle details and images.
4. **Management:** Edit or mark listings as sold.
### 5.3 Buyer Workflow
1. **Discovery:** Find a vehicle.
2. **Purchase Request:** Submit a formal request with payment reference (Bank ID).
3. **Tracking:** View request status in the dashboard.
4. **Receipt:** Generate a digital receipt upon approval.
### 5.4 Admin Capabilities
- **Dashboard:** High-level stats (Total sales, users, cars).
- **Approval System:** Approve or reject car listings and purchase requests.
- **User Management:** Oversee the community.
- **Communications:** Manage messages from the contact form.
## 6. UI/UX Design Principles
### 6.1 Sophisticated Dark Theme
The "Darker and User-Friendly" theme uses a color palette that reduces eye strain and emphasizes high-value content.
- **Background:** `#0f172a` (Deep Space)
- **Accents:** `#d4af37` (Luxury Gold)
- **Contrast:** High legibility white and slate-gray text.
### 6.2 Modern Components
- **Cards:** Elevated cards with hover scaling.
- **Glassmorphism:** Professional blur effects for navigation and overlays.
- **Buttons:** Large, accessible touch targets with subtle shadows.
## 7. Security and Integrity
- **Password Hashing:** `password_hash()` and `password_verify()` for industry-standard security.
- **SQL Protection:** 100% usage of PDO prepared statements.
- **Input Sanitization:** `htmlspecialchars()` for XSS prevention.
- **State Management:** Secure session handling and CSRF awareness.
## 8. Conclusion
This system represents a state-of-the-art vehicle marketplace, combining technical excellence with a premium user experience. It is designed to be both a functional tool and a beautiful interface, adhering to the highest standards of modern web development.
---
*Monograph created on February 23, 2026.*
*Version 1.0.0*

143
README.md
View File

@ -1,143 +0,0 @@
# AfgCars - Modern Automotive Marketplace
AfgCars is a robust, visually stunning automotive marketplace platform designed for the Afghan car market. It features a modern "glassmorphism" design, a powerful admin panel, and seamless car listing management for both individual sellers and administrators.
## 🚀 Quick Start (How to Run)
### 1. Database Setup
The application requires a MySQL/MariaDB database.
**Option A: Import SQL File (Recommended)**
1. Create a database named `app_38703` (or the name specified in `db/config.php`).
2. Import the `database.sql` file located in the `db/` directory:
```bash
mysql -u your_username -p app_38703 < db/database.sql
```
**Option B: Run Setup Script**
Alternatively, you can run the PHP setup script which creates the tables automatically:
```bash
php db/setup.php
```
### 2. Configuration
Ensure your database credentials in `db/config.php` are correct:
```php
define('DB_HOST', '127.0.0.1');
define('DB_NAME', 'app_38703');
define('DB_USER', 'your_user');
define('DB_PASS', 'your_password');
```
### 3. Launch
Open your web browser and navigate to the project root (e.g., `http://localhost/`).
---
## 🚀 Key Features
- **Modern UI/UX**: Clean, youthful, and inviting design with glassmorphism effects.
- **Admin Dashboard**: Full control over users, car listings, and customer messages.
- **User Dashboard**: Personal area for users to manage their own car listings.
- **Car Marketplace**: Advanced search and filtering for cars across various cities in Afghanistan.
- **Responsive Design**: Fully functional on mobile, tablet, and desktop devices.
- **Secure Authentication**: Robust registration and login system with role-based access control.
## 🛠️ Technology Stack
- **Backend**: PHP 8.x
- **Database**: MariaDB/MySQL
- **Frontend**: HTML5, CSS3 (Custom Glassmorphism Styles), JavaScript (Vanilla)
- **Email**: Integrated PHPMailer service
## 👤 Default Admin Account
Use these credentials to access the administrative panel:
- **Email**: `admin@gmail.com`
- **Password**: `12345678`
- **Role**: `admin`
## 📊 Entity Relationship Diagram (ERD)
```mermaid
erDiagram
USERS ||--o{ CARS : "posts"
USERS ||--o{ REVIEWS : "writes"
USERS ||--o{ PURCHASES : "makes"
CARS ||--o{ CAR_IMAGES : "has"
CARS ||--o{ REVIEWS : "receives"
CARS ||--o{ PURCHASES : "is_part_of"
USERS {
int id PK
string name
string email UK
string password
enum role "guest, user, admin"
enum status "active, inactive"
timestamp created_at
}
CARS {
int id PK
int user_id FK
string brand
string model
int year
decimal price
string city
text description
enum status "pending, approved, rejected, sold"
boolean is_hot_deal
timestamp created_at
}
CAR_IMAGES {
int id PK
int car_id FK
string image_path
boolean is_main
}
REVIEWS {
int id PK
int car_id FK
int user_id FK
int rating
text comment
enum status "pending, approved"
timestamp created_at
}
PURCHASES {
int id PK
int car_id FK
int user_id FK
string buyer_name
string buyer_email
string buyer_phone
enum status "pending, completed, cancelled"
timestamp created_at
}
CONTACT_MESSAGES {
int id PK
string name
string email
string subject
text message
enum status "unread, read, answered"
timestamp created_at
}
```
## 📁 Project Structure
- `index.php`: Landing page and marketplace hero.
- `cars.php`: Searchable list of all vehicles.
- `car_detail.php`: Detailed view of a single car with photo gallery.
- `admin_dashboard.php`: Entry point for administrative management.
- `dashboard.php`: User-specific panel for listing management.
- `db/`: Database configuration, setup scripts, and `database.sql` export.
- `assets/`: CSS, JS, and image assets.
- `includes/`: Reusable header and footer components.
- `mail/`: Built-in email service components.
## 📝 License
This project is built for educational and demonstration purposes.

View File

@ -1,77 +0,0 @@
<?php
require_once __DIR__ . '/includes/header.php';
?>
<section class="hero" style="height: 50vh; background: linear-gradient(rgba(15, 23, 42, 0.8), rgba(15, 23, 42, 0.8)), url('assets/images/about-hero.jpg') center/cover no-repeat fixed;">
<h1 class="fw-black" style="font-size: 5rem; letter-spacing: -3px; color: #fff;">Our Legacy</h1>
<p class="text-secondary fw-bold" style="font-size: 1.3rem; max-width: 700px; margin-left: auto; margin-right: auto;">The definitive portal for elite automotive excellence in Afghanistan.</p>
</section>
<div class="container" style="padding: 10rem 0;">
<div class="grid" style="grid-template-columns: 1fr 1fr; align-items: center; gap: 6rem;">
<div class="glass" style="padding: 4rem; border-top: 5px solid var(--primary-color);">
<h2 class="fw-black mb-2 text-gold" style="font-size: 2.5rem; text-transform: uppercase; letter-spacing: 2px;">Our Strategic Mission</h2>
<p class="text-secondary mb-2 fw-bold" style="font-size: 1.2rem; line-height: 2;">
Established in 2026, AfgCars has redefined the standards of the Afghan automotive industry. Our platform is engineered to deliver absolute transparency, unparalleled security, and an elite trading experience for the nation's most discerning car enthusiasts.
</p>
<p class="text-secondary fw-bold" style="font-size: 1.15rem; line-height: 2;">
We bridge the critical gap between high-end global automotive luxury and the dynamic local Afghan market, ensuring every transaction is verified and every vehicle is an asset.
</p>
</div>
<div style="position: relative;">
<img src="assets/images/about-team.jpg" alt="Team" class="w-full" style="border-radius: 32px; box-shadow: 0 30px 60px rgba(0,0,0,0.5); border: 1px solid var(--glass-border);">
<div style="position: absolute; bottom: -30px; right: -30px; background: var(--primary-color); padding: 2.5rem; border-radius: 20px; color: #000; box-shadow: 0 20px 40px rgba(0,0,0,0.3);">
<h3 class="fw-black" style="font-size: 1.5rem;">EST. 2026</h3>
<p class="fw-bold text-sm">Founded in Kabul</p>
</div>
</div>
</div>
</div>
<div class="container" style="padding: 8rem 0;">
<h2 class="section-title justify-center mb-4" style="font-size: 3.5rem;">Our National Network</h2>
<div class="grid grid-3 mt-3">
<div class="glass text-center" style="padding: 4rem 2rem;">
<h3 class="fw-black text-gold mb-1" style="font-size: 1.6rem; text-transform: uppercase;">Kabul Main Experience</h3>
<p class="text-secondary fw-bold">Wazir Akbar Khan, District 10</p>
<p class="text-secondary fw-bold">Kabul, Afghanistan</p>
<p class="fw-black mt-2" style="font-size: 1.3rem; color: #fff;">+93 700 123 456</p>
</div>
<div class="glass text-center" style="padding: 4rem 2rem;">
<h3 class="fw-black text-gold mb-1" style="font-size: 1.6rem; text-transform: uppercase;">Herat Elite Branch</h3>
<p class="text-secondary fw-bold">Jada-e-Main, Near Blue Mosque</p>
<p class="text-secondary fw-bold">Herat, Afghanistan</p>
<p class="fw-black mt-2" style="font-size: 1.3rem; color: #fff;">+93 700 987 654</p>
</div>
<div class="glass text-center" style="padding: 4rem 2rem;">
<h3 class="fw-black text-gold mb-1" style="font-size: 1.6rem; text-transform: uppercase;">Mazar-i-Sharif Luxury</h3>
<p class="text-secondary fw-bold">Balkh Gate National Road</p>
<p class="text-secondary fw-bold">Mazar-i-Sharif, Afghanistan</p>
<p class="fw-black mt-2" style="font-size: 1.3rem; color: #fff;">+93 700 456 789</p>
</div>
</div>
</div>
<div class="container" style="text-align: center; background: rgba(30, 41, 59, 0.4); padding: 10rem 6%; border-radius: 48px; margin-bottom: 8rem;">
<h2 class="fw-black mb-4" style="font-size: 3.5rem; color: #fff;">Unrivaled Standards</h2>
<div class="grid grid-4 mt-3">
<div>
<h1 class="text-gold fw-black" style="font-size: 5rem; line-height: 1;">800+</h1>
<p class="text-secondary fw-bold" style="font-size: 1.1rem; text-transform: uppercase; letter-spacing: 2px;">Premium Sales</p>
</div>
<div>
<h1 class="text-gold fw-black" style="font-size: 5rem; line-height: 1;">24/7</h1>
<p class="text-secondary fw-bold" style="font-size: 1.1rem; text-transform: uppercase; letter-spacing: 2px;">Concierge Access</p>
</div>
<div>
<h1 class="text-gold fw-black" style="font-size: 5rem; line-height: 1;">100%</h1>
<p class="text-secondary fw-bold" style="font-size: 1.1rem; text-transform: uppercase; letter-spacing: 2px;">Verified Listings</p>
</div>
<div>
<h1 class="text-gold fw-black" style="font-size: 5rem; line-height: 1;">08+</h1>
<p class="text-secondary fw-bold" style="font-size: 1.1rem; text-transform: uppercase; letter-spacing: 2px;">National Hubs</p>
</div>
</div>
</div>
<?php require_once __DIR__ . '/includes/footer.php'; ?>

View File

@ -1,186 +0,0 @@
<?php
require_once __DIR__ . '/includes/header.php';
if (!isset($_SESSION['user_id'])) {
header('Location: login.php');
exit;
}
$error = '';
$success = false;
$pdo = db();
// Fetch current user details to pre-fill
$stmt = $pdo->prepare("SELECT phone, address FROM users WHERE id = ?");
$stmt->execute([$_SESSION['user_id']]);
$user_info = $stmt->fetch();
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$brand = $_POST['brand'] ?? '';
$model = $_POST['model'] ?? '';
$year = $_POST['year'] ?? '';
$price = $_POST['price'] ?? '';
$city = $_POST['city'] ?? '';
$description = $_POST['description'] ?? '';
$phone = $_POST['phone'] ?? '';
$address = $_POST['address'] ?? '';
// Update user info if provided
if ($phone || $address) {
$stmt = $pdo->prepare("UPDATE users SET phone = ?, address = ? WHERE id = ?");
$stmt->execute([$phone, $address, $_SESSION['user_id']]);
}
try {
$pdo->beginTransaction();
$stmt = $pdo->prepare("INSERT INTO cars (user_id, brand, model, year, price, city, description, status) VALUES (?, ?, ?, ?, ?, ?, ?, 'pending')");
$stmt->execute([$_SESSION['user_id'], $brand, $model, $year, $price, $city, $description]);
$carId = $pdo->lastInsertId();
// Handle Image Upload
if (isset($_FILES['car_image']) && $_FILES['car_image']['error'] === UPLOAD_ERR_OK) {
$fileTmpPath = $_FILES['car_image']['tmp_name'];
$fileName = $_FILES['car_image']['name'];
$fileSize = $_FILES['car_image']['size'];
$fileType = $_FILES['car_image']['type'];
$fileNameCmps = explode(".", $fileName);
$fileExtension = strtolower(end($fileNameCmps));
$allowedfileExtensions = array('jpg', 'gif', 'png', 'jpeg', 'webp');
if (in_array($fileExtension, $allowedfileExtensions)) {
$uploadFileDir = './assets/images/uploads/';
$newFileName = md5(time() . $fileName) . '.' . $fileExtension;
$dest_path = $uploadFileDir . $newFileName;
if(move_uploaded_file($fileTmpPath, $dest_path)) {
$imagePath = 'assets/images/uploads/' . $newFileName;
$stmt = $pdo->prepare("INSERT INTO car_images (car_id, image_path, is_main) VALUES (?, ?, 1)");
$stmt->execute([$carId, $imagePath]);
} else {
throw new Exception("There was an error moving the uploaded file.");
}
} else {
throw new Exception("Upload failed. Allowed file types: " . implode(',', $allowedfileExtensions));
}
} else if (!empty($_POST['image_url'])) {
$stmt = $pdo->prepare("INSERT INTO car_images (car_id, image_path, is_main) VALUES (?, ?, 1)");
$stmt->execute([$carId, $_POST['image_url']]);
}
$pdo->commit();
$success = true;
} catch (Exception $e) {
$pdo->rollBack();
$error = "Failed to list car: " . $e->getMessage();
}
}
$cities = ['Kabul', 'Herat', 'Mazar-i-Sharif', 'Kandahar', 'Jalalabad', 'Kunduz', 'Ghazni', 'Balkh'];
?>
<div class="container" style="max-width: 1000px; padding: 4rem 0;">
<div class="box" style="padding: 4.5rem;">
<h1 class="fw-black mb-1" style="font-size: 3rem; color: #fff;">List Your Vehicle</h1>
<p class="text-secondary mb-3" style="font-size: 1.15rem; font-weight: 500;">Provide all details about your car and yourself. Our team will review and approve your listing shortly.</p>
<?php if ($success): ?>
<div class="glass text-center" style="padding: 3rem; border-color: var(--success); background: rgba(46, 213, 115, 0.05); color: var(--success); margin-bottom: 4rem; border-radius: 24px;">
<h3 class="fw-black mb-1" style="font-size: 2rem;">🎉 Listing Successfully Submitted!</h3>
<p class="text-secondary mb-2" style="font-size: 1.1rem; font-weight: 700;">Your vehicle and seller documentation are now under review. Check your dashboard for status updates.</p>
<div class="mt-2">
<a href="dashboard.php" class="btn btn-primary btn-lg">Return to My Dashboard</a>
</div>
</div>
<?php endif; ?>
<?php if ($error): ?>
<div class="alert alert-error mb-2"><?= $error ?></div>
<?php endif; ?>
<form method="POST" enctype="multipart/form-data">
<h3 class="fw-black text-gold mb-2" style="font-size: 1.3rem; text-transform: uppercase; letter-spacing: 1px;">1. Vehicle Details</h3>
<div class="grid grid-2 mb-2">
<div class="form-group">
<label>Vehicle Brand</label>
<input type="text" name="brand" class="form-control" required placeholder="e.g. Toyota">
</div>
<div class="form-group">
<label>Vehicle Model</label>
<input type="text" name="model" class="form-control" required placeholder="e.g. Land Cruiser">
</div>
</div>
<div class="grid grid-2 mb-2">
<div class="form-group">
<label>Manufacturing Year</label>
<input type="number" name="year" class="form-control" required placeholder="2024" min="1990" max="<?= date('Y') + 1 ?>">
</div>
<div class="form-group">
<label>Asking Price (USD)</label>
<input type="number" name="price" class="form-control" required placeholder="55000">
</div>
</div>
<div class="form-group">
<label>Current City Location</label>
<select name="city" class="form-control" required>
<?php foreach ($cities as $c): ?>
<option value="<?= $c ?>"><?= $c ?></option>
<?php endforeach; ?>
</select>
</div>
<div class="form-group">
<label>Vehicle Photography</label>
<div class="glass text-center" style="padding: 3rem; border: 3px dashed var(--glass-border); border-radius: 20px; background: rgba(0,0,0,0.1);">
<input type="file" name="car_image" id="car_image" style="display: none;" accept="image/*">
<label for="car_image" style="cursor: pointer; display: block;">
<div style="font-size: 3.5rem; margin-bottom: 1.5rem; filter: drop-shadow(0 5px 15px rgba(0,0,0,0.3));">📸</div>
<div class="fw-black text-gold" style="font-size: 1.2rem; text-transform: uppercase; letter-spacing: 1px;">Click to Choose Image</div>
<div class="text-secondary text-sm mt-1 fw-bold">Professional quality JPG, PNG or WEBP recommended (Max 5MB)</div>
</label>
<div id="file-name" class="mt-2 fw-black" style="color: var(--success); font-size: 1rem; display: none;"></div>
</div>
<div class="mt-2">
<label>Or Provide External Image URL</label>
<input type="url" name="image_url" class="form-control" placeholder="https://example.com/premium-car-image.jpg">
</div>
</div>
<div class="form-group">
<label>Vehicle Description & Special Features</label>
<textarea name="description" class="form-control" rows="5" required placeholder="Enter all details about current condition, special features, and maintenance history..."></textarea>
</div>
<hr style="margin: 4rem 0; border: 0; border-top: 1px solid var(--glass-border);">
<h3 class="fw-black text-gold mb-2" style="font-size: 1.3rem; text-transform: uppercase; letter-spacing: 1px;">2. Verified Seller Documentation</h3>
<div class="form-group">
<label>Verified Phone Number</label>
<input type="text" name="phone" class="form-control" required placeholder="+93 7xx xxx xxx" value="<?= htmlspecialchars($user_info['phone'] ?? '') ?>">
</div>
<div class="form-group">
<label>Detailed Residential Address / Location</label>
<textarea name="address" class="form-control" rows="2" required placeholder="Enter your full residential address for identity verification and inspection arrangements..."><?= htmlspecialchars($user_info['address'] ?? '') ?></textarea>
</div>
<div class="mt-3 flex gap-1 align-center">
<button type="submit" class="btn btn-primary btn-lg" style="flex: 2; font-weight: 900; letter-spacing: 1px;">SUBMIT VEHICLE FOR APPROVAL</button>
<a href="dashboard.php" class="btn btn-outline btn-lg" style="flex: 1; font-weight: 700;">CANCEL</a>
</div>
</form>
</div>
</div>
<script>
document.getElementById('car_image').onchange = function() {
if (this.files && this.files[0]) {
const fileName = document.getElementById('file-name');
fileName.textContent = '✅ Selected File: ' + this.files[0].name;
fileName.style.display = 'block';
}
};
</script>
<?php require_once __DIR__ . '/includes/footer.php'; ?>

View File

@ -1,149 +0,0 @@
<?php
session_start();
require_once __DIR__ . '/db/config.php';
if (!isset($_SESSION['user_id']) || ($_SESSION['role'] ?? '') !== 'admin') {
header('Location: login.php');
exit;
}
$pdo = db();
$message = '';
if (isset($_POST['action']) && isset($_POST['car_id'])) {
$car_id = $_POST['car_id'];
$action = $_POST['action'];
$status = ($action === 'approve') ? 'approved' : 'rejected';
$stmt = $pdo->prepare("UPDATE cars SET status = ? WHERE id = ?");
if ($stmt->execute([$status, $car_id])) {
$message = "Car listing " . ($status === 'approved' ? 'approved' : 'rejected') . " successfully.";
}
}
if (isset($_GET['delete'])) {
$id = $_GET['delete'];
$stmt = $pdo->prepare("UPDATE cars SET deleted_at = NOW() WHERE id = ?");
if ($stmt->execute([$id])) {
$message = "Car deleted successfully.";
}
}
// Fetch all cars with user and image info
$stmt = $pdo->query("
SELECT c.*, u.name as seller_name, u.phone as seller_phone, ci.image_path
FROM cars c
JOIN users u ON c.user_id = u.id
LEFT JOIN car_images ci ON c.id = ci.car_id AND ci.is_main = 1
WHERE c.deleted_at IS NULL
ORDER BY c.created_at DESC
");
$cars = $stmt->fetchAll();
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Manage Inventory | Admin</title>
<link rel="stylesheet" href="assets/css/fonts.css">
<link rel="stylesheet" href="assets/css/style.css?v=<?= time() ?>">
</head>
<body>
<div class="dashboard-container">
<!-- Sidebar -->
<aside class="sidebar">
<a href="index.php" class="sidebar-brand">AFGCARS</a>
<ul class="sidebar-menu">
<li><a href="admin_dashboard.php"><span>Dashboard</span></a></li>
<li><a href="admin_cars.php" class="active"><span>Manage Cars</span></a></li>
<li><a href="admin_purchases.php"><span>Purchase Requests</span></a></li>
<li><a href="admin_users.php"><span>Users</span></a></li>
<li><a href="admin_messages.php"><span>Messages</span></a></li>
</ul>
<div class="sidebar-footer">
<a href="logout.php" class="btn btn-danger btn-sm" style="width: 100%;">Logout</a>
</div>
</aside>
<!-- Main Content -->
<main class="main-content">
<header class="mb-3" style="display: flex; justify-content: space-between; align-items: center;">
<div>
<h1 class="fw-bold" style="font-size: 2.5rem;">Inventory Management</h1>
<p class="text-secondary">Review, approve, and manage all vehicle listings across the platform.</p>
</div>
<div class="nav-actions">
<a href="admin_purchases.php" class="btn btn-primary">Purchase Requests</a>
</div>
</header>
<?php if ($message): ?>
<div class="alert alert-success">
<span class="text-gold"></span> <?= $message ?>
</div>
<?php endif; ?>
<div class="glass" style="padding: 2.5rem;">
<div class="table-container">
<table>
<thead>
<tr>
<th>Vehicle Details</th>
<th>Seller Info</th>
<th>Price & City</th>
<th>Status</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<?php foreach ($cars as $car): ?>
<tr>
<td>
<div style="display: flex; align-items: center; gap: 1.2rem;">
<img src="<?= htmlspecialchars($car['image_path'] ?: 'assets/images/placeholder-car.jpg') ?>" style="width: 110px; height: 70px; object-fit: cover; border-radius: 12px; border: 1px solid var(--glass-border);">
<div>
<div class="fw-bold"><?= htmlspecialchars($car['brand'] . ' ' . $car['model']) ?></div>
<div class="text-sm text-secondary"><?= $car['year'] ?></div>
</div>
</div>
</td>
<td>
<div class="fw-bold text-sm"><?= htmlspecialchars($car['seller_name']) ?></div>
<div class="text-sm text-secondary"><?= htmlspecialchars($car['seller_phone']) ?></div>
</td>
<td>
<div class="text-gold fw-bold">$<?= number_format($car['price']) ?></div>
<div class="text-sm text-secondary"><?= htmlspecialchars($car['city']) ?></div>
</td>
<td>
<span class="badge badge-<?= $car['status'] === 'approved' ? 'success' : ($car['status'] === 'sold' ? 'info' : ($car['status'] === 'rejected' ? 'danger' : 'warning')) ?>">
<?= ucfirst($car['status']) ?>
</span>
</td>
<td>
<div style="display: flex; gap: 1rem; align-items: center;">
<?php if ($car['status'] === 'pending'): ?>
<form method="POST" style="display: inline;">
<input type="hidden" name="car_id" value="<?= $car['id'] ?>">
<button type="submit" name="action" value="approve" class="text-gold text-sm fw-bold btn-sm" style="background: none; border: none; cursor: pointer; padding: 0;">Approve</button>
</form>
<form method="POST" style="display: inline;">
<input type="hidden" name="car_id" value="<?= $car['id'] ?>">
<button type="submit" name="action" value="reject" class="text-sm fw-bold btn-sm" style="background: none; border: none; cursor: pointer; padding: 0; color: var(--danger);">Reject</button>
</form>
<?php endif; ?>
<a href="edit_car.php?id=<?= $car['id'] ?>" class="text-sm fw-bold text-secondary" style="text-decoration: none;">Edit</a>
<a href="?delete=<?= $car['id'] ?>" class="text-sm fw-bold" style="color: var(--danger); text-decoration: none;" onclick="return confirm('Delete this vehicle?')">Delete</a>
</div>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
</div>
</main>
</div>
</body>
</html>

View File

@ -1,153 +0,0 @@
<?php
session_start();
require_once __DIR__ . '/db/config.php';
// Check if user is admin
if (!isset($_SESSION['user_id']) || ($_SESSION['role'] ?? '') !== 'admin') {
header('Location: login.php');
exit;
}
$pdo = db();
// Fetch Stats
$totalCars = $pdo->query("SELECT COUNT(*) FROM cars WHERE deleted_at IS NULL")->fetchColumn();
$pendingCars = $pdo->query("SELECT COUNT(*) FROM cars WHERE status = 'pending' AND deleted_at IS NULL")->fetchColumn();
$totalUsers = $pdo->query("SELECT COUNT(*) FROM users WHERE deleted_at IS NULL")->fetchColumn();
$totalPurchases = $pdo->query("SELECT COUNT(*) FROM purchases WHERE status = 'pending'")->fetchColumn();
// Fetch Recent Cars
$recentCars = $pdo->query("
SELECT c.*, u.name as owner_name
FROM cars c
JOIN users u ON c.user_id = u.id
WHERE c.deleted_at IS NULL
ORDER BY c.created_at DESC
LIMIT 5
")->fetchAll();
// Fetch Recent Messages
$recentMessages = $pdo->query("SELECT * FROM contact_messages ORDER BY created_at DESC LIMIT 5")->fetchAll();
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Admin Dashboard | AfgCars</title>
<link rel="stylesheet" href="assets/css/fonts.css">
<link rel="stylesheet" href="assets/css/style.css?v=<?= time() ?>">
</head>
<body>
<div class="dashboard-container">
<!-- Sidebar -->
<aside class="sidebar">
<a href="index.php" class="sidebar-brand">AFGCARS</a>
<ul class="sidebar-menu">
<li><a href="admin_dashboard.php" class="active"><span>Dashboard</span></a></li>
<li><a href="admin_cars.php"><span>Manage Cars</span></a></li>
<li><a href="admin_purchases.php"><span>Purchase Requests</span></a></li>
<li><a href="admin_users.php"><span>Users</span></a></li>
<li><a href="admin_messages.php"><span>Messages</span></a></li>
</ul>
<div class="sidebar-footer">
<a href="logout.php" class="btn btn-danger btn-sm" style="width: 100%;">Logout</a>
</div>
</aside>
<!-- Main Content -->
<main class="main-content">
<header class="mb-3" style="display: flex; justify-content: space-between; align-items: center;">
<div>
<h1 class="fw-bold" style="font-size: 2.5rem;">Dashboard Overview</h1>
<p class="text-secondary">Welcome back, <?= htmlspecialchars($_SESSION['user_name']) ?></p>
</div>
<div class="nav-actions">
<a href="index.php" class="btn btn-outline">View Site</a>
</div>
</header>
<!-- Stats Grid -->
<div class="stats-grid">
<div class="stat-card glass">
<span class="stat-label">Total Listings</span>
<span class="stat-value"><?= $totalCars ?></span>
</div>
<div class="stat-card glass" style="border-left: 4px solid var(--warning);">
<span class="stat-label">Listing Requests</span>
<span class="stat-value"><?= $pendingCars ?></span>
</div>
<div class="stat-card glass">
<span class="stat-label">Total Users</span>
<span class="stat-value"><?= $totalUsers ?></span>
</div>
<div class="stat-card glass" style="border-left: 4px solid var(--success); cursor: pointer;" onclick="window.location.href='admin_purchases.php'">
<span class="stat-label">Pending Purchases</span>
<span class="stat-value"><?= $totalPurchases ?></span>
</div>
</div>
<div class="grid grid-2">
<!-- Recent Listings -->
<div class="glass" style="padding: 2.5rem; grid-column: span 1;">
<div class="mb-2" style="display: flex; justify-content: space-between; align-items: center;">
<h3 class="fw-bold">Recent Car Listings</h3>
<a href="admin_cars.php" class="text-gold text-sm fw-bold" style="text-decoration: none;">View All</a>
</div>
<div class="table-container">
<table>
<thead>
<tr>
<th>Car</th>
<th>Owner</th>
<th>Price</th>
<th>Action</th>
</tr>
</thead>
<tbody>
<?php foreach ($recentCars as $car): ?>
<tr>
<td>
<div class="fw-bold"><?= htmlspecialchars($car['brand'] . ' ' . $car['model']) ?></div>
<div class="text-sm"><?= $car['year'] ?></div>
</td>
<td><?= htmlspecialchars($car['owner_name']) ?></td>
<td class="text-gold fw-bold">$<?= number_format($car['price']) ?></td>
<td><a href="car_detail.php?id=<?= $car['id'] ?>" class="btn-auth text-sm" style="padding: 0.4rem 0.8rem;">View</a></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
</div>
<!-- Recent Messages -->
<div class="glass" style="padding: 2.5rem;">
<div class="mb-2" style="display: flex; justify-content: space-between; align-items: center;">
<h3 class="fw-bold">Recent Messages</h3>
<a href="admin_messages.php" class="text-gold text-sm fw-bold" style="text-decoration: none;">All Messages</a>
</div>
<?php if (empty($recentMessages)): ?>
<p class="text-secondary text-sm">No new messages.</p>
<?php else: ?>
<div style="display: flex; flex-direction: column; gap: 1.5rem;">
<?php foreach ($recentMessages as $msg): ?>
<div style="border-bottom: 1px solid rgba(255,255,255,0.05); padding-bottom: 1rem;">
<div style="display: flex; justify-content: space-between; margin-bottom: 0.3rem;">
<span class="fw-bold text-sm"><?= htmlspecialchars($msg['name']) ?></span>
<span class="text-sm text-secondary"><?= date('M d', strtotime($msg['created_at'])) ?></span>
</div>
<p class="text-sm text-secondary" style="line-height: 1.4;">
<?= htmlspecialchars(substr($msg['message'] ?? '', 0, 80)) ?>...
</p>
</div>
<?php endforeach; ?>
</div>
<?php endif; ?>
</div>
</div>
</main>
</div>
</body>
</html>

View File

@ -1,93 +0,0 @@
<?php
session_start();
require_once __DIR__ . '/db/config.php';
if (!isset($_SESSION['user_id']) || ($_SESSION['role'] ?? '') !== 'admin') {
header('Location: login.php');
exit;
}
$pdo = db();
if (isset($_GET['action']) && isset($_GET['id'])) {
$id = $_GET['id'];
if ($_GET['action'] === 'read') {
$pdo->prepare("UPDATE contact_messages SET status = 'read' WHERE id = ?")->execute([$id]);
} elseif ($_GET['action'] === 'delete') {
$pdo->prepare("DELETE FROM contact_messages WHERE id = ?")->execute([$id]);
}
header('Location: admin_messages.php');
exit;
}
$messages = $pdo->query("SELECT * FROM contact_messages ORDER BY created_at DESC")->fetchAll();
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Manage Messages | Admin</title>
<link rel="stylesheet" href="assets/css/fonts.css">
<link rel="stylesheet" href="assets/css/style.css?v=<?= time() ?>">
</head>
<body>
<div class="dashboard-container">
<!-- Sidebar -->
<aside class="sidebar">
<a href="index.php" class="sidebar-brand">AFGCARS</a>
<ul class="sidebar-menu">
<li><a href="admin_dashboard.php"><span>Dashboard</span></a></li>
<li><a href="admin_cars.php"><span>Manage Cars</span></a></li>
<li><a href="admin_purchases.php"><span>Purchase Requests</span></a></li>
<li><a href="admin_users.php"><span>Users</span></a></li>
<li><a href="admin_messages.php" class="active"><span>Messages</span></a></li>
</ul>
<div class="sidebar-footer">
<a href="logout.php" class="btn btn-danger btn-sm" style="width: 100%;">Logout</a>
</div>
</aside>
<!-- Main Content -->
<main class="main-content">
<header class="mb-3">
<h1 class="fw-bold" style="font-size: 2.5rem;">Customer Inquiries</h1>
<p class="text-secondary">Review and respond to messages from marketplace users and visitors.</p>
</header>
<div class="grid" style="grid-template-columns: 1fr; gap: 2rem;">
<?php if (empty($messages)): ?>
<div class="glass" style="padding: 4rem; text-align: center;">
<p class="text-secondary">No messages found.</p>
</div>
<?php else: ?>
<?php foreach ($messages as $msg): ?>
<div class="glass" style="padding: 2.5rem; border-left: 5px solid <?= $msg['status'] === 'unread' ? 'var(--primary-color)' : 'transparent' ?>;">
<div style="display: flex; justify-content: space-between; align-items: flex-start; margin-bottom: 2rem;">
<div>
<h3 class="fw-bold mb-1" style="font-size: 1.4rem;"><?= htmlspecialchars($msg['subject']) ?></h3>
<p class="text-sm">From: <strong class="text-gold"><?= htmlspecialchars($msg['name']) ?></strong> <span class="text-secondary">(<?= htmlspecialchars($msg['email']) ?>)</span></p>
</div>
<div style="text-align: right;">
<div class="text-sm text-secondary mb-1" style="font-weight: 600;"><?= date('M d, Y H:i', strtotime($msg['created_at'])) ?></div>
<span class="badge badge-<?= $msg['status'] === 'unread' ? 'warning' : 'success' ?>"><?= ucfirst($msg['status']) ?></span>
</div>
</div>
<div class="mb-2" style="background: rgba(255,255,255,0.03); padding: 2rem; border-radius: 16px; line-height: 1.8; color: var(--text-secondary); font-size: 0.95rem;">
<?= nl2br(htmlspecialchars($msg['message'])) ?>
</div>
<div style="display: flex; gap: 1.2rem;">
<?php if ($msg['status'] === 'unread'): ?>
<a href="admin_messages.php?action=read&id=<?= $msg['id'] ?>" class="btn btn-primary btn-sm" style="padding: 0.8rem 1.5rem;">Mark as Read</a>
<?php endif; ?>
<a href="mailto:<?= $msg['email'] ?>" class="btn btn-outline btn-sm" style="padding: 0.8rem 1.5rem; border-color: var(--primary-color); color: var(--primary-color);">Reply via Email</a>
<a href="admin_messages.php?action=delete&id=<?= $msg['id'] ?>" onclick="return confirm('Delete this message?')" class="btn btn-outline btn-sm" style="padding: 0.8rem 1.5rem; border-color: var(--danger); color: var(--danger);">Delete Inquiry</a>
</div>
</div>
<?php endforeach; ?>
<?php endif; ?>
</div>
</main>
</div>
</body>
</html>

View File

@ -1,182 +0,0 @@
<?php
session_start();
require_once __DIR__ . '/db/config.php';
use App\Repositories\PurchaseRepository;
use App\Repositories\CarRepository;
if (!isset($_SESSION['user_id']) || ($_SESSION['role'] ?? '') !== 'admin') {
header('Location: login.php');
exit;
}
$pdo = db();
$message = '';
$purchaseRepo = new PurchaseRepository();
$carRepo = new CarRepository();
if (isset($_POST['action']) && isset($_POST['purchase_id'])) {
$purchase_id = $_POST['purchase_id'];
$action = $_POST['action'];
try {
$pdo->beginTransaction();
if ($action === 'approve') {
// Admin verifies -> move to held_in_escrow
$stmt = $pdo->prepare("UPDATE purchases SET status = 'paid', escrow_status = 'held_in_escrow' WHERE id = ?");
$stmt->execute([$purchase_id]);
// Get car ID and mark as sold
$stmt = $pdo->prepare("SELECT car_id FROM purchases WHERE id = ?");
$stmt->execute([$purchase_id]);
$car_id = $stmt->fetchColumn();
$carRepo->markAsSold($car_id);
$message = "Transaction verified. Funds are now held in Escrow.";
} elseif ($action === 'release') {
// Admin releases payment to seller
$stmt = $pdo->prepare("UPDATE purchases SET status = 'completed', escrow_status = 'released' WHERE id = ?");
$stmt->execute([$purchase_id]);
$message = "Payment released to seller. Transaction completed.";
} elseif ($action === 'reject') {
$stmt = $pdo->prepare("UPDATE purchases SET status = 'failed', escrow_status = 'cancelled' WHERE id = ?");
$stmt->execute([$purchase_id]);
$message = "Transaction rejected and cancelled.";
}
$pdo->commit();
} catch (Exception $e) {
$pdo->rollBack();
$message = "Error: " . $e->getMessage();
}
}
// Fetch all purchases with car and user info
$stmt = $pdo->query("
SELECT p.*, c.brand, c.model, c.year, u.name as buyer_user_name, ci.image_path
FROM purchases p
JOIN cars c ON p.car_id = c.id
JOIN users u ON p.user_id = u.id
LEFT JOIN car_images ci ON c.id = ci.car_id AND ci.is_main = 1
ORDER BY p.created_at DESC
");
$purchases = $stmt->fetchAll();
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Enterprise Transactions | Admin</title>
<link rel="stylesheet" href="assets/css/fonts.css">
<link rel="stylesheet" href="assets/css/style.css?v=<?= time() ?>">
</head>
<body>
<div class="dashboard-container">
<!-- Sidebar -->
<aside class="sidebar">
<a href="index.php" class="sidebar-brand">AFGCARS ENT</a>
<ul class="sidebar-menu">
<li><a href="admin_dashboard.php"><span>Dashboard</span></a></li>
<li><a href="admin_cars.php"><span>Manage Cars</span></a></li>
<li><a href="admin_purchases.php" class="active"><span>Transactions</span></a></li>
<li><a href="admin_users.php"><span>Users</span></a></li>
<li><a href="admin_messages.php"><span>Messages</span></a></li>
</ul>
<div class="sidebar-footer">
<a href="logout.php" class="btn btn-danger btn-sm" style="width: 100%;">Logout</a>
</div>
</aside>
<!-- Main Content -->
<main class="main-content">
<header class="mb-3">
<span class="badge badge-primary mb-1">ENTERPRISE MODE</span>
<h1 class="fw-bold" style="font-size: 2.5rem;">Transaction Engine</h1>
<p class="text-secondary">Manage Escrow, verify SHA256 tokens, and release payments for secure car marketplace sales.</p>
</header>
<?php if ($message): ?>
<div class="alert alert-success">
<span class="text-gold"></span> <?= $message ?>
</div>
<?php endif; ?>
<div class="glass" style="padding: 2.5rem;">
<div class="table-container">
<table>
<thead>
<tr>
<th>Transaction Ref</th>
<th>Vehicle</th>
<th>Escrow Status</th>
<th>Cost Breakdown</th>
<th>Verification</th>
<th>Action</th>
</tr>
</thead>
<tbody>
<?php foreach ($purchases as $p): ?>
<tr>
<td>
<div class="fw-bold"><?= htmlspecialchars($p['reference_number'] ?: 'LEGACY-'.$p['id']) ?></div>
<div class="text-sm text-secondary" style="font-family: monospace; font-size: 0.7rem;"><?= htmlspecialchars($p['transaction_id'] ?: 'N/A') ?></div>
<div class="text-sm text-secondary"><?= date('M d, H:i', strtotime($p['created_at'])) ?></div>
</td>
<td>
<div style="display: flex; align-items: center; gap: 1.2rem;">
<img src="<?= htmlspecialchars($p['image_path'] ?: 'assets/images/placeholder-car.jpg') ?>" style="width: 70px; height: 50px; object-fit: cover; border-radius: 8px;">
<div>
<div class="fw-bold text-sm"><?= htmlspecialchars($p['brand']) ?></div>
<div class="text-sm text-secondary"><?= $p['year'] ?></div>
</div>
</div>
</td>
<td>
<div class="badge badge-<?= $p['escrow_status'] === 'released' ? 'success' : ($p['escrow_status'] === 'cancelled' ? 'danger' : 'warning') ?>" style="display: block; text-align: center; margin-bottom: 0.3rem;">
<?= strtoupper(str_replace('_', ' ', $p['escrow_status'] ?: 'awaiting_verification')) ?>
</div>
<span class="text-sm text-secondary">Status: <?= ucfirst($p['status']) ?></span>
</td>
<td>
<div class="text-sm">Base: <span class="text-white">$<?= number_format($p['base_price'], 0) ?></span></div>
<div class="text-sm">Fee: <span class="text-gold">$<?= number_format($p['marketplace_fee'], 0) ?></span></div>
<div class="text-gold fw-bold" style="font-size: 1.1rem; border-top: 1px solid rgba(255,255,255,0.1); margin-top: 0.3rem; padding-top: 0.3rem;">Total: $<?= number_format($p['total_amount'] ?: $p['base_price'], 0) ?></div>
</td>
<td>
<div class="text-sm fw-bold"><?= htmlspecialchars($p['buyer_name']) ?></div>
<div class="text-sm text-secondary">Bank ID: <span class="text-white"><?= htmlspecialchars($p['bank_id'] ?: 'N/A') ?></span></div>
<div class="text-sm text-secondary" title="<?= htmlspecialchars($p['verification_token']) ?>">Token: <span style="font-family: monospace; font-size: 0.6rem;"><?= substr($p['verification_token'], 0, 12) ?>...</span></div>
</td>
<td>
<?php if ($p['escrow_status'] === 'awaiting_verification' || !$p['escrow_status']): ?>
<div style="display: flex; gap: 0.8rem; flex-direction: column;">
<form method="POST">
<input type="hidden" name="purchase_id" value="<?= $p['id'] ?>">
<button type="submit" name="action" value="approve" class="btn btn-primary btn-sm" style="width: 100%;">Verify & Hold</button>
</form>
<form method="POST">
<input type="hidden" name="purchase_id" value="<?= $p['id'] ?>">
<button type="submit" name="action" value="reject" class="text-sm fw-bold" style="background: none; border: none; cursor: pointer; color: var(--danger); width: 100%;">Reject</button>
</form>
</div>
<?php elseif ($p['escrow_status'] === 'held_in_escrow'): ?>
<form method="POST">
<input type="hidden" name="purchase_id" value="<?= $p['id'] ?>">
<button type="submit" name="action" value="release" class="btn btn-success btn-sm" style="width: 100%; background-color: #2ed573;">Release Funds</button>
</form>
<?php else: ?>
<span class="text-secondary text-sm fw-bold">COMPLETED</span>
<?php endif; ?>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
</div>
</main>
</div>
</body>
</html>

View File

@ -1,104 +0,0 @@
<?php
session_start();
require_once __DIR__ . '/db/config.php';
if (!isset($_SESSION['user_id']) || ($_SESSION['role'] ?? '') !== 'admin') {
header('Location: login.php');
exit;
}
$pdo = db();
if (isset($_GET['action']) && isset($_GET['id'])) {
$id = $_GET['id'];
if ($_GET['action'] === 'activate') {
$pdo->prepare("UPDATE users SET status = 'active' WHERE id = ?")->execute([$id]);
} elseif ($_GET['action'] === 'deactivate') {
$pdo->prepare("UPDATE users SET status = 'inactive' WHERE id = ?")->execute([$id]);
} elseif ($_GET['action'] === 'delete') {
$pdo->prepare("UPDATE users SET deleted_at = NOW() WHERE id = ?")->execute([$id]);
}
header('Location: admin_users.php');
exit;
}
$users = $pdo->query("SELECT * FROM users WHERE deleted_at IS NULL ORDER BY created_at DESC")->fetchAll();
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Manage Users | Admin</title>
<link rel="stylesheet" href="assets/css/fonts.css">
<link rel="stylesheet" href="assets/css/style.css?v=<?= time() ?>">
</head>
<body>
<div class="dashboard-container">
<!-- Sidebar -->
<aside class="sidebar">
<a href="index.php" class="sidebar-brand">AFGCARS</a>
<ul class="sidebar-menu">
<li><a href="admin_dashboard.php"><span>Dashboard</span></a></li>
<li><a href="admin_cars.php"><span>Manage Cars</span></a></li>
<li><a href="admin_purchases.php"><span>Purchase Requests</span></a></li>
<li><a href="admin_users.php" class="active"><span>Users</span></a></li>
<li><a href="admin_messages.php"><span>Messages</span></a></li>
</ul>
<div class="sidebar-footer">
<a href="logout.php" class="btn btn-danger btn-sm" style="width: 100%;">Logout</a>
</div>
</aside>
<!-- Main Content -->
<main class="main-content">
<header class="mb-3">
<h1 class="fw-bold" style="font-size: 2.5rem;">User Management</h1>
<p class="text-secondary">Manage access levels and monitor activity of marketplace users.</p>
</header>
<div class="glass" style="padding: 2.5rem;">
<div class="table-container">
<table>
<thead>
<tr>
<th>User Info</th>
<th>Phone/Address</th>
<th>Role</th>
<th>Status</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<?php foreach ($users as $u): ?>
<tr>
<td>
<div class="fw-bold"><?= htmlspecialchars($u['name']) ?></div>
<div class="text-sm"><?= htmlspecialchars($u['email']) ?></div>
</td>
<td>
<div class="fw-bold text-sm"><?= htmlspecialchars($u['phone'] ?: 'N/A') ?></div>
<div class="text-sm text-secondary" style="max-width: 250px; overflow: hidden; text-overflow: ellipsis;"><?= htmlspecialchars($u['address'] ?: 'N/A') ?></div>
</td>
<td><span class="badge badge-<?= $u['role'] === 'admin' ? 'danger' : 'success' ?>"><?= strtoupper($u['role']) ?></span></td>
<td><span class="badge badge-<?= $u['status'] === 'active' ? 'success' : 'warning' ?>"><?= ucfirst($u['status']) ?></span></td>
<td>
<div style="display: flex; gap: 1rem;">
<?php if ($u['status'] === 'active'): ?>
<a href="admin_users.php?action=deactivate&id=<?= $u['id'] ?>" class="text-gold text-sm fw-bold" style="text-decoration: none;">Deactivate</a>
<?php else: ?>
<a href="admin_users.php?action=activate&id=<?= $u['id'] ?>" class="text-gold text-sm fw-bold" style="text-decoration: none;">Activate</a>
<?php endif; ?>
<a href="admin_users.php?action=delete&id=<?= $u['id'] ?>" onclick="return confirm('Delete this user?')" class="text-sm fw-bold" style="color: var(--danger); text-decoration: none;">Delete</a>
</div>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
</div>
</main>
</div>
</body>
</html>

View File

@ -1,34 +0,0 @@
<?php
namespace App\Controllers;
use App\Services\PurchaseService;
use App\Repositories\CarRepository;
use Exception;
class PurchaseController {
protected $purchaseService;
protected $carRepo;
public function __construct() {
$this->purchaseService = new PurchaseService();
$this->carRepo = new CarRepository();
}
public function reserve($carId, $userId) {
try {
$this->purchaseService->reserveCar($carId, $userId);
return ['success' => true, 'message' => 'Car reserved successfully for 15 minutes.'];
} catch (Exception $e) {
return ['success' => false, 'message' => $e->getMessage()];
}
}
public function checkout($carId, $userId, $buyerData) {
try {
$transactionId = $this->purchaseService->initiatePurchase($carId, $userId, $buyerData);
return ['success' => true, 'transaction_id' => $transactionId];
} catch (Exception $e) {
return ['success' => false, 'message' => $e->getMessage()];
}
}
}

View File

@ -1,19 +0,0 @@
<?php
spl_autoload_register(function ($class) {
// Map namespace/class to directory structure
// e.g., App\Controllers\PurchaseController -> app/Controllers/PurchaseController.php
// Remove 'App\' prefix if present
if (strpos($class, 'App\\') === 0) {
$class = substr($class, 4);
}
$file = __DIR__ . '/../' . str_replace('\\', '/', $class) . '.php';
if (file_exists($file)) {
require_once $file;
return true;
}
return false;
});

View File

@ -1,22 +0,0 @@
<?php
namespace App\Repositories;
abstract class BaseRepository {
protected $db;
public function __construct() {
$this->db = db();
}
public function beginTransaction() {
return $this->db->beginTransaction();
}
public function commit() {
return $this->db->commit();
}
public function rollBack() {
return $this->db->rollBack();
}
}

View File

@ -1,44 +0,0 @@
<?php
namespace App\Repositories;
class CarRepository extends BaseRepository {
public function find($id, $lock = false) {
$sql = "SELECT * FROM cars WHERE id = :id";
if ($lock) {
$sql .= " FOR UPDATE";
}
$stmt = $this->db->prepare($sql);
$stmt->execute(['id' => $id]);
return $stmt->fetch();
}
public function reserve($carId, $userId, $minutes = 15) {
$expiresAt = date('Y-m-d H:i:s', strtotime("+$minutes minutes"));
$sql = "UPDATE cars SET
reserved_by = :user_id,
reserved_at = NOW(),
reservation_expires_at = :expires_at
WHERE id = :id";
$stmt = $this->db->prepare($sql);
return $stmt->execute([
'user_id' => $userId,
'expires_at' => $expiresAt,
'id' => $carId
]);
}
public function markAsSold($id) {
$stmt = $this->db->prepare("UPDATE cars SET status = 'sold' WHERE id = :id");
return $stmt->execute(['id' => $id]);
}
public function isAvailable($id) {
$sql = "SELECT * FROM cars WHERE id = :id
AND status = 'approved'
AND (reserved_by IS NULL OR reservation_expires_at < NOW())";
$stmt = $this->db->prepare($sql);
$stmt->execute(['id' => $id]);
return $stmt->fetch();
}
}

View File

@ -1,54 +0,0 @@
<?php
namespace App\Repositories;
class PurchaseRepository extends BaseRepository {
public function create($data) {
$sql = "INSERT INTO purchases (
transaction_id, reference_number, verification_token,
car_id, user_id, buyer_name, buyer_email, buyer_phone,
base_price, marketplace_fee, tax, total_amount,
status, escrow_status, payment_method, expires_at
) VALUES (
:transaction_id, :reference_number, :verification_token,
:car_id, :user_id, :buyer_name, :buyer_email, :buyer_phone,
:base_price, :marketplace_fee, :tax, :total_amount,
:status, :escrow_status, :payment_method, :expires_at
)";
$stmt = $this->db->prepare($sql);
$stmt->execute($data);
return $this->db->lastInsertId();
}
public function findByTransactionId($transactionId) {
$stmt = $this->db->prepare("SELECT * FROM purchases WHERE transaction_id = :id");
$stmt->execute(['id' => $transactionId]);
return $stmt->fetch();
}
public function updateStatus($id, $status, $escrowStatus = null) {
$sql = "UPDATE purchases SET status = :status";
$params = ['id' => $id, 'status' => $status];
if ($escrowStatus) {
$sql .= ", escrow_status = :escrow_status";
$params['escrow_status'] = $escrowStatus;
}
$sql .= " WHERE id = :id";
$stmt = $this->db->prepare($sql);
return $stmt->execute($params);
}
public function generateUniqueReference() {
$ref = 'REF-' . strtoupper(substr(md5(uniqid()), 0, 8));
// Check if exists
$stmt = $this->db->prepare("SELECT id FROM purchases WHERE reference_number = :ref");
$stmt->execute(['ref' => $ref]);
if ($stmt->fetch()) {
return $this->generateUniqueReference();
}
return $ref;
}
}

View File

@ -1,12 +0,0 @@
<?php
namespace App\Repositories;
class SettingRepository extends BaseRepository {
public function get($key, $default = null) {
$stmt = $this->db->prepare("SELECT value FROM settings WHERE `key` = :key");
$stmt->execute(['key' => $key]);
$row = $stmt->fetch();
return $row ? $row['value'] : $default;
}
}

View File

@ -1,29 +0,0 @@
<?php
namespace App\Services;
class PaymentService {
public function generateUUID() {
return sprintf('%04x%04x-%04x-%04x-%04x-%04x%04x%04x',
mt_rand(0, 0xffff), mt_rand(0, 0xffff),
mt_rand(0, 0xffff),
mt_rand(0, 0x0fff) | 0x4000,
mt_rand(0, 0x3fff) | 0x8000,
mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0xffff)
);
}
public function generateVerificationToken($transactionId, $amount) {
return hash('sha256', $transactionId . $amount . 'SECRET_SALT_2026');
}
public function processPayment($method, $amount) {
// Offline Simulation
// In a real scenario, this would call a gateway API
return [
'success' => true,
'transaction_id' => $this->generateUUID(),
'status' => 'paid'
];
}
}

View File

@ -1,98 +0,0 @@
<?php
namespace App\Services;
use App\Repositories\CarRepository;
use App\Repositories\PurchaseRepository;
use App\Repositories\SettingRepository;
use Exception;
class PurchaseService {
protected $carRepo;
protected $purchaseRepo;
protected $settingRepo;
protected $paymentService;
public function __construct() {
$this->carRepo = new CarRepository();
$this->purchaseRepo = new PurchaseRepository();
$this->settingRepo = new SettingRepository();
$this->paymentService = new PaymentService();
}
public function reserveCar($carId, $userId) {
$this->carRepo->beginTransaction();
try {
$car = $this->carRepo->find($carId, true); // Lock for update
if (!$car) throw new Exception("Car not found.");
if ($car['status'] !== 'approved') throw new Exception("Car is not available for sale.");
if ($car['user_id'] == $userId) throw new Exception("You cannot buy your own car.");
// Check if already reserved by someone else and not expired
if ($car['reserved_by'] && $car['reserved_by'] != $userId && strtotime($car['reservation_expires_at']) > time()) {
throw new Exception("This car is currently reserved by another buyer.");
}
$this->carRepo->reserve($carId, $userId);
$this->carRepo->commit();
return true;
} catch (Exception $e) {
$this->carRepo->rollBack();
throw $e;
}
}
public function calculateFees($price) {
$feePercent = $this->settingRepo->get('marketplace_fee_percentage', 5);
$taxPercent = $this->settingRepo->get('tax_percentage', 10);
$fee = ($price * $feePercent) / 100;
$tax = ($price * $taxPercent) / 100;
$total = $price + $fee + $tax;
return [
'base_price' => $price,
'fee' => $fee,
'tax' => $tax,
'total' => $total
];
}
public function initiatePurchase($carId, $userId, $buyerData) {
$this->purchaseRepo->beginTransaction();
try {
$car = $this->carRepo->find($carId, true);
if (!$car) throw new Exception("Car not found.");
$costs = $this->calculateFees($car['price']);
$transactionId = $this->paymentService->generateUUID();
$ref = $this->purchaseRepo->generateUniqueReference();
$token = $this->paymentService->generateVerificationToken($transactionId, $costs['total']);
$purchaseId = $this->purchaseRepo->create([
'transaction_id' => $transactionId,
'reference_number' => $ref,
'verification_token' => $token,
'car_id' => $carId,
'user_id' => $userId,
'buyer_name' => $buyerData['name'],
'buyer_email' => $buyerData['email'],
'buyer_phone' => $buyerData['phone'],
'base_price' => $costs['base_price'],
'marketplace_fee' => $costs['fee'],
'tax' => $costs['tax'],
'total_amount' => $costs['total'],
'status' => 'initiated',
'escrow_status' => 'awaiting_verification',
'payment_method' => $buyerData['payment_method'],
'expires_at' => date('Y-m-d H:i:s', strtotime("+1 hour"))
]);
$this->purchaseRepo->commit();
return $transactionId;
} catch (Exception $e) {
$this->purchaseRepo->rollBack();
throw $e;
}
}
}

View File

@ -1,378 +0,0 @@
/* cyrillic-ext */
@font-face {
font-family: 'Inter';
font-style: normal;
font-weight: 400;
font-display: swap;
src: url(../fonts/inter/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa2JL7SUc.woff2) format('woff2');
unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}
/* cyrillic */
@font-face {
font-family: 'Inter';
font-style: normal;
font-weight: 400;
font-display: swap;
src: url(../fonts/inter/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa0ZL7SUc.woff2) format('woff2');
unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
/* greek-ext */
@font-face {
font-family: 'Inter';
font-style: normal;
font-weight: 400;
font-display: swap;
src: url(../fonts/inter/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa2ZL7SUc.woff2) format('woff2');
unicode-range: U+1F00-1FFF;
}
/* greek */
@font-face {
font-family: 'Inter';
font-style: normal;
font-weight: 400;
font-display: swap;
src: url(../fonts/inter/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa1pL7SUc.woff2) format('woff2');
unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF;
}
/* vietnamese */
@font-face {
font-family: 'Inter';
font-style: normal;
font-weight: 400;
font-display: swap;
src: url(../fonts/inter/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa2pL7SUc.woff2) format('woff2');
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face {
font-family: 'Inter';
font-style: normal;
font-weight: 400;
font-display: swap;
src: url(../fonts/inter/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa25L7SUc.woff2) format('woff2');
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
font-family: 'Inter';
font-style: normal;
font-weight: 400;
font-display: swap;
src: url(../fonts/inter/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa1ZL7.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* cyrillic-ext */
@font-face {
font-family: 'Inter';
font-style: normal;
font-weight: 500;
font-display: swap;
src: url(../fonts/inter/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa2JL7SUc.woff2) format('woff2');
unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}
/* cyrillic */
@font-face {
font-family: 'Inter';
font-style: normal;
font-weight: 500;
font-display: swap;
src: url(../fonts/inter/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa0ZL7SUc.woff2) format('woff2');
unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
/* greek-ext */
@font-face {
font-family: 'Inter';
font-style: normal;
font-weight: 500;
font-display: swap;
src: url(../fonts/inter/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa2ZL7SUc.woff2) format('woff2');
unicode-range: U+1F00-1FFF;
}
/* greek */
@font-face {
font-family: 'Inter';
font-style: normal;
font-weight: 500;
font-display: swap;
src: url(../fonts/inter/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa1pL7SUc.woff2) format('woff2');
unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF;
}
/* vietnamese */
@font-face {
font-family: 'Inter';
font-style: normal;
font-weight: 500;
font-display: swap;
src: url(../fonts/inter/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa2pL7SUc.woff2) format('woff2');
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face {
font-family: 'Inter';
font-style: normal;
font-weight: 500;
font-display: swap;
src: url(../fonts/inter/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa25L7SUc.woff2) format('woff2');
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
font-family: 'Inter';
font-style: normal;
font-weight: 500;
font-display: swap;
src: url(../fonts/inter/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa1ZL7.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* cyrillic-ext */
@font-face {
font-family: 'Inter';
font-style: normal;
font-weight: 600;
font-display: swap;
src: url(../fonts/inter/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa2JL7SUc.woff2) format('woff2');
unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}
/* cyrillic */
@font-face {
font-family: 'Inter';
font-style: normal;
font-weight: 600;
font-display: swap;
src: url(../fonts/inter/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa0ZL7SUc.woff2) format('woff2');
unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
/* greek-ext */
@font-face {
font-family: 'Inter';
font-style: normal;
font-weight: 600;
font-display: swap;
src: url(../fonts/inter/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa2ZL7SUc.woff2) format('woff2');
unicode-range: U+1F00-1FFF;
}
/* greek */
@font-face {
font-family: 'Inter';
font-style: normal;
font-weight: 600;
font-display: swap;
src: url(../fonts/inter/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa1pL7SUc.woff2) format('woff2');
unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF;
}
/* vietnamese */
@font-face {
font-family: 'Inter';
font-style: normal;
font-weight: 600;
font-display: swap;
src: url(../fonts/inter/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa2pL7SUc.woff2) format('woff2');
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face {
font-family: 'Inter';
font-style: normal;
font-weight: 600;
font-display: swap;
src: url(../fonts/inter/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa25L7SUc.woff2) format('woff2');
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
font-family: 'Inter';
font-style: normal;
font-weight: 600;
font-display: swap;
src: url(../fonts/inter/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa1ZL7.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* cyrillic-ext */
@font-face {
font-family: 'Inter';
font-style: normal;
font-weight: 700;
font-display: swap;
src: url(../fonts/inter/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa2JL7SUc.woff2) format('woff2');
unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}
/* cyrillic */
@font-face {
font-family: 'Inter';
font-style: normal;
font-weight: 700;
font-display: swap;
src: url(../fonts/inter/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa0ZL7SUc.woff2) format('woff2');
unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
/* greek-ext */
@font-face {
font-family: 'Inter';
font-style: normal;
font-weight: 700;
font-display: swap;
src: url(../fonts/inter/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa2ZL7SUc.woff2) format('woff2');
unicode-range: U+1F00-1FFF;
}
/* greek */
@font-face {
font-family: 'Inter';
font-style: normal;
font-weight: 700;
font-display: swap;
src: url(../fonts/inter/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa1pL7SUc.woff2) format('woff2');
unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF;
}
/* vietnamese */
@font-face {
font-family: 'Inter';
font-style: normal;
font-weight: 700;
font-display: swap;
src: url(../fonts/inter/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa2pL7SUc.woff2) format('woff2');
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face {
font-family: 'Inter';
font-style: normal;
font-weight: 700;
font-display: swap;
src: url(../fonts/inter/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa25L7SUc.woff2) format('woff2');
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
font-family: 'Inter';
font-style: normal;
font-weight: 700;
font-display: swap;
src: url(../fonts/inter/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa1ZL7.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* cyrillic-ext */
@font-face {
font-family: 'Inter';
font-style: normal;
font-weight: 800;
font-display: swap;
src: url(../fonts/inter/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa2JL7SUc.woff2) format('woff2');
unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}
/* cyrillic */
@font-face {
font-family: 'Inter';
font-style: normal;
font-weight: 800;
font-display: swap;
src: url(../fonts/inter/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa0ZL7SUc.woff2) format('woff2');
unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
/* greek-ext */
@font-face {
font-family: 'Inter';
font-style: normal;
font-weight: 800;
font-display: swap;
src: url(../fonts/inter/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa2ZL7SUc.woff2) format('woff2');
unicode-range: U+1F00-1FFF;
}
/* greek */
@font-face {
font-family: 'Inter';
font-style: normal;
font-weight: 800;
font-display: swap;
src: url(../fonts/inter/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa1pL7SUc.woff2) format('woff2');
unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF;
}
/* vietnamese */
@font-face {
font-family: 'Inter';
font-style: normal;
font-weight: 800;
font-display: swap;
src: url(../fonts/inter/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa2pL7SUc.woff2) format('woff2');
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face {
font-family: 'Inter';
font-style: normal;
font-weight: 800;
font-display: swap;
src: url(../fonts/inter/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa25L7SUc.woff2) format('woff2');
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
font-family: 'Inter';
font-style: normal;
font-weight: 800;
font-display: swap;
src: url(../fonts/inter/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa1ZL7.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* cyrillic-ext */
@font-face {
font-family: 'Inter';
font-style: normal;
font-weight: 900;
font-display: swap;
src: url(../fonts/inter/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa2JL7SUc.woff2) format('woff2');
unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}
/* cyrillic */
@font-face {
font-family: 'Inter';
font-style: normal;
font-weight: 900;
font-display: swap;
src: url(../fonts/inter/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa0ZL7SUc.woff2) format('woff2');
unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
/* greek-ext */
@font-face {
font-family: 'Inter';
font-style: normal;
font-weight: 900;
font-display: swap;
src: url(../fonts/inter/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa2ZL7SUc.woff2) format('woff2');
unicode-range: U+1F00-1FFF;
}
/* greek */
@font-face {
font-family: 'Inter';
font-style: normal;
font-weight: 900;
font-display: swap;
src: url(../fonts/inter/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa1pL7SUc.woff2) format('woff2');
unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF;
}
/* vietnamese */
@font-face {
font-family: 'Inter';
font-style: normal;
font-weight: 900;
font-display: swap;
src: url(../fonts/inter/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa2pL7SUc.woff2) format('woff2');
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face {
font-family: 'Inter';
font-style: normal;
font-weight: 900;
font-display: swap;
src: url(../fonts/inter/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa25L7SUc.woff2) format('woff2');
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
font-family: 'Inter';
font-style: normal;
font-weight: 900;
font-display: swap;
src: url(../fonts/inter/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa1ZL7.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

View File

@ -1,642 +0,0 @@
:root {
--primary-color: #d4af37; /* Gold */
--secondary-color: #1e293b; /* Dark Slate Blue */
--bg-color: #0f172a; /* Deep Background */
--card-bg: #1e293b;
--glass-border: rgba(255, 255, 255, 0.1);
--text-primary: #f8fafc;
--text-secondary: #94a3b8;
--transition: all 0.4s cubic-bezier(0.16, 1, 0.3, 1);
--sidebar-width: 280px;
--danger: #ff4757;
--success: #2ed573;
--warning: #ffa502;
--info: #1e90ff;
--glass-bg: rgba(30, 41, 59, 0.7);
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Inter', system-ui, -apple-system, sans-serif;
background-color: var(--bg-color);
color: var(--text-primary);
line-height: 1.6;
overflow-x: hidden;
}
/* Glassmorphism utility */
.glass {
background: var(--glass-bg);
backdrop-filter: blur(15px);
-webkit-backdrop-filter: blur(15px);
border: 1px solid var(--glass-border);
border-radius: 20px;
box-shadow: 0 10px 30px -10px rgba(0, 0, 0, 0.3);
transition: var(--transition);
}
.glass:hover {
border-color: rgba(212, 175, 55, 0.5);
background: rgba(30, 41, 59, 0.9);
box-shadow: 0 15px 45px -10px rgba(0, 0, 0, 0.4);
}
/* Navbar */
nav {
display: flex;
justify-content: space-between;
align-items: center;
padding: 1.2rem 6%;
position: sticky;
top: 0;
z-index: 1000;
background: rgba(15, 23, 42, 0.9);
backdrop-filter: blur(20px);
border-bottom: 1px solid var(--glass-border);
}
.logo {
font-size: 1.6rem;
font-weight: 900;
color: var(--primary-color);
text-transform: uppercase;
letter-spacing: 3px;
text-decoration: none;
background: linear-gradient(45deg, var(--primary-color), #fff);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
.nav-links {
display: flex;
gap: 3rem;
list-style: none;
}
.nav-links a {
color: var(--text-primary);
text-decoration: none;
font-size: 0.9rem;
font-weight: 600;
transition: var(--transition);
text-transform: uppercase;
letter-spacing: 1px;
opacity: 0.8;
}
.nav-links a:hover {
color: var(--primary-color);
opacity: 1;
}
/* Container */
.container {
padding: 0 6%;
}
.container-fluid {
padding: 0 4%;
}
/* Dashboard Layout */
.dashboard-container {
display: flex;
min-height: 100vh;
background: #050505;
}
.main-content {
flex: 1;
margin-left: var(--sidebar-width);
padding: 3rem 4rem;
min-width: 0;
}
/* Sidebar (Admin) */
.sidebar {
width: var(--sidebar-width);
height: 100vh;
background: #0a0a0a;
border-right: 1px solid var(--glass-border);
position: fixed;
padding: 2.5rem 1.5rem;
display: flex;
flex-direction: column;
z-index: 100;
}
.sidebar-brand {
font-size: 1.5rem;
font-weight: 900;
color: var(--primary-color);
text-decoration: none;
letter-spacing: 4px;
margin-bottom: 3.5rem;
padding-left: 1rem;
display: block;
}
.sidebar-menu {
list-style: none;
flex: 1;
}
.sidebar-menu li {
margin-bottom: 0.5rem;
}
.sidebar-menu a {
display: flex;
align-items: center;
gap: 1rem;
padding: 1.2rem 1.5rem;
color: var(--text-secondary);
text-decoration: none;
font-weight: 600;
border-radius: 12px;
transition: var(--transition);
font-size: 0.95rem;
}
.sidebar-menu a:hover, .sidebar-menu a.active {
background: rgba(212, 175, 55, 0.1);
color: var(--primary-color);
}
.sidebar-footer {
padding-top: 2rem;
border-top: 1px solid var(--glass-border);
}
/* Hero Section */
.hero {
height: 85vh;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
text-align: center;
background: radial-gradient(circle at top right, rgba(212, 175, 55, 0.15), transparent),
radial-gradient(circle at bottom left, rgba(30, 41, 59, 0.5), transparent);
}
.hero h1 {
font-size: 5rem;
font-weight: 900;
line-height: 1.1;
margin-bottom: 2rem;
letter-spacing: -2px;
color: #ffffff;
}
.hero p {
font-size: 1.4rem;
color: var(--text-secondary);
max-width: 600px;
margin-bottom: 3rem;
}
/* Form Styles */
.form-group {
margin-bottom: 1.5rem;
}
label {
display: block;
margin-bottom: 0.5rem;
font-weight: 600;
color: var(--text-primary);
font-size: 0.9rem;
}
.form-control {
width: 100%;
padding: 1rem 1.2rem;
border-radius: 12px;
background: var(--card-bg);
border: 1px solid var(--glass-border);
color: var(--text-primary);
font-family: inherit;
transition: var(--transition);
}
.form-control:focus {
outline: none;
border-color: var(--primary-color);
box-shadow: 0 0 0 4px rgba(212, 175, 55, 0.2);
}
textarea.form-control {
resize: none;
}
/* Buttons */
.btn {
padding: 1rem 2rem;
border-radius: 12px;
font-weight: 700;
cursor: pointer;
text-decoration: none;
display: inline-flex;
align-items: center;
justify-content: center;
gap: 0.8rem;
transition: var(--transition);
border: none;
font-size: 0.95rem;
white-space: nowrap;
}
.btn-primary {
background: var(--primary-color);
color: #000;
box-shadow: 0 10px 20px -5px rgba(212, 175, 55, 0.4);
}
.btn-primary:hover {
transform: translateY(-3px);
box-shadow: 0 15px 30px -5px rgba(212, 175, 55, 0.6);
background: #e5be47;
}
.btn-outline {
background: transparent;
border: 2px solid var(--glass-border);
color: var(--text-primary);
}
.btn-outline:hover {
background: rgba(255, 255, 255, 0.05);
border-color: var(--text-primary);
}
.btn-sm {
padding: 0.6rem 1.2rem;
font-size: 0.85rem;
}
.btn-lg {
padding: 1.5rem 3rem;
font-size: 1.1rem;
}
.btn-danger {
background: rgba(255, 71, 87, 0.1);
color: var(--danger);
border: 1px solid var(--danger);
}
.btn-danger:hover {
background: var(--danger);
color: white;
}
.btn-auth {
padding: 0.8rem 1.5rem;
border-radius: 12px;
border: 2px solid var(--glass-border);
text-decoration: none;
color: var(--text-primary);
font-weight: 700;
font-size: 0.9rem;
transition: var(--transition);
display: inline-flex;
align-items: center;
gap: 0.5rem;
}
.btn-auth:hover {
border-color: var(--primary-color);
color: var(--primary-color);
}
/* Grid Layouts */
.grid {
display: grid;
gap: 2rem;
}
.grid-2 { grid-template-columns: repeat(2, 1fr); }
.grid-3 { grid-template-columns: repeat(3, 1fr); }
.grid-4 { grid-template-columns: repeat(4, 1fr); }
/* Stats Card */
.stats-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
gap: 1.5rem;
margin-bottom: 3rem;
}
.stat-card {
padding: 2.5rem 2rem;
display: flex;
flex-direction: column;
}
.stat-label {
font-size: 0.8rem;
color: var(--text-secondary);
text-transform: uppercase;
letter-spacing: 2px;
font-weight: 800;
margin-bottom: 1rem;
}
.stat-value {
font-size: 3rem;
font-weight: 900;
color: var(--primary-color);
line-height: 1;
}
/* Table Styling */
.table-container {
overflow-x: auto;
border-radius: 16px;
}
table {
width: 100%;
border-collapse: collapse;
text-align: left;
}
table thead tr {
background: rgba(255, 255, 255, 0.03) !important;
}
table th {
padding: 1.5rem;
color: var(--text-primary);
font-weight: 800;
font-size: 0.85rem;
text-transform: uppercase;
letter-spacing: 1px;
border-bottom: 1px solid var(--glass-border);
}
table td {
padding: 1.5rem;
color: var(--text-secondary);
border-bottom: 1px solid rgba(255, 255, 255, 0.05);
vertical-align: middle;
}
table tr:last-child td {
border-bottom: none;
}
/* Badge */
.badge {
padding: 0.4rem 1rem;
border-radius: 30px;
font-size: 0.75rem;
font-weight: 800;
text-transform: uppercase;
letter-spacing: 1px;
display: inline-block;
}
.badge-success { background: rgba(46, 213, 115, 0.15); color: #2ed573; border: 1px solid rgba(46, 213, 115, 0.3); }
.badge-warning { background: rgba(255, 165, 2, 0.15); color: #ffa502; border: 1px solid rgba(255, 165, 2, 0.3); }
.badge-danger { background: rgba(255, 71, 87, 0.15); color: #ff4757; border: 1px solid rgba(255, 71, 87, 0.3); }
.badge-info { background: rgba(30, 144, 255, 0.15); color: #1e90ff; border: 1px solid rgba(30, 144, 255, 0.3); }
.badge-primary { background: rgba(212, 175, 55, 0.15); color: var(--primary-color); border: 1px solid rgba(212, 175, 55, 0.3); }
/* Card Styling */
.card {
background: var(--card-bg);
border-radius: 24px;
overflow: hidden;
border: 1px solid var(--glass-border);
transition: var(--transition);
}
.card:hover {
transform: translateY(-10px);
box-shadow: 0 20px 40px -10px rgba(0, 0, 0, 0.5);
border-color: rgba(212, 175, 55, 0.3);
}
.card-img {
width: 100%;
height: 250px;
object-fit: cover;
}
.card-content {
padding: 2rem;
}
/* Page Header */
.page-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 4rem;
padding: 2rem 0;
}
.page-header h1 {
font-size: 3rem;
font-weight: 900;
color: #fff;
margin-bottom: 0.5rem;
}
.page-header p {
color: var(--text-secondary);
font-size: 1.1rem;
}
/* Section Title */
.section-title {
font-size: 2rem;
font-weight: 800;
margin-bottom: 2.5rem;
display: flex;
align-items: center;
gap: 1rem;
color: #fff;
}
.section-icon {
background: var(--primary-color);
color: #000;
width: 45px;
height: 45px;
display: flex;
align-items: center;
justify-content: center;
border-radius: 12px;
font-size: 1.3rem;
}
/* Sold Overlay */
.sold-overlay {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0,0,0,0.7);
display: flex;
align-items: center;
justify-content: center;
color: var(--primary-color);
font-weight: 900;
font-size: 2.5rem;
letter-spacing: 5px;
text-shadow: 0 5px 15px rgba(0,0,0,0.5);
z-index: 5;
}
.sold-stamp {
border: 10px double white;
color: white;
padding: 20px 50px;
font-weight: 900;
font-size: 5rem;
transform: rotate(-15deg);
letter-spacing: 10px;
text-shadow: 0 10px 30px rgba(0,0,0,0.5);
}
/* Price Tag */
.price-tag {
font-weight: 900;
color: var(--primary-color);
font-size: 1.5rem;
}
.price-tag-large {
font-size: 3.5rem;
font-weight: 900;
color: var(--primary-color);
line-height: 1;
}
/* Alerts */
.alert {
padding: 1.2rem 2rem;
border-radius: 16px;
margin-bottom: 2rem;
font-weight: 600;
display: flex;
align-items: center;
gap: 1rem;
}
.alert-error {
background: rgba(255, 71, 87, 0.15);
color: #ff6b81;
border: 1px solid rgba(255, 71, 87, 0.3);
}
.alert-success {
background: rgba(46, 213, 115, 0.15);
color: #7bed9f;
border: 1px solid rgba(46, 213, 115, 0.3);
}
/* Box component */
.box {
background: var(--card-bg);
border-radius: 32px;
border: 1px solid var(--glass-border);
padding: 4rem;
}
/* Utility */
.mb-1 { margin-bottom: 1rem; }
.mb-2 { margin-bottom: 2rem; }
.mb-3 { margin-bottom: 3rem; }
.mt-1 { margin-top: 1rem; }
.mt-2 { margin-top: 2rem; }
.mt-3 { margin-top: 3rem; }
.fw-bold { font-weight: 700; }
.fw-black { font-weight: 900; }
.text-gold { color: var(--primary-color); }
.text-sm { font-size: 0.85rem; }
.text-center { text-align: center; }
.flex { display: flex; }
.justify-between { justify-content: space-between; }
.align-center { align-items: center; }
.gap-1 { gap: 1rem; }
.w-full { width: 100%; }
/* Footer Styles */
footer {
background: var(--bg-color);
border-top: 1px solid var(--glass-border);
padding: 6rem 6% 3rem;
color: var(--text-primary);
}
.footer-grid {
display: grid;
grid-template-columns: 2fr 1fr 1fr 1.5fr;
gap: 4rem;
margin-bottom: 4rem;
}
.footer-col h4 {
font-size: 1.1rem;
font-weight: 800;
margin-bottom: 2rem;
text-transform: uppercase;
letter-spacing: 1px;
}
.footer-col ul {
list-style: none;
}
.footer-col ul li {
margin-bottom: 1.2rem;
}
.footer-col ul li a {
color: var(--text-secondary);
text-decoration: none;
transition: var(--transition);
font-size: 0.95rem;
}
.footer-col ul li a:hover {
color: var(--primary-color);
padding-left: 0.5rem;
}
.footer-bottom {
padding-top: 3rem;
border-top: 1px solid var(--glass-border);
text-align: center;
color: var(--text-secondary);
font-size: 0.9rem;
}
@media (max-width: 1200px) {
.main-content { padding: 3rem 2rem; }
}
@media (max-width: 1024px) {
.grid-4, .grid-3 { grid-template-columns: repeat(2, 1fr); }
.footer-grid { grid-template-columns: 1fr 1fr; }
.sidebar { width: 80px; padding: 2rem 0.5rem; }
.sidebar span, .sidebar-brand { display: none; }
.main-content { margin-left: 80px; }
}
@media (max-width: 768px) {
.grid-4, .grid-3, .grid-2 { grid-template-columns: 1fr; }
.hero h1 { font-size: 3rem; }
.footer-grid { grid-template-columns: 1fr; }
.page-header { flex-direction: column; text-align: center; gap: 2rem; }
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 126 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 73 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 53 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 81 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 81 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 76 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 76 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 81 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 88 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 91 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 63 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 86 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 114 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 295 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 404 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 127 KiB

View File

@ -1,13 +1,39 @@
document.addEventListener('DOMContentLoaded', function() { document.addEventListener('DOMContentLoaded', () => {
console.log('AfgCars Premium Marketplace Initialized'); const chatForm = document.getElementById('chat-form');
const chatInput = document.getElementById('chat-input');
const chatMessages = document.getElementById('chat-messages');
// Smooth scrolling for anchor links const appendMessage = (text, sender) => {
document.querySelectorAll('a[href^="#"]').forEach(anchor => { const msgDiv = document.createElement('div');
anchor.addEventListener('click', function (e) { msgDiv.classList.add('message', sender);
msgDiv.textContent = text;
chatMessages.appendChild(msgDiv);
chatMessages.scrollTop = chatMessages.scrollHeight;
};
chatForm.addEventListener('submit', async (e) => {
e.preventDefault(); e.preventDefault();
document.querySelector(this.getAttribute('href')).scrollIntoView({ const message = chatInput.value.trim();
behavior: 'smooth' if (!message) return;
});
appendMessage(message, 'visitor');
chatInput.value = '';
try {
const response = await fetch('api/chat.php', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ message })
}); });
const data = await response.json();
// Artificial delay for realism
setTimeout(() => {
appendMessage(data.reply, 'bot');
}, 500);
} catch (error) {
console.error('Error:', error);
appendMessage("Sorry, something went wrong. Please try again.", 'bot');
}
}); });
}); });

View File

@ -1,110 +0,0 @@
<?php
require_once __DIR__ . '/includes/header.php';
$pdo = db();
$id = $_GET['id'] ?? 0;
$stmt = $pdo->prepare("
SELECT c.*, u.name as seller_name, ci.image_path
FROM cars c
JOIN users u ON c.user_id = u.id
LEFT JOIN car_images ci ON c.id = ci.car_id AND ci.is_main = 1
WHERE c.id = ? AND c.deleted_at IS NULL AND (c.status = 'approved' OR c.status = 'sold')
");
$stmt->execute([$id]);
$car = $stmt->fetch();
if (!$car) {
header('Location: cars.php');
exit;
}
// Fetch all images
$stmt = $pdo->prepare("SELECT image_path FROM car_images WHERE car_id = ?");
$stmt->execute([$id]);
$images = $stmt->fetchAll(PDO::FETCH_COLUMN);
?>
<div class="container" style="padding: 4rem 0;">
<div class="grid" style="grid-template-columns: 1.5fr 1fr; gap: 4rem; align-items: start;">
<!-- Left Column: Images & Info -->
<div>
<div style="position: relative; margin-bottom: 2rem;">
<img src="<?= htmlspecialchars($car['image_path'] ?: 'assets/images/placeholder-car.jpg') ?>" class="w-full" style="border-radius: 24px; box-shadow: 0 20px 40px rgba(0,0,0,0.3);">
<?php if ($car['status'] === 'sold'): ?>
<div class="sold-overlay">
<div class="sold-stamp">SOLD</div>
</div>
<?php endif; ?>
</div>
<div class="grid grid-4 mb-3">
<?php foreach ($images as $img): ?>
<img src="<?= htmlspecialchars($img) ?>" class="w-full" style="height: 120px; object-fit: cover; border-radius: 16px; cursor: pointer; transition: transform 0.3s ease; border: 1px solid var(--glass-border);" onmouseover="this.style.transform='scale(1.05)'" onmouseout="this.style.transform='scale(1)'">
<?php endforeach; ?>
</div>
<div class="glass" style="padding: 3rem;">
<h2 class="section-title mb-2">Description</h2>
<div style="line-height: 2; color: var(--text-secondary); white-space: pre-line; font-size: 1.1rem;">
<?= htmlspecialchars($car['description']) ?>
</div>
</div>
</div>
<!-- Right Column: Details & Actions -->
<div style="position: sticky; top: 120px;">
<div class="glass" style="padding: 3.5rem; border-top: 5px solid var(--primary-color);">
<div class="mb-2">
<span class="badge badge-primary"><?= htmlspecialchars($car['city']) ?></span>
</div>
<h1 class="fw-black mb-1" style="font-size: 3rem; line-height: 1.1; color: #fff;">
<?= htmlspecialchars($car['brand'] . ' ' . $car['model']) ?>
</h1>
<p class="text-secondary mb-3" style="font-size: 1.2rem; font-weight: 600;">
Year: <span class="text-gold"><?= $car['year'] ?></span> | Status: <span class="text-gold"><?= ucfirst($car['status']) ?></span>
</p>
<div style="background: rgba(0,0,0,0.2); padding: 2.5rem; border-radius: 24px; margin-bottom: 3rem; border: 1px solid var(--glass-border);">
<p class="text-secondary mb-1 text-sm fw-black" style="text-transform: uppercase; letter-spacing: 2px;">Current Marketplace Price</p>
<div class="price-tag-large">$<?= number_format($car['price']) ?></div>
</div>
<?php if ($car['status'] === 'sold'): ?>
<div class="box text-center" style="padding: 2.5rem; background: rgba(0,0,0,0.1); border-color: var(--glass-border);">
<p class="text-secondary fw-bold" style="font-size: 1.1rem;">This vehicle has been successfully sold.</p>
</div>
<?php else: ?>
<a href="purchase.php?id=<?= $car['id'] ?>" class="btn btn-primary btn-lg w-full mb-2 fw-black">Initiate Purchase Request</a>
<?php endif; ?>
<div class="mt-3 pt-3" style="border-top: 1px solid var(--glass-border);">
<div class="flex align-center gap-1">
<div style="width: 55px; height: 55px; background: var(--primary-color); color: #000; border-radius: 16px; display: flex; align-items: center; justify-content: center; font-weight: 900; font-size: 1.4rem;">
<?= strtoupper(substr($car['seller_name'], 0, 1)) ?>
</div>
<div>
<p class="text-secondary text-sm fw-black" style="text-transform: uppercase; letter-spacing: 1px; margin-bottom: 0.2rem;">Verified Seller</p>
<p class="fw-black" style="font-size: 1.1rem; color: #fff;"><?= htmlspecialchars($car['seller_name']) ?></p>
</div>
</div>
</div>
</div>
<div class="glass mt-2" style="padding: 2rem; background: rgba(46, 213, 115, 0.05); border-color: rgba(46, 213, 115, 0.2);">
<h4 style="color: #2ed573; margin-bottom: 1rem; display: flex; align-items: center; gap: 0.8rem; font-weight: 800;">
<span style="font-size: 1.5rem;">🛡️</span> AfgCars Secure Payment
</h4>
<p class="text-secondary text-sm" style="line-height: 1.8;">
Every transaction is protected. We verify bank references and legal documentation before finalizing any sale in Afghanistan.
</p>
</div>
</div>
</div>
</div>
<?php require_once __DIR__ . '/includes/footer.php'; ?>

116
cars.php
View File

@ -1,116 +0,0 @@
<?php
require_once __DIR__ . '/includes/header.php';
$pdo = db();
$search = $_GET['search'] ?? '';
$city = $_GET['city'] ?? '';
$brand = $_GET['brand'] ?? '';
$query = "SELECT c.*, ci.image_path FROM cars c LEFT JOIN car_images ci ON c.id = ci.car_id AND ci.is_main = 1 WHERE c.deleted_at IS NULL AND (c.status = 'approved' OR c.status = 'sold')";
$params = [];
if ($search) {
$query .= " AND (brand LIKE ? OR model LIKE ?)";
$params[] = "%$search%";
$params[] = "%$search%";
}
if ($city) {
$query .= " AND city = ?";
$params[] = $city;
}
if ($brand) {
$query .= " AND brand = ?";
$params[] = $brand;
}
$query .= " ORDER BY c.created_at DESC";
$stmt = $pdo->prepare($query);
$stmt->execute($params);
$cars = $stmt->fetchAll();
// Fetch distinct cities and brands for filters
$cities = $pdo->query("SELECT DISTINCT city FROM cars WHERE status = 'approved'")->fetchAll(PDO::FETCH_COLUMN);
$brands = $pdo->query("SELECT DISTINCT brand FROM cars WHERE status = 'approved'")->fetchAll(PDO::FETCH_COLUMN);
?>
<div class="container" style="padding: 6rem 0;">
<div class="page-header" style="margin-bottom: 5rem;">
<div>
<h1 class="fw-black" style="font-size: 4rem; color: #fff; line-height: 1;">Premium Inventory</h1>
<p class="text-secondary fw-bold" style="font-size: 1.25rem;">Explore our curated selection of verified elite vehicles across Afghanistan.</p>
</div>
</div>
<!-- Filters -->
<div class="glass mb-4" style="padding: 3.5rem; border-top: 5px solid var(--primary-color);">
<form method="GET" class="grid" style="grid-template-columns: 2fr 1fr 1fr 1fr; gap: 2rem; align-items: end;">
<div class="form-group mb-0">
<label class="text-secondary fw-black mb-1" style="text-transform: uppercase; letter-spacing: 2px; font-size: 0.75rem;">Vehicle Search</label>
<input type="text" name="search" class="form-control" placeholder="Search brand or model..." value="<?= htmlspecialchars($search) ?>">
</div>
<div class="form-group mb-0">
<label class="text-secondary fw-black mb-1" style="text-transform: uppercase; letter-spacing: 2px; font-size: 0.75rem;">Location</label>
<select name="city" class="form-control">
<option value="">All Regions</option>
<?php foreach ($cities as $c): ?>
<option value="<?= $c ?>" <?= $city === $c ? 'selected' : '' ?>><?= $c ?></option>
<?php endforeach; ?>
</select>
</div>
<div class="form-group mb-0">
<label class="text-secondary fw-black mb-1" style="text-transform: uppercase; letter-spacing: 2px; font-size: 0.75rem;">Brand</label>
<select name="brand" class="form-control">
<option value="">All Brands</option>
<?php foreach ($brands as $b): ?>
<option value="<?= $b ?>" <?= $brand === $b ? 'selected' : '' ?>><?= $b ?></option>
<?php endforeach; ?>
</select>
</div>
<button type="submit" class="btn btn-primary fw-black" style="height: 56px; padding: 0 2rem; letter-spacing: 1px;">APPLY FILTERS</button>
</form>
</div>
<!-- Listings -->
<div class="grid grid-3 mt-4">
<?php foreach ($cars as $car): ?>
<div class="card car-card">
<div style="height: 240px; background-image: url('<?= htmlspecialchars($car['image_path'] ?: 'assets/images/placeholder-car.jpg') ?>'); background-size: cover; background-position: center; position: relative;">
<?php if ($car['status'] === 'sold'): ?>
<div class="sold-overlay">
<div class="sold-stamp" style="font-size: 2.5rem; padding: 10px 20px; border-width: 5px;">SOLD</div>
</div>
<?php elseif ($car['is_hot_deal']): ?>
<span class="badge badge-danger" style="position: absolute; top: 1.5rem; left: 1.5rem; z-index: 5;">Hot Deal</span>
<?php endif; ?>
</div>
<div class="card-content" style="padding: 2.5rem;">
<div class="flex gap-1 text-secondary text-sm fw-black mb-1" style="text-transform: uppercase; letter-spacing: 1px;">
<span>📍 <?= htmlspecialchars($car['city']) ?></span>
<span>📅 <?= $car['year'] ?> Model</span>
</div>
<h3 class="fw-black mb-2" style="font-size: 1.6rem; color: #fff;"><?= htmlspecialchars($car['brand'] . ' ' . $car['model']) ?></h3>
<div class="flex justify-between align-center mt-2 pt-2" style="border-top: 1px solid var(--glass-border);">
<span class="price-tag" style="font-size: 1.8rem;">$<?= number_format($car['price']) ?></span>
<?php if ($car['status'] === 'sold'): ?>
<a href="car_detail.php?id=<?= $car['id'] ?>" class="btn btn-outline btn-sm fw-bold" style="opacity: 0.5;">View Info</a>
<?php else: ?>
<a href="car_detail.php?id=<?= $car['id'] ?>" class="btn btn-primary btn-sm fw-bold">View Details</a>
<?php endif; ?>
</div>
</div>
</div>
<?php endforeach; ?>
</div>
<?php if (empty($cars)): ?>
<div class="text-center" style="padding: 12rem 0;">
<div style="font-size: 5rem; margin-bottom: 2rem; filter: drop-shadow(0 10px 20px rgba(0,0,0,0.3));">🔍</div>
<h2 class="fw-black mb-1" style="font-size: 2.5rem; color: #fff;">No premium vehicles found</h2>
<p class="text-secondary fw-bold" style="font-size: 1.1rem;">Try adjusting your filters or refining your search criteria.</p>
</div>
<?php endif; ?>
</div>
<?php require_once __DIR__ . '/includes/footer.php'; ?>

View File

@ -1,109 +0,0 @@
<?php
require_once __DIR__ . '/includes/header.php';
$success = false;
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$name = $_POST['name'] ?? '';
$email = $_POST['email'] ?? '';
$subject = $_POST['subject'] ?? '';
$message = $_POST['message'] ?? '';
$pdo = db();
$stmt = $pdo->prepare("INSERT INTO contact_messages (name, email, subject, message) VALUES (?, ?, ?, ?)");
if ($stmt->execute([$name, $email, $subject, $message])) {
$success = true;
}
}
?>
<section class="hero" style="height: 50vh; background: linear-gradient(rgba(15, 23, 42, 0.8), rgba(15, 23, 42, 0.8)), url('assets/images/contact-hero.jpg') center/cover no-repeat fixed;">
<h1 class="fw-black" style="font-size: 5rem; letter-spacing: -3px; color: #fff;">Connect With Us</h1>
<p class="text-secondary fw-bold" style="font-size: 1.3rem; max-width: 700px; margin-left: auto; margin-right: auto;">Our elite concierge team is ready to assist you with every aspect of your premium automotive journey.</p>
</section>
<div class="container" style="max-width: 1200px; margin-top: -6rem; padding-bottom: 8rem;">
<div class="grid" style="grid-template-columns: 1fr 1.8fr; gap: 4rem; align-items: start;">
<div class="flex" style="flex-direction: column; gap: 2rem;">
<div class="glass" style="padding: 3rem; border-left: 6px solid var(--primary-color);">
<h3 class="fw-black text-gold mb-2" style="display: flex; align-items: center; gap: 1rem; font-size: 1.4rem;">
<span style="font-size: 2rem;">📍</span> Headquarters
</h3>
<p class="text-secondary fw-bold" style="font-size: 1.1rem; line-height: 1.8;">
Wazir Akbar Khan, District 10,<br>
Kabul, Afghanistan
</p>
<p class="text-gold fw-black mt-2" style="font-size: 1.5rem;">+93 799 123 456</p>
</div>
<div class="glass" style="padding: 3rem; border-left: 6px solid var(--primary-color);">
<h3 class="fw-black text-gold mb-2" style="display: flex; align-items: center; gap: 1rem; font-size: 1.4rem;">
<span style="font-size: 2rem;">🕒</span> Concierge Hours
</h3>
<div class="flex justify-between mb-1">
<span class="text-secondary fw-bold">Sat - Wed:</span>
<span class="fw-black">08:00 - 18:00</span>
</div>
<div class="flex justify-between">
<span class="text-secondary fw-bold">Thursday:</span>
<span class="fw-black">08:00 - 13:00</span>
</div>
</div>
<div class="glass" style="padding: 3rem; border-left: 6px solid var(--primary-color);">
<h3 class="fw-black text-gold mb-2" style="display: flex; align-items: center; gap: 1rem; font-size: 1.4rem;">
<span style="font-size: 2rem;">✉️</span> Digital Inquiries
</h3>
<p class="text-secondary fw-bold" style="font-size: 1.1rem;">info@afgcars.af</p>
<p class="text-secondary fw-bold" style="font-size: 1.1rem;">concierge@afgcars.af</p>
</div>
</div>
<div class="glass" style="padding: 5rem;">
<h2 class="fw-black mb-2" style="font-size: 2.5rem; color: #fff;">Direct Inquiry Portal</h2>
<p class="text-secondary mb-3 fw-bold">Submit your requirements and our specialists will contact you shortly.</p>
<?php if ($success): ?>
<div class="alert alert-success mb-3" style="padding: 2rem; border-radius: 20px;">
<span style="font-size: 1.5rem;"></span> Your message has been encrypted and securely transmitted to our team.
</div>
<?php endif; ?>
<form method="POST">
<div class="grid grid-2 mb-2">
<div class="form-group">
<label class="text-secondary fw-black mb-1" style="text-transform: uppercase; letter-spacing: 2px; font-size: 0.75rem;">Your Full Name</label>
<input type="text" name="name" class="form-control" required placeholder="John Doe">
</div>
<div class="form-group">
<label class="text-secondary fw-black mb-1" style="text-transform: uppercase; letter-spacing: 2px; font-size: 0.75rem;">Email Address</label>
<input type="email" name="email" class="form-control" required placeholder="john@example.com">
</div>
</div>
<div class="form-group">
<label class="text-secondary fw-black mb-1" style="text-transform: uppercase; letter-spacing: 2px; font-size: 0.75rem;">Inquiry Subject</label>
<input type="text" name="subject" class="form-control" required placeholder="Regarding Land Cruiser 2024 Inquiry">
</div>
<div class="form-group">
<label class="text-secondary fw-black mb-1" style="text-transform: uppercase; letter-spacing: 2px; font-size: 0.75rem;">Detailed Message</label>
<textarea name="message" class="form-control" rows="6" required placeholder="Provide as much detail as possible..."></textarea>
</div>
<button type="submit" class="btn btn-primary w-full fw-black" style="padding: 1.5rem; font-size: 1.1rem; letter-spacing: 1px;">TRANSMIT SECURE MESSAGE</button>
</form>
</div>
</div>
</div>
<div class="container" style="padding-bottom: 8rem;">
<div class="glass" style="height: 500px; width: 100%; position: relative; overflow: hidden; border-radius: 32px;">
<!-- Map Placeholder -->
<div style="position: absolute; inset: 0; background: url('assets/images/contact-map.jpg') center/cover; filter: grayscale(0.8) contrast(1.1) brightness(0.4);"></div>
<div style="position: relative; height: 100%; display: flex; flex-direction: column; justify-content: center; align-items: center; background: rgba(15, 23, 42, 0.4);">
<div style="font-size: 5rem; margin-bottom: 2rem; filter: drop-shadow(0 10px 20px rgba(0,0,0,0.5));">📍</div>
<h2 class="fw-black" style="font-size: 3.5rem; text-transform: uppercase; letter-spacing: 5px; color: #fff; line-height: 1;">Strategic Location</h2>
<p class="text-gold fw-black" style="font-size: 1.4rem; letter-spacing: 2px; margin-top: 1rem;">VISIT THE KABUL EXPERIENCE CENTER</p>
<a href="https://maps.google.com" target="_blank" class="btn btn-outline fw-black" style="margin-top: 3rem; padding: 1.2rem 3rem;">OPEN IN NAVIGATION</a>
</div>
</div>
</div>
<?php require_once __DIR__ . '/includes/footer.php'; ?>

View File

@ -1,154 +0,0 @@
<?php
require_once __DIR__ . '/includes/header.php';
if (!isset($_SESSION['user_id'])) {
header('Location: login.php');
exit;
}
$pdo = db();
$user_id = $_SESSION['user_id'];
// Fetch user's car listings
$stmt = $pdo->prepare("
SELECT c.*, ci.image_path
FROM cars c
LEFT JOIN car_images ci ON c.id = ci.car_id AND ci.is_main = 1
WHERE c.user_id = ? AND c.deleted_at IS NULL
ORDER BY c.created_at DESC
");
$stmt->execute([$user_id]);
$my_listings = $stmt->fetchAll();
// Fetch user's purchase requests
$stmt = $pdo->prepare("
SELECT p.*, c.brand, c.model, c.year, c.price, ci.image_path
FROM purchases p
JOIN cars c ON p.car_id = c.id
LEFT JOIN car_images ci ON c.id = ci.car_id AND ci.is_main = 1
WHERE p.user_id = ?
ORDER BY p.created_at DESC
");
$stmt->execute([$user_id]);
$my_purchases = $stmt->fetchAll();
?>
<div class="container" style="padding: 4rem 0;">
<div class="page-header">
<div>
<h1>User Dashboard</h1>
<p>Manage your vehicle listings and track your purchase requests.</p>
</div>
<a href="add_car.php" class="btn btn-primary">List New Vehicle</a>
</div>
<div class="grid" style="grid-template-columns: 1fr; gap: 5rem;">
<!-- My Listings Section -->
<section>
<h2 class="section-title">
<span class="section-icon">🚗</span>
My Vehicle Listings
</h2>
<?php if (empty($my_listings)): ?>
<div class="box text-center">
<p class="text-secondary mb-2" style="font-size: 1.2rem;">You haven't listed any vehicles yet.</p>
<a href="add_car.php" class="btn btn-outline">Start Selling Today</a>
</div>
<?php else: ?>
<div class="grid grid-3">
<?php foreach ($my_listings as $car): ?>
<div class="card" style="position: relative;">
<div style="height: 200px; background-image: url('<?= htmlspecialchars($car['image_path'] ?: 'assets/images/placeholder-car.jpg') ?>'); background-size: cover; background-position: center;">
<?php if ($car['status'] === 'sold'): ?>
<div class="sold-overlay">SOLD</div>
<?php endif; ?>
</div>
<div class="card-content">
<div class="flex justify-between align-center mb-2">
<div>
<h3 class="fw-black mb-1" style="font-size: 1.4rem;"><?= htmlspecialchars($car['brand'] . ' ' . $car['model']) ?></h3>
<p class="text-secondary text-sm fw-bold"><?= $car['year'] ?> • <?= htmlspecialchars($car['city']) ?></p>
</div>
<span class="badge badge-<?= $car['status'] === 'approved' ? 'success' : ($car['status'] === 'sold' ? 'info' : ($car['status'] === 'rejected' ? 'danger' : 'primary')) ?>">
<?= $car['status'] ?>
</span>
</div>
<div class="flex justify-between align-center mt-2 pt-2" style="border-top: 1px solid var(--glass-border);">
<span class="price-tag">$<?= number_format($car['price']) ?></span>
<a href="edit_car.php?id=<?= $car['id'] ?>" class="text-gold fw-bold text-sm" style="text-decoration: none;">
Edit Details
</a>
</div>
</div>
</div>
<?php endforeach; ?>
</div>
<?php endif; ?>
</section>
<!-- My Purchase Requests Section -->
<section>
<h2 class="section-title">
<span class="section-icon">💰</span>
My Purchase Requests
</h2>
<?php if (empty($my_purchases)): ?>
<div class="box text-center">
<p class="text-secondary mb-2" style="font-size: 1.2rem;">You haven't made any purchase requests yet.</p>
<a href="cars.php" class="btn btn-outline">Browse Marketplace</a>
</div>
<?php else: ?>
<div class="box" style="padding: 0; overflow: hidden;">
<div class="table-container">
<table>
<thead>
<tr>
<th>Vehicle</th>
<th>Price</th>
<th>Bank ID</th>
<th>Status</th>
<th>Action</th>
</tr>
</thead>
<tbody>
<?php foreach ($my_purchases as $p): ?>
<tr>
<td>
<div class="flex align-center gap-1">
<img src="<?= htmlspecialchars($p['image_path'] ?: 'assets/images/placeholder-car.jpg') ?>" style="width: 80px; height: 50px; object-fit: cover; border-radius: 8px;">
<div>
<div class="fw-black" style="font-size: 1.1rem; color: #fff;"><?= htmlspecialchars($p['brand'] . ' ' . $p['model']) ?></div>
<div class="text-sm text-secondary fw-bold"><?= $p['year'] ?> Model</div>
</div>
</div>
</td>
<td class="price-tag">$<?= number_format($p['price']) ?></td>
<td><code class="text-gold fw-bold" style="background: rgba(255,255,255,0.05); padding: 0.4rem 0.8rem; border-radius: 6px;"><?= htmlspecialchars($p['bank_id']) ?></code></td>
<td>
<span class="badge badge-<?= $p['status'] === 'approved' ? 'success' : ($p['status'] === 'rejected' ? 'danger' : 'primary') ?>">
<?= $p['status'] ?>
</span>
</td>
<td>
<?php if ($p['status'] === 'approved'): ?>
<a href="receipt.php?id=<?= $p['id'] ?>" class="btn btn-primary btn-sm">View Receipt</a>
<?php else: ?>
<span class="text-secondary text-sm fw-bold">Under Review</span>
<?php endif; ?>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
</div>
<?php endif; ?>
</section>
</div>
</div>
<?php require_once __DIR__ . '/includes/footer.php'; ?>

View File

@ -15,6 +15,3 @@ function db() {
} }
return $pdo; return $pdo;
} }
// Global Autoloader for Enterprise Architecture
require_once __DIR__ . '/../app/Helpers/Autoloader.php';

View File

@ -1,347 +0,0 @@
/*M!999999\- enable the sandbox mode */
-- MariaDB dump 10.19 Distrib 10.11.14-MariaDB, for debian-linux-gnu (x86_64)
--
-- Host: 127.0.0.1 Database: app_38703
-- ------------------------------------------------------
-- Server version 10.11.14-MariaDB-0+deb12u2
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8mb4 */;
/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
/*!40103 SET TIME_ZONE='+00:00' */;
/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
--
-- Table structure for table `car_images`
--
DROP TABLE IF EXISTS `car_images`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8mb4 */;
CREATE TABLE `car_images` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`car_id` int(11) NOT NULL,
`image_path` varchar(255) NOT NULL,
`is_main` tinyint(1) DEFAULT 0,
PRIMARY KEY (`id`),
KEY `car_id` (`car_id`),
CONSTRAINT `car_images_ibfk_1` FOREIGN KEY (`car_id`) REFERENCES `cars` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=41 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
--
-- Dumping data for table `car_images`
--
LOCK TABLES `car_images` WRITE;
/*!40000 ALTER TABLE `car_images` DISABLE KEYS */;
INSERT INTO `car_images` VALUES
(1,5,'https://images.pexels.com/photos/170811/pexels-photo-170811.jpeg?auto=compress&cs=tinysrgb&w=600',1),
(2,6,'https://images.pexels.com/photos/116675/pexels-photo-116675.jpeg?auto=compress&cs=tinysrgb&w=600',1),
(3,7,'https://images.pexels.com/photos/337909/pexels-photo-337909.jpeg?auto=compress&cs=tinysrgb&w=600',1),
(4,8,'https://images.pexels.com/photos/912413/pexels-photo-912413.jpeg?auto=compress&cs=tinysrgb&w=600',1),
(5,9,'https://images.pexels.com/photos/3729464/pexels-photo-3729464.jpeg?auto=compress&cs=tinysrgb&w=600',1),
(6,10,'https://images.pexels.com/photos/337909/pexels-photo-337909.jpeg?auto=compress&cs=tinysrgb&w=600',1),
(7,11,'https://images.pexels.com/photos/3729464/pexels-photo-3729464.jpeg?auto=compress&cs=tinysrgb&w=600',1),
(8,12,'https://images.pexels.com/photos/112460/pexels-photo-112460.jpeg?auto=compress&cs=tinysrgb&w=600',1),
(9,13,'https://images.pexels.com/photos/1149137/pexels-photo-1149137.jpeg?auto=compress&cs=tinysrgb&w=600',1),
(10,14,'https://images.pexels.com/photos/3729464/pexels-photo-3729464.jpeg?auto=compress&cs=tinysrgb&w=600',1),
(11,15,'https://images.pexels.com/photos/1149137/pexels-photo-1149137.jpeg?auto=compress&cs=tinysrgb&w=600',1),
(12,16,'https://images.pexels.com/photos/1149137/pexels-photo-1149137.jpeg?auto=compress&cs=tinysrgb&w=600',1),
(13,17,'https://images.pexels.com/photos/210019/pexels-photo-210019.jpeg?auto=compress&cs=tinysrgb&w=600',1),
(14,18,'https://images.pexels.com/photos/1149137/pexels-photo-1149137.jpeg?auto=compress&cs=tinysrgb&w=600',1),
(15,19,'https://images.pexels.com/photos/3729464/pexels-photo-3729464.jpeg?auto=compress&cs=tinysrgb&w=600',1),
(16,20,'https://images.pexels.com/photos/337909/pexels-photo-337909.jpeg?auto=compress&cs=tinysrgb&w=600',1),
(17,21,'https://images.pexels.com/photos/210019/pexels-photo-210019.jpeg?auto=compress&cs=tinysrgb&w=600',1),
(18,22,'https://images.pexels.com/photos/912413/pexels-photo-912413.jpeg?auto=compress&cs=tinysrgb&w=600',1),
(19,23,'https://images.pexels.com/photos/337909/pexels-photo-337909.jpeg?auto=compress&cs=tinysrgb&w=600',1),
(20,24,'https://images.pexels.com/photos/112460/pexels-photo-112460.jpeg?auto=compress&cs=tinysrgb&w=600',1),
(21,25,'assets/images/cars/car_25.jpg',1),
(22,26,'assets/images/cars/car_26.jpg',1),
(23,27,'assets/images/cars/car_27.jpg',1),
(24,28,'assets/images/cars/car_28.jpg',1),
(25,29,'assets/images/cars/car_29.jpg',1),
(26,30,'assets/images/cars/car_30.jpg',1),
(27,31,'assets/images/cars/car_31.jpg',1),
(28,32,'assets/images/cars/car_32.jpg',1),
(29,33,'assets/images/cars/car_33.jpg',1),
(30,34,'assets/images/cars/car_34.jpg',1),
(31,35,'assets/images/cars/car_35.jpg',1),
(32,36,'assets/images/cars/car_36.jpg',1),
(33,37,'assets/images/cars/car_37.jpg',1),
(34,38,'assets/images/cars/car_38.jpg',1),
(35,39,'assets/images/cars/car_39.jpg',1),
(36,40,'assets/images/cars/car_40.jpg',1),
(37,41,'assets/images/cars/car_41.jpg',1),
(38,42,'assets/images/cars/car_42.jpg',1),
(39,43,'assets/images/cars/car_43.jpg',1),
(40,44,'assets/images/cars/car_44.jpg',1);
/*!40000 ALTER TABLE `car_images` ENABLE KEYS */;
UNLOCK TABLES;
--
-- Table structure for table `cars`
--
DROP TABLE IF EXISTS `cars`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8mb4 */;
CREATE TABLE `cars` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`user_id` int(11) NOT NULL,
`brand` varchar(50) NOT NULL,
`model` varchar(50) NOT NULL,
`year` int(11) NOT NULL,
`price` decimal(10,2) NOT NULL,
`city` varchar(50) NOT NULL,
`description` text DEFAULT NULL,
`status` enum('pending','approved','rejected','sold') DEFAULT 'pending',
`is_hot_deal` tinyint(1) DEFAULT 0,
`created_at` timestamp NULL DEFAULT current_timestamp(),
`deleted_at` timestamp NULL DEFAULT NULL,
`reserved_by` int(11) DEFAULT NULL,
`reserved_at` timestamp NULL DEFAULT NULL,
`reservation_expires_at` timestamp NULL DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `user_id` (`user_id`),
KEY `fk_cars_reserved_by` (`reserved_by`),
CONSTRAINT `cars_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE,
CONSTRAINT `fk_cars_reserved_by` FOREIGN KEY (`reserved_by`) REFERENCES `users` (`id`) ON DELETE SET NULL
) ENGINE=InnoDB AUTO_INCREMENT=45 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
--
-- Dumping data for table `cars`
--
LOCK TABLES `cars` WRITE;
/*!40000 ALTER TABLE `cars` DISABLE KEYS */;
INSERT INTO `cars` VALUES
(1,1,'Toyota','Land Cruiser',2023,85000.00,'Kabul','Brand new armored Land Cruiser.','approved',1,'2026-02-23 08:30:42',NULL,NULL,NULL,NULL),
(2,1,'Mercedes-Benz','G-Wagon',2022,120000.00,'Kabul','Luxury performance SUV.','approved',1,'2026-02-23 08:30:42',NULL,NULL,NULL,NULL),
(3,1,'Lexus','LX570',2021,95000.00,'Herat','Full option premium SUV.','approved',1,'2026-02-23 08:30:42',NULL,NULL,NULL,NULL),
(4,1,'Toyota','Corolla',2020,15000.00,'Mazar-i-Sharif','Reliable and fuel efficient.','approved',1,'2026-02-23 08:30:42',NULL,NULL,NULL,NULL),
(5,1,'Honda','CR-V',2023,108176.00,'Ghazni','Luxury interior, premium sound system, and smooth ride.','approved',1,'2026-02-23 08:38:51',NULL,NULL,NULL,NULL),
(6,1,'Honda','CR-V',2020,92260.00,'Kunduz','Very clean inside and out, low mileage.','approved',0,'2026-02-23 08:38:51',NULL,NULL,NULL,NULL),
(7,1,'Hyundai','Elantra',2018,106805.00,'Mazar-i-Sharif','Powerful engine, off-road capabilities, and spacious.','approved',0,'2026-02-23 08:38:51',NULL,NULL,NULL,NULL),
(8,1,'Lexus','RX350',2022,113917.00,'Jalalabad','Fuel efficient, perfect for city driving.','approved',0,'2026-02-23 08:38:51',NULL,NULL,NULL,NULL),
(9,1,'Toyota','4Runner',2019,9825.00,'Kandahar','Recently imported, custom cleared, and plate registered.','approved',0,'2026-02-23 08:38:51',NULL,NULL,NULL,NULL),
(10,1,'Ford','Mustang',2015,73007.00,'Balkh','Powerful engine, off-road capabilities, and spacious.','approved',1,'2026-02-23 08:38:51',NULL,NULL,NULL,NULL),
(11,1,'Lexus','GX460',2019,55171.00,'Kunduz','Fuel efficient, perfect for city driving.','approved',1,'2026-02-23 08:38:51',NULL,NULL,NULL,NULL),
(12,1,'Mercedes-Benz','E-Class',2021,32368.00,'Balkh','Very clean inside and out, low mileage.','approved',0,'2026-02-23 08:38:51',NULL,NULL,NULL,NULL),
(13,1,'Lexus','GX460',2016,113113.00,'Jalalabad','Top of the line model with all modern features.','approved',0,'2026-02-23 08:38:51',NULL,NULL,NULL,NULL),
(14,1,'Honda','CR-V',2024,47994.00,'Kabul','Top of the line model with all modern features.','approved',1,'2026-02-23 08:38:51',NULL,NULL,NULL,NULL),
(15,1,'BMW','X6',2023,47523.00,'Kunduz','Very clean inside and out, low mileage.','approved',0,'2026-02-23 08:38:51',NULL,NULL,NULL,NULL),
(16,1,'Lexus','LX570',2024,16004.00,'Balkh','Excellent condition, very well maintained.','approved',1,'2026-02-23 08:38:51',NULL,NULL,NULL,NULL),
(17,1,'Ford','F-150',2017,94685.00,'Mazar-i-Sharif','Very clean inside and out, low mileage.','approved',0,'2026-02-23 08:38:51',NULL,NULL,NULL,NULL),
(18,1,'Hyundai','Elantra',2018,72033.00,'Jalalabad','Very clean inside and out, low mileage.','approved',1,'2026-02-23 08:38:51',NULL,NULL,NULL,NULL),
(19,1,'Lexus','RX350',2019,22049.00,'Kabul','Powerful engine, off-road capabilities, and spacious.','approved',0,'2026-02-23 08:38:51',NULL,NULL,NULL,NULL),
(20,1,'Toyota','Corolla',2015,46604.00,'Kunduz','Very clean inside and out, low mileage.','approved',0,'2026-02-23 08:38:51',NULL,NULL,NULL,NULL),
(21,1,'Mercedes-Benz','E-Class',2022,122658.00,'Kandahar','Full option, armored, and ready for any terrain.','approved',1,'2026-02-23 08:38:51',NULL,NULL,NULL,NULL),
(22,1,'BMW','X5',2023,129562.00,'Balkh','Powerful engine, off-road capabilities, and spacious.','approved',0,'2026-02-23 08:38:51',NULL,NULL,NULL,NULL),
(23,1,'Ford','Explorer',2019,83940.00,'Kandahar','Recently imported, custom cleared, and plate registered.','approved',0,'2026-02-23 08:38:51',NULL,NULL,NULL,NULL),
(24,1,'Toyota','Hilux',2018,93171.00,'Mazar-i-Sharif','Fuel efficient, perfect for city driving.','approved',0,'2026-02-23 08:38:51',NULL,NULL,NULL,NULL),
(25,1,'Toyota','Camry',2022,25000.00,'Kabul','Excellent condition, low mileage, full options.','approved',1,'2026-02-23 09:39:14',NULL,NULL,NULL,NULL),
(26,1,'Honda','Accord',2021,22000.00,'Herat','Well maintained, fuel efficient, clean interior.','approved',0,'2026-02-23 09:39:14',NULL,NULL,NULL,NULL),
(27,1,'Ford','F-150',2023,45000.00,'Kandahar','Powerful truck, brand new, ready for heavy duty.','approved',1,'2026-02-23 09:39:14',NULL,NULL,NULL,NULL),
(28,1,'BMW','3 Series',2020,32000.00,'Mazar-i-Sharif','Luxury sedan, premium sound system, sunroof.','approved',0,'2026-02-23 09:39:14',NULL,NULL,NULL,NULL),
(29,1,'Mercedes-Benz','C-Class',2021,38000.00,'Jalalabad','Elegant design, smooth ride, advanced safety features.','approved',1,'2026-02-23 09:39:14',NULL,NULL,NULL,NULL),
(30,1,'Audi','A4',2022,35000.00,'Kabul','Quattro all-wheel drive, leather seats, virtual cockpit.','approved',0,'2026-02-23 09:39:14',NULL,NULL,NULL,NULL),
(31,1,'Tesla','Model 3',2023,40000.00,'Kabul','Electric car, long range, autopilot enabled.','approved',1,'2026-02-23 09:39:14',NULL,NULL,NULL,NULL),
(32,1,'Hyundai','Elantra',2021,18000.00,'Herat','Reliable daily driver, great gas mileage.','approved',0,'2026-02-23 09:39:14',NULL,NULL,NULL,NULL),
(33,1,'Kia','Forte',2022,19500.00,'Kandahar','Sporty look, modern technology, long warranty.','approved',0,'2026-02-23 09:39:14',NULL,NULL,NULL,NULL),
(34,1,'Mazda','3',2021,21000.00,'Mazar-i-Sharif','Fun to drive, stylish exterior, high-quality materials.','approved',0,'2026-02-23 09:39:14',NULL,NULL,NULL,NULL),
(35,1,'Volkswagen','Jetta',2020,17500.00,'Kabul','German engineering, spacious cabin, comfortable ride.','approved',0,'2026-02-23 09:39:14',NULL,NULL,NULL,NULL),
(36,1,'Chevrolet','Malibu',2022,23000.00,'Herat','Smooth performance, quiet interior, spacious trunk.','approved',0,'2026-02-23 09:39:14',NULL,NULL,NULL,NULL),
(37,1,'Nissan','Altima',2021,20000.00,'Jalalabad','All-wheel drive, comfortable seats, good fuel economy.','approved',0,'2026-02-23 09:39:14',NULL,NULL,NULL,NULL),
(38,1,'Subaru','Impreza',2022,21500.00,'Kabul','Standard AWD, great safety ratings, durable build.','approved',0,'2026-02-23 09:39:14',NULL,NULL,NULL,NULL),
(39,1,'Lexus','IS',2021,36000.00,'Kandahar','Refined luxury, excellent reliability, sharp handling.','approved',1,'2026-02-23 09:39:14',NULL,NULL,NULL,NULL),
(40,1,'Volvo','S60',2022,39000.00,'Mazar-i-Sharif','Award-winning safety, Scandinavian design, powerful engine.','approved',0,'2026-02-23 09:39:14',NULL,NULL,NULL,NULL),
(41,1,'Cadillac','CT4',2021,33000.00,'Kabul','American luxury, sporty performance, advanced tech.','approved',0,'2026-02-23 09:39:14',NULL,NULL,NULL,NULL),
(42,1,'Genesis','G70',2022,37000.00,'Herat','Premium interior, athletic handling, great value.','approved',1,'2026-02-23 09:39:14',NULL,NULL,NULL,NULL),
(43,1,'Infiniti','Q50',2020,28000.00,'Kandahar','Dynamic performance, twin-turbo engine, stylish looks.','approved',0,'2026-02-23 09:39:14',NULL,NULL,NULL,NULL),
(44,1,'Acura','TLX',2021,31000.00,'Jalalabad','Precision crafted performance, comfortable and tech-focused.','approved',0,'2026-02-23 09:39:14',NULL,NULL,NULL,NULL);
/*!40000 ALTER TABLE `cars` ENABLE KEYS */;
UNLOCK TABLES;
--
-- Table structure for table `contact_messages`
--
DROP TABLE IF EXISTS `contact_messages`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8mb4 */;
CREATE TABLE `contact_messages` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(100) DEFAULT NULL,
`email` varchar(100) DEFAULT NULL,
`subject` varchar(200) DEFAULT NULL,
`message` text DEFAULT NULL,
`status` enum('unread','read','answered') DEFAULT 'unread',
`created_at` timestamp NULL DEFAULT current_timestamp(),
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
--
-- Dumping data for table `contact_messages`
--
LOCK TABLES `contact_messages` WRITE;
/*!40000 ALTER TABLE `contact_messages` DISABLE KEYS */;
/*!40000 ALTER TABLE `contact_messages` ENABLE KEYS */;
UNLOCK TABLES;
--
-- Table structure for table `purchases`
--
DROP TABLE IF EXISTS `purchases`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8mb4 */;
CREATE TABLE `purchases` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`transaction_id` char(36) DEFAULT NULL,
`reference_number` varchar(50) DEFAULT NULL,
`verification_token` varchar(64) DEFAULT NULL,
`car_id` int(11) NOT NULL,
`user_id` int(11) NOT NULL,
`buyer_name` varchar(100) DEFAULT NULL,
`buyer_email` varchar(100) DEFAULT NULL,
`buyer_phone` varchar(20) DEFAULT NULL,
`bank_id` varchar(100) DEFAULT NULL,
`personal_info` text DEFAULT NULL,
`status` enum('initiated','processing','paid','failed','refunded','chargeback','reserved','completed','cancelled','pending','approved','rejected') DEFAULT 'initiated',
`created_at` timestamp NULL DEFAULT current_timestamp(),
`base_price` decimal(10,2) NOT NULL DEFAULT 0.00,
`marketplace_fee` decimal(10,2) NOT NULL DEFAULT 0.00,
`tax` decimal(10,2) NOT NULL DEFAULT 0.00,
`total_amount` decimal(10,2) NOT NULL DEFAULT 0.00,
`payment_method` enum('card','bank_transfer','wallet') DEFAULT NULL,
`escrow_status` enum('awaiting_verification','held_in_escrow','released','cancelled') DEFAULT 'awaiting_verification',
`expires_at` timestamp NULL DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `car_id` (`car_id`),
KEY `user_id` (`user_id`),
CONSTRAINT `purchases_ibfk_1` FOREIGN KEY (`car_id`) REFERENCES `cars` (`id`) ON DELETE CASCADE,
CONSTRAINT `purchases_ibfk_2` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
--
-- Dumping data for table `purchases`
--
LOCK TABLES `purchases` WRITE;
/*!40000 ALTER TABLE `purchases` DISABLE KEYS */;
/*!40000 ALTER TABLE `purchases` ENABLE KEYS */;
UNLOCK TABLES;
--
-- Table structure for table `reviews`
--
DROP TABLE IF EXISTS `reviews`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8mb4 */;
CREATE TABLE `reviews` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`car_id` int(11) NOT NULL,
`user_id` int(11) NOT NULL,
`rating` int(11) DEFAULT NULL CHECK (`rating` >= 1 and `rating` <= 5),
`comment` text DEFAULT NULL,
`status` enum('pending','approved') DEFAULT 'pending',
`created_at` timestamp NULL DEFAULT current_timestamp(),
PRIMARY KEY (`id`),
KEY `car_id` (`car_id`),
KEY `user_id` (`user_id`),
CONSTRAINT `reviews_ibfk_1` FOREIGN KEY (`car_id`) REFERENCES `cars` (`id`) ON DELETE CASCADE,
CONSTRAINT `reviews_ibfk_2` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
--
-- Dumping data for table `reviews`
--
LOCK TABLES `reviews` WRITE;
/*!40000 ALTER TABLE `reviews` DISABLE KEYS */;
/*!40000 ALTER TABLE `reviews` ENABLE KEYS */;
UNLOCK TABLES;
--
-- Table structure for table `settings`
--
DROP TABLE IF EXISTS `settings`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8mb4 */;
CREATE TABLE `settings` (
`key` varchar(50) NOT NULL,
`value` varchar(255) NOT NULL,
`updated_at` timestamp NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
PRIMARY KEY (`key`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
--
-- Dumping data for table `settings`
--
LOCK TABLES `settings` WRITE;
/*!40000 ALTER TABLE `settings` DISABLE KEYS */;
INSERT INTO `settings` VALUES
('marketplace_fee_percentage','5','2026-02-23 15:37:03'),
('tax_percentage','10','2026-02-23 15:37:03');
/*!40000 ALTER TABLE `settings` ENABLE KEYS */;
UNLOCK TABLES;
--
-- Table structure for table `users`
--
DROP TABLE IF EXISTS `users`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8mb4 */;
CREATE TABLE `users` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(100) NOT NULL,
`email` varchar(100) NOT NULL,
`phone` varchar(20) DEFAULT NULL,
`address` text DEFAULT NULL,
`password` varchar(255) NOT NULL,
`role` enum('guest','user','admin') DEFAULT 'user',
`status` enum('active','inactive') DEFAULT 'active',
`created_at` timestamp NULL DEFAULT current_timestamp(),
`deleted_at` timestamp NULL DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `email` (`email`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
--
-- Dumping data for table `users`
--
LOCK TABLES `users` WRITE;
/*!40000 ALTER TABLE `users` DISABLE KEYS */;
INSERT INTO `users` VALUES
(1,'Admin','admin@gmail.com',NULL,NULL,'$2y$10$JCXfZuRFtFozIdO.r40iQeueUsqIWutBjlAS/8hkL/7rVbPd2JOhu','admin','active','2026-02-23 08:29:20',NULL);
/*!40000 ALTER TABLE `users` ENABLE KEYS */;
UNLOCK TABLES;
/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
-- Dump completed on 2026-02-23 15:59:42

View File

@ -1,38 +0,0 @@
-- Enterprise Buy/Sell/Payment Module Migration
-- Update cars table for reservations
ALTER TABLE `cars`
ADD COLUMN `reserved_by` INT NULL,
ADD COLUMN `reserved_at` TIMESTAMP NULL,
ADD COLUMN `reservation_expires_at` TIMESTAMP NULL,
ADD CONSTRAINT `fk_cars_reserved_by` FOREIGN KEY (`reserved_by`) REFERENCES `users`(`id`) ON DELETE SET NULL;
-- Update purchases table for Enterprise Flow
-- We need to check if existing purchases exist and handle them.
-- Since this is an upgrade, we'll allow NULL for new columns temporarily if needed,
-- but the requirement asks for NOT NULL UNIQUE, so we'll be careful.
ALTER TABLE `purchases`
ADD COLUMN `transaction_id` CHAR(36) NULL AFTER `id`,
ADD COLUMN `reference_number` VARCHAR(50) NULL AFTER `transaction_id`,
ADD COLUMN `verification_token` VARCHAR(64) NULL AFTER `reference_number`,
ADD COLUMN `base_price` DECIMAL(10,2) NOT NULL DEFAULT 0.00,
ADD COLUMN `marketplace_fee` DECIMAL(10,2) NOT NULL DEFAULT 0.00,
ADD COLUMN `tax` DECIMAL(10,2) NOT NULL DEFAULT 0.00,
ADD COLUMN `total_amount` DECIMAL(10,2) NOT NULL DEFAULT 0.00,
ADD COLUMN `payment_method` ENUM('card', 'bank_transfer', 'wallet') NULL,
ADD COLUMN `escrow_status` ENUM('awaiting_verification', 'held_in_escrow', 'released', 'cancelled') DEFAULT 'awaiting_verification',
ADD COLUMN `expires_at` TIMESTAMP NULL;
ALTER TABLE `purchases`
MODIFY COLUMN `status` ENUM('initiated', 'processing', 'paid', 'failed', 'refunded', 'chargeback', 'reserved', 'completed', 'cancelled', 'pending', 'approved', 'rejected') DEFAULT 'initiated';
-- Settings table for configurable marketplace values
CREATE TABLE IF NOT EXISTS `settings` (
`key` VARCHAR(50) PRIMARY KEY,
`value` VARCHAR(255) NOT NULL,
`updated_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
INSERT IGNORE INTO `settings` (`key`, `value`) VALUES
('marketplace_fee_percentage', '5'),
('tax_percentage', '10');

View File

@ -1,126 +0,0 @@
<?php
require_once __DIR__ . '/config.php';
try {
$pdo = db();
// Users Table
$pdo->exec("CREATE TABLE IF NOT EXISTS users (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(100) NOT NULL,
email VARCHAR(100) NOT NULL UNIQUE,
password VARCHAR(255) NOT NULL,
phone VARCHAR(20) DEFAULT NULL,
address TEXT DEFAULT NULL,
role ENUM('guest', 'user', 'admin') DEFAULT 'user',
status ENUM('active', 'inactive') DEFAULT 'active',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
deleted_at TIMESTAMP NULL DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;");
// Cars Table
$pdo->exec("CREATE TABLE IF NOT EXISTS cars (
id INT AUTO_INCREMENT PRIMARY KEY,
user_id INT NOT NULL,
brand VARCHAR(50) NOT NULL,
model VARCHAR(50) NOT NULL,
year INT NOT NULL,
price DECIMAL(10, 2) NOT NULL,
city VARCHAR(50) NOT NULL,
description TEXT,
status ENUM('pending', 'approved', 'rejected', 'sold') DEFAULT 'pending',
is_hot_deal BOOLEAN DEFAULT FALSE,
reserved_by INT NULL,
reserved_at TIMESTAMP NULL,
reservation_expires_at TIMESTAMP NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
deleted_at TIMESTAMP NULL DEFAULT NULL,
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
CONSTRAINT fk_cars_reserved_by FOREIGN KEY (reserved_by) REFERENCES users(id) ON DELETE SET NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;");
// Car Images Table
$pdo->exec("CREATE TABLE IF NOT EXISTS car_images (
id INT AUTO_INCREMENT PRIMARY KEY,
car_id INT NOT NULL,
image_path VARCHAR(255) NOT NULL,
is_main BOOLEAN DEFAULT FALSE,
FOREIGN KEY (car_id) REFERENCES cars(id) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;");
// Reviews Table
$pdo->exec("CREATE TABLE IF NOT EXISTS reviews (
id INT AUTO_INCREMENT PRIMARY KEY,
car_id INT NOT NULL,
user_id INT NOT NULL,
rating INT CHECK (rating >= 1 AND rating <= 5),
comment TEXT,
status ENUM('pending', 'approved') DEFAULT 'pending',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (car_id) REFERENCES cars(id) ON DELETE CASCADE,
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;");
// Purchases Table (Enterprise Module)
$pdo->exec("CREATE TABLE IF NOT EXISTS purchases (
id INT AUTO_INCREMENT PRIMARY KEY,
transaction_id CHAR(36) NULL,
reference_number VARCHAR(50) NULL,
verification_token VARCHAR(64) NULL,
car_id INT NOT NULL,
user_id INT NOT NULL,
buyer_name VARCHAR(100),
buyer_email VARCHAR(100),
buyer_phone VARCHAR(20),
bank_id VARCHAR(100),
personal_info TEXT,
base_price DECIMAL(10,2) NOT NULL DEFAULT 0.00,
marketplace_fee DECIMAL(10,2) NOT NULL DEFAULT 0.00,
tax DECIMAL(10,2) NOT NULL DEFAULT 0.00,
total_amount DECIMAL(10,2) NOT NULL DEFAULT 0.00,
payment_method ENUM('card', 'bank_transfer', 'wallet') NULL,
escrow_status ENUM('awaiting_verification', 'held_in_escrow', 'released', 'cancelled') DEFAULT 'awaiting_verification',
expires_at TIMESTAMP NULL,
status ENUM('initiated', 'processing', 'paid', 'failed', 'refunded', 'chargeback', 'reserved', 'completed', 'cancelled', 'pending', 'approved', 'rejected') DEFAULT 'initiated',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (car_id) REFERENCES cars(id) ON DELETE CASCADE,
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;");
// Contact Messages
$pdo->exec("CREATE TABLE IF NOT EXISTS contact_messages (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(100),
email VARCHAR(100),
subject VARCHAR(200),
message TEXT,
status ENUM('unread', 'read', 'answered') DEFAULT 'unread',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;");
// Settings Table
$pdo->exec("CREATE TABLE IF NOT EXISTS settings (
`key` VARCHAR(50) PRIMARY KEY,
`value` VARCHAR(255) NOT NULL,
`updated_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;");
// Seed Settings
$pdo->exec("INSERT IGNORE INTO settings (`key`, `value`) VALUES
('marketplace_fee_percentage', '5'),
('tax_percentage', '10');");
// Seed Admin User
$adminEmail = 'admin@gmail.com';
$stmt = $pdo->prepare("SELECT id FROM users WHERE email = ?");
$stmt->execute([$adminEmail]);
if (!$stmt->fetch()) {
$password = password_hash('12345678', PASSWORD_DEFAULT);
$pdo->prepare("INSERT INTO users (name, email, password, role) VALUES (?, ?, ?, ?)")
->execute(['Admin', $adminEmail, $password, 'admin']);
}
echo "Database setup successfully.";
} catch (PDOException $e) {
die("Database error: " . $e->getMessage());
}

View File

@ -1,123 +0,0 @@
<?php
require_once __DIR__ . '/includes/header.php';
if (!isset($_SESSION['user_id'])) {
header('Location: login.php');
exit;
}
$pdo = db();
$id = $_GET['id'] ?? 0;
$userId = $_SESSION['user_id'];
// Check ownership or admin role
$isAdmin = isset($_SESSION['role']) && $_SESSION['role'] === 'admin';
if ($isAdmin) {
$stmt = $pdo->prepare("SELECT * FROM cars WHERE id = ? AND deleted_at IS NULL");
$stmt->execute([$id]);
} else {
$stmt = $pdo->prepare("SELECT * FROM cars WHERE id = ? AND user_id = ? AND deleted_at IS NULL");
$stmt->execute([$id, $userId]);
}
$car = $stmt->fetch();
if (!$car) {
header('Location: dashboard.php');
exit;
}
$error = '';
$success = false;
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$brand = $_POST['brand'] ?? '';
$model = $_POST['model'] ?? '';
$year = $_POST['year'] ?? '';
$price = $_POST['price'] ?? '';
$city = $_POST['city'] ?? '';
$description = $_POST['description'] ?? '';
try {
$stmt = $pdo->prepare("UPDATE cars SET brand = ?, model = ?, year = ?, price = ?, city = ?, description = ?, status = 'pending' WHERE id = ?");
$stmt->execute([$brand, $model, $year, $price, $city, $description, $id]);
$success = true;
// Refresh car data
$car['brand'] = $brand;
$car['model'] = $model;
$car['year'] = $year;
$car['price'] = $price;
$car['city'] = $city;
$car['description'] = $description;
} catch (Exception $e) {
$error = "Update failed: " . $e->getMessage();
}
}
$cities = ['Kabul', 'Herat', 'Mazar-i-Sharif', 'Kandahar', 'Jalalabad', 'Kunduz', 'Ghazni', 'Balkh'];
?>
<div class="container" style="max-width: 900px; padding: 4rem 0;">
<div class="box" style="padding: 4.5rem;">
<h1 class="fw-black mb-1" style="font-size: 3rem; color: #fff;">Edit Vehicle Listing</h1>
<p class="text-secondary mb-3" style="font-size: 1.15rem; font-weight: 500;">Update your vehicle specifications. Note: making changes will reset the approval status to 'pending'.</p>
<?php if ($success): ?>
<div class="glass text-center mb-4" style="padding: 3rem; border-color: var(--success); background: rgba(46, 213, 115, 0.05); color: var(--success); border-radius: 24px;">
<h3 class="fw-black mb-1" style="font-size: 2rem;"> Vehicle Updated Successfully!</h3>
<p class="text-secondary mb-2" style="font-size: 1.1rem; font-weight: 700;">Your changes have been saved and the listing is awaiting re-approval by our administrators.</p>
<div class="mt-2">
<a href="<?= $isAdmin ? 'admin_cars.php' : 'dashboard.php' ?>" class="btn btn-primary btn-lg">Back to Management Console</a>
</div>
</div>
<?php endif; ?>
<?php if ($error): ?>
<div class="alert alert-error mb-2"><?= $error ?></div>
<?php endif; ?>
<form method="POST">
<div class="grid grid-2 mb-2">
<div class="form-group">
<label>Vehicle Brand</label>
<input type="text" name="brand" class="form-control" value="<?= htmlspecialchars($car['brand']) ?>" required>
</div>
<div class="form-group">
<label>Vehicle Model</label>
<input type="text" name="model" class="form-control" value="<?= htmlspecialchars($car['model']) ?>" required>
</div>
</div>
<div class="grid grid-2 mb-2">
<div class="form-group">
<label>Manufacturing Year</label>
<input type="number" name="year" class="form-control" value="<?= htmlspecialchars($car['year']) ?>" required>
</div>
<div class="form-group">
<label>Asking Price (USD)</label>
<input type="number" name="price" class="form-control" value="<?= htmlspecialchars($car['price']) ?>" required>
</div>
</div>
<div class="form-group">
<label>Current Location (City)</label>
<select name="city" class="form-control" required>
<?php foreach ($cities as $c): ?>
<option value="<?= $c ?>" <?= $car['city'] === $c ? 'selected' : '' ?>><?= $c ?></option>
<?php endforeach; ?>
</select>
</div>
<div class="form-group">
<label>Vehicle Description & Details</label>
<textarea name="description" class="form-control" rows="6" required placeholder="Describe the current condition, maintenance history, and features..."><?= htmlspecialchars($car['description']) ?></textarea>
</div>
<div class="mt-3 flex gap-1 align-center">
<button type="submit" class="btn btn-primary btn-lg" style="flex: 2; font-weight: 900; letter-spacing: 1px;">SAVE DOCUMENTED CHANGES</button>
<a href="<?= $isAdmin ? 'admin_cars.php' : 'dashboard.php' ?>" class="btn btn-outline btn-lg" style="flex: 1; font-weight: 700;">DISCARD & EXIT</a>
</div>
</form>
</div>
</div>
<?php require_once __DIR__ . '/includes/footer.php'; ?>

View File

@ -1,49 +0,0 @@
<footer>
<div class="footer-grid">
<div class="footer-col">
<a href="index.php" class="logo">AfgCars</a>
<p style="margin-top: 1.5rem; color: var(--text-secondary); font-size: 0.95rem; line-height: 1.8;">
The most premium and trusted car marketplace in Afghanistan. We bridge the gap between luxury and accessibility for every Afghan citizen.
</p>
<div style="display: flex; gap: 1rem; margin-top: 1.5rem;">
<span style="font-size: 1.2rem; cursor: pointer; opacity: 0.6;">𝕏</span>
<span style="font-size: 1.2rem; cursor: pointer; opacity: 0.6;">📘</span>
<span style="font-size: 1.2rem; cursor: pointer; opacity: 0.6;">📸</span>
</div>
</div>
<div class="footer-col">
<h4>Marketplace</h4>
<ul>
<li><a href="index.php">Home</a></li>
<li><a href="cars.php">All Vehicles</a></li>
<li><a href="cars.php?hot_deal=1">Hot Deals</a></li>
<li><a href="register.php">Sell Your Car</a></li>
</ul>
</div>
<div class="footer-col">
<h4>Company</h4>
<ul>
<li><a href="about.php">About Us</a></li>
<li><a href="contact.php">Contact Us</a></li>
<li><a href="about.php#locations">Our Locations</a></li>
<li><a href="about.php#mission">Our Mission</a></li>
</ul>
</div>
<div class="footer-col">
<h4>Showrooms</h4>
<ul style="color: var(--text-secondary); font-size: 0.9rem;">
<li style="margin-bottom: 0.8rem;">📍 Kabul Main: Street 15, Wazir Akbar Khan</li>
<li style="margin-bottom: 0.8rem;">📍 Herat: Near Blue Mosque</li>
<li style="margin-bottom: 0.8rem;">📍 Mazar: Balkh Gate Road</li>
<li style="margin-bottom: 0.8rem;">📞 Support: +93 799 123 456</li>
</ul>
</div>
</div>
<div class="footer-bottom">
<p>&copy; <?= date('Y') ?> AfgCars Premium Marketplace. All rights reserved.</p>
<p style="margin-top: 1rem; opacity: 0.4; font-size: 0.75rem; letter-spacing: 1px;">UNIVERSITY FINAL-YEAR PROJECT DESIGNED FOR AFGHANISTAN 2026</p>
</div>
</footer>
<script src="assets/js/main.js"></script>
</body>
</html>

View File

@ -1,53 +0,0 @@
<?php
if (session_status() === PHP_SESSION_NONE) {
session_start();
}
require_once __DIR__ . '/../db/config.php';
$projectDescription = $_SERVER['PROJECT_DESCRIPTION'] ?? 'Premium Car Marketplace Afghanistan';
// List of admin pages that use the sidebar layout
$adminPages = [
'admin_dashboard.php',
'admin_cars.php',
'admin_users.php',
'admin_messages.php',
'admin_purchases.php'
];
$currentPage = basename($_SERVER['SCRIPT_NAME']);
$isAdminPage = in_array($currentPage, $adminPages);
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>AfgCars | Premium Marketplace</title>
<meta name="description" content="<?= htmlspecialchars($projectDescription) ?>">
<link rel="stylesheet" href="assets/css/fonts.css">
<link rel="stylesheet" href="assets/css/style.css?v=<?= time() ?>">
</head>
<body>
<?php if (!$isAdminPage): ?>
<nav>
<a href="index.php" class="logo">AfgCars</a>
<ul class="nav-links">
<li><a href="index.php">Home</a></li>
<li><a href="cars.php">Marketplace</a></li>
<li><a href="about.php">About</a></li>
<li><a href="contact.php">Contact</a></li>
</ul>
<div class="nav-actions" style="display: flex; align-items: center; gap: 1rem;">
<?php if (isset($_SESSION['user_id'])): ?>
<?php if (($_SESSION['role'] ?? '') === 'admin'): ?>
<a href="admin_dashboard.php" class="btn-auth">Admin Panel</a>
<?php else: ?>
<a href="dashboard.php" class="btn-auth">My Account</a>
<?php endif; ?>
<a href="logout.php" class="btn-auth" style="border-color: rgba(255, 71, 87, 0.3); color: var(--danger);">Logout</a>
<?php else: ?>
<a href="login.php" class="btn-auth">Login / Register</a>
<?php endif; ?>
</div>
</nav>
<?php endif; ?>

265
index.php
View File

@ -1,127 +1,150 @@
<?php <?php
require_once __DIR__ . '/includes/header.php'; declare(strict_types=1);
@ini_set('display_errors', '1');
@error_reporting(E_ALL);
@date_default_timezone_set('UTC');
$pdo = db(); $phpVersion = PHP_VERSION;
// Get hot deals $now = date('Y-m-d H:i:s');
$hotDeals = $pdo->query("SELECT c.*, ci.image_path FROM cars c LEFT JOIN car_images ci ON c.id = ci.car_id AND ci.is_main = 1 WHERE c.is_hot_deal = 1 AND c.status = 'approved' LIMIT 6")->fetchAll();
$testimonials = [
[
'name' => 'Ahmad Wali',
'city' => 'Kabul',
'text' => 'Found my dream Land Cruiser here. The process was smooth and the seller was very professional. Highly recommended for premium cars in Afghanistan!',
'rating' => 5
],
[
'name' => 'Mariam Sadat',
'city' => 'Herat',
'text' => 'As a first-time car buyer, I felt very safe using AfgCars. The verified listings give me peace of mind. Excellent service!',
'rating' => 5
],
[
'name' => 'Zubair Khan',
'city' => 'Mazar-i-Sharif',
'text' => 'The best marketplace in the country. Clean interface and very easy to contact sellers. Sold my Corolla within 3 days!',
'rating' => 4
]
];
?> ?>
<!doctype html>
<section class="hero" style="background: linear-gradient(rgba(15, 23, 42, 0.85), rgba(15, 23, 42, 0.85)), url('assets/images/hero-home.jpg') center/cover no-repeat fixed;"> <html lang="en">
<div style="z-index: 2; position: relative;"> <head>
<h1 class="fw-black" style="color: #ffffff; font-size: 5.5rem; letter-spacing: -3px; line-height: 1;">Find Your Premium Ride</h1> <meta charset="utf-8" />
<p class="text-secondary mt-2 mb-3" style="font-size: 1.4rem; max-width: 800px; margin-left: auto; margin-right: auto; font-weight: 500;">Afghanistan's most trusted elite automotive marketplace. Where luxury meets reliability.</p> <meta name="viewport" content="width=device-width, initial-scale=1" />
<div class="flex justify-center gap-1"> <title>New Style</title>
<a href="cars.php" class="btn btn-primary btn-lg fw-black">View Marketplace</a> <?php
<?php if (!isset($_SESSION['user_id'])): ?> // Read project preview data from environment
<a href="register.php" class="btn btn-outline btn-lg fw-black">Start Selling Today</a> $projectDescription = $_SERVER['PROJECT_DESCRIPTION'] ?? '';
<?php else: ?> $projectImageUrl = $_SERVER['PROJECT_IMAGE_URL'] ?? '';
<a href="dashboard.php" class="btn btn-outline btn-lg fw-black">Access My Portal</a> ?>
<?php endif; ?> <?php if ($projectDescription): ?>
</div> <!-- Meta description -->
</div> <meta name="description" content='<?= htmlspecialchars($projectDescription) ?>' />
</section> <!-- Open Graph meta tags -->
<meta property="og:description" content="<?= htmlspecialchars($projectDescription) ?>" />
<div class="container" style="padding: 8rem 0;"> <!-- Twitter meta tags -->
<h2 class="section-title justify-center mb-4" style="font-size: 3.5rem;">🔥 Current Hot Deals</h2> <meta property="twitter:description" content="<?= htmlspecialchars($projectDescription) ?>" />
<div class="grid grid-3 mt-3"> <?php endif; ?>
<?php foreach ($hotDeals as $car): ?> <?php if ($projectImageUrl): ?>
<!-- Open Graph image -->
<meta property="og:image" content="<?= htmlspecialchars($projectImageUrl) ?>" />
<!-- Twitter image -->
<meta property="twitter:image" content="<?= htmlspecialchars($projectImageUrl) ?>" />
<?php endif; ?>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=swap" rel="stylesheet">
<style>
:root {
--bg-color-start: #6a11cb;
--bg-color-end: #2575fc;
--text-color: #ffffff;
--card-bg-color: rgba(255, 255, 255, 0.01);
--card-border-color: rgba(255, 255, 255, 0.1);
}
body {
margin: 0;
font-family: 'Inter', sans-serif;
background: linear-gradient(45deg, var(--bg-color-start), var(--bg-color-end));
color: var(--text-color);
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
text-align: center;
overflow: hidden;
position: relative;
}
body::before {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100" viewBox="0 0 100 100"><path d="M-10 10L110 10M10 -10L10 110" stroke-width="1" stroke="rgba(255,255,255,0.05)"/></svg>');
animation: bg-pan 20s linear infinite;
z-index: -1;
}
@keyframes bg-pan {
0% { background-position: 0% 0%; }
100% { background-position: 100% 100%; }
}
main {
padding: 2rem;
}
.card {
background: var(--card-bg-color);
border: 1px solid var(--card-border-color);
border-radius: 16px;
padding: 2rem;
backdrop-filter: blur(20px);
-webkit-backdrop-filter: blur(20px);
box-shadow: 0 8px 32px 0 rgba(0, 0, 0, 0.1);
}
.loader {
margin: 1.25rem auto 1.25rem;
width: 48px;
height: 48px;
border: 3px solid rgba(255, 255, 255, 0.25);
border-top-color: #fff;
border-radius: 50%;
animation: spin 1s linear infinite;
}
@keyframes spin {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
.hint {
opacity: 0.9;
}
.sr-only {
position: absolute;
width: 1px; height: 1px;
padding: 0; margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap; border: 0;
}
h1 {
font-size: 3rem;
font-weight: 700;
margin: 0 0 1rem;
letter-spacing: -1px;
}
p {
margin: 0.5rem 0;
font-size: 1.1rem;
}
code {
background: rgba(0,0,0,0.2);
padding: 2px 6px;
border-radius: 4px;
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
}
footer {
position: absolute;
bottom: 1rem;
font-size: 0.8rem;
opacity: 0.7;
}
</style>
</head>
<body>
<main>
<div class="card"> <div class="card">
<div style="overflow: hidden; height: 260px; border-bottom: 1px solid var(--glass-border); position: relative;"> <h1>Analyzing your requirements and generating your website…</h1>
<img src="<?= htmlspecialchars($car['image_path'] ?: 'assets/images/placeholder-car.jpg') ?>" class="w-full" style="height: 100%; object-fit: cover;"> <div class="loader" role="status" aria-live="polite" aria-label="Applying initial changes">
<span class="badge badge-danger" style="position: absolute; top: 1.5rem; left: 1.5rem; z-index: 5;">Hot Deal</span> <span class="sr-only">Loading…</span>
</div> </div>
<div class="card-content"> <p class="hint"><?= ($_SERVER['HTTP_HOST'] ?? '') === 'appwizzy.com' ? 'AppWizzy' : 'Flatlogic' ?> AI is collecting your requirements and applying the first changes.</p>
<div class="flex gap-1 text-secondary text-sm fw-black mb-1" style="text-transform: uppercase; letter-spacing: 1px;"> <p class="hint">This page will update automatically as the plan is implemented.</p>
<span>📅 <?= htmlspecialchars($car['year']) ?> Model</span> <p>Runtime: PHP <code><?= htmlspecialchars($phpVersion) ?></code> — UTC <code><?= htmlspecialchars($now) ?></code></p>
<span>📍 <?= htmlspecialchars($car['city']) ?></span>
</div> </div>
<h3 class="fw-black mb-2" style="font-size: 1.6rem; color: #fff;"><?= htmlspecialchars($car['brand'] . ' ' . $car['model']) ?></h3> </main>
<div class="flex justify-between align-center mt-2 pt-2" style="border-top: 1px solid var(--glass-border);"> <footer>
<div class="price-tag" style="font-size: 1.8rem;">$<?= number_format($car['price']) ?></div> Page updated: <?= htmlspecialchars($now) ?> (UTC)
<a href="car_detail.php?id=<?= $car['id'] ?>" class="btn btn-outline btn-sm fw-bold">View Details</a> </footer>
</div> </body>
</div> </html>
</div>
<?php endforeach; ?>
</div>
</div>
<section style="background: rgba(30, 41, 59, 0.4); padding: 10rem 0; border-top: 1px solid var(--glass-border); border-bottom: 1px solid var(--glass-border);">
<div class="container">
<h2 class="section-title justify-center mb-4" style="font-size: 3.5rem;">What Our Clients Say</h2>
<div class="grid grid-3 mt-3">
<?php foreach ($testimonials as $t): ?>
<div class="glass" style="padding: 4rem; background: rgba(15, 23, 42, 0.6);">
<div style="color: var(--primary-color); margin-bottom: 2rem; font-size: 1.5rem; letter-spacing: 5px;">
<?php for($i=0; $i<$t['rating']; $i++) echo '★'; ?>
</div>
<p class="text-secondary mb-3" style="font-style: italic; line-height: 2; font-size: 1.2rem; font-weight: 500;">"<?= htmlspecialchars($t['text']) ?>"</p>
<div class="flex align-center gap-1">
<div style="width: 60px; height: 60px; background: var(--primary-color); border-radius: 16px; display: flex; align-items: center; justify-content: center; font-weight: 900; color: #000; font-size: 1.4rem;">
<?= substr($t['name'], 0, 1) ?>
</div>
<div>
<h4 class="fw-black" style="margin: 0; font-size: 1.2rem; color: #fff;"><?= htmlspecialchars($t['name']) ?></h4>
<p class="text-secondary text-sm fw-bold" style="margin: 0;"><?= htmlspecialchars($t['city']) ?></p>
</div>
</div>
</div>
<?php endforeach; ?>
</div>
</div>
</section>
<div class="container" style="padding: 10rem 0;">
<h2 class="section-title justify-center mb-4" style="font-size: 3.5rem;">Elite Showrooms</h2>
<div class="grid grid-3 mt-3">
<div class="box text-center" style="padding: 5rem 3rem;">
<div style="font-size: 5rem; margin-bottom: 2.5rem; filter: drop-shadow(0 10px 20px rgba(0,0,0,0.3));">📍</div>
<h3 class="fw-black mb-1" style="font-size: 1.8rem; color: #fff;">Kabul Headquarters</h3>
<p class="text-secondary mb-2 fw-bold">Wazir Akbar Khan, Street 15</p>
<p class="text-gold fw-black" style="font-size: 1.4rem;">+93 700 123 456</p>
</div>
<div class="box text-center" style="padding: 5rem 3rem;">
<div style="font-size: 5rem; margin-bottom: 2.5rem; filter: drop-shadow(0 10px 20px rgba(0,0,0,0.3));">📍</div>
<h3 class="fw-black mb-1" style="font-size: 1.8rem; color: #fff;">Herat Elite Branch</h3>
<p class="text-secondary mb-2 fw-bold">Jada-e-Main, Near Blue Mosque</p>
<p class="text-gold fw-black" style="font-size: 1.4rem;">+93 700 987 654</p>
</div>
<div class="box text-center" style="padding: 5rem 3rem;">
<div style="font-size: 5rem; margin-bottom: 2.5rem; filter: drop-shadow(0 10px 20px rgba(0,0,0,0.3));">📍</div>
<h3 class="fw-black mb-1" style="font-size: 1.8rem; color: #fff;">Mazar Luxury Center</h3>
<p class="text-secondary mb-2 fw-bold">Balkh Gate Road Center</p>
<p class="text-gold fw-black" style="font-size: 1.4rem;">+93 700 456 789</p>
</div>
</div>
</div>
<div class="container" style="text-align: center; margin-bottom: 10rem;">
<div class="box" style="padding: 10rem 5rem; background: linear-gradient(135deg, rgba(212, 175, 55, 0.15), rgba(30, 41, 59, 0.4)); border-radius: 48px;">
<h2 class="fw-black mb-2" style="font-size: 4.5rem; color: #fff; line-height: 1;">Ready to sell your vehicle?</h2>
<p class="text-secondary mb-4" style="max-width: 800px; margin-left: auto; margin-right: auto; font-size: 1.4rem; line-height: 1.8; font-weight: 500;">Experience the most professional automotive trading platform in Afghanistan. Verified buyers and seamless documentation guaranteed.</p>
<a href="register.php" class="btn btn-primary btn-lg fw-black" style="padding: 1.8rem 5rem; font-size: 1.2rem; letter-spacing: 1px;">START SELLING TODAY</a>
</div>
</div>
<?php require_once __DIR__ . '/includes/footer.php'; ?>

View File

@ -1,68 +0,0 @@
<?php
require_once __DIR__ . '/includes/header.php';
$error = '';
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$email = $_POST['email'] ?? '';
$password = $_POST['password'] ?? '';
$pdo = db();
$stmt = $pdo->prepare("SELECT * FROM users WHERE email = ? AND deleted_at IS NULL");
$stmt->execute([$email]);
$user = $stmt->fetch();
if ($user && password_verify($password, $user['password'])) {
if ($user['status'] === 'active') {
$_SESSION['user_id'] = $user['id'];
$_SESSION['user_name'] = $user['name'];
$_SESSION['user_email'] = $user['email'];
$_SESSION['role'] = $user['role'];
// Redirect based on role
if ($user['role'] === 'admin') {
header('Location: admin_dashboard.php');
} else {
header('Location: dashboard.php');
}
exit;
} else {
$error = "Your account is inactive. Please contact admin.";
}
} else {
$error = "Invalid email or password.";
}
}
?>
<div class="container" style="display: flex; justify-content: center; align-items: center; min-height: 80vh; padding: 4rem 0;">
<div class="box" style="width: 100%; max-width: 500px; padding: 4.5rem;">
<div class="text-center mb-3">
<h2 class="fw-black" style="font-size: 2.8rem; color: #fff; margin-bottom: 0.5rem; line-height: 1.1;">Welcome Back</h2>
<p class="text-secondary fw-bold" style="font-size: 1.1rem;">Sign in to your premium AfgCars portal</p>
</div>
<?php if ($error): ?>
<div class="alert alert-error mb-2 text-center" style="justify-content: center;">
<?= $error ?>
</div>
<?php endif; ?>
<form method="POST">
<div class="form-group">
<label class="text-secondary fw-black mb-1" style="text-transform: uppercase; letter-spacing: 2px; font-size: 0.75rem;">Email Address</label>
<input type="email" name="email" class="form-control" required placeholder="name@example.com">
</div>
<div class="form-group">
<label class="text-secondary fw-black mb-1" style="text-transform: uppercase; letter-spacing: 2px; font-size: 0.75rem;">Security Password</label>
<input type="password" name="password" class="form-control" required placeholder="••••••••">
</div>
<button type="submit" class="btn btn-primary w-full mt-2 fw-black" style="padding: 1.3rem; font-size: 1.1rem; letter-spacing: 1px;">SIGN IN TO ACCOUNT</button>
</form>
<p class="text-center mt-3 text-secondary fw-bold" style="font-size: 1rem;">
New to AfgCars? <a href="register.php" class="text-gold" style="text-decoration: none; border-bottom: 1px solid var(--primary-color);">Create your account</a>
</p>
</div>
</div>
<?php require_once __DIR__ . '/includes/footer.php'; ?>

View File

@ -1,5 +0,0 @@
<?php
session_start();
session_destroy();
header('Location: index.php');
exit;

View File

@ -1,187 +0,0 @@
<?php
require_once __DIR__ . '/includes/header.php';
use App\Controllers\PurchaseController;
use App\Services\PurchaseService;
use App\Repositories\CarRepository;
if (!isset($_SESSION['user_id'])) {
header('Location: login.php');
exit;
}
$controller = new PurchaseController();
$purchaseService = new PurchaseService();
$carRepo = new CarRepository();
$id = $_GET['id'] ?? 0;
$userId = $_SESSION['user_id'];
// Step 1: Try to reserve the car
$reservation = $controller->reserve($id, $userId);
if (!$reservation['success']) {
$_SESSION['error'] = $reservation['message'];
header('Location: car_detail.php?id=' . $id);
exit;
}
$car = $carRepo->find($id);
// Fetch main image manually since find() doesn't JOIN images (standard repository pattern)
$stmt = db()->prepare("SELECT image_path FROM car_images WHERE car_id = ? AND is_main = 1");
$stmt->execute([$id]);
$mainImage = $stmt->fetch();
$car['image_path'] = $mainImage ? $mainImage['image_path'] : 'assets/images/placeholder-car.jpg';
$costs = $purchaseService->calculateFees($car['price']);
$success = false;
$error = '';
$transactionId = '';
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$buyerData = [
'name' => $_POST['buyer_name'] ?? '',
'phone' => $_POST['buyer_phone'] ?? '',
'email' => $_SESSION['user_email'] ?? '',
'bank_id' => $_POST['bank_id'] ?? '',
'personal_info' => $_POST['personal_info'] ?? '',
'payment_method' => $_POST['payment_method'] ?? 'bank_transfer'
];
$result = $controller->checkout($id, $userId, $buyerData);
if ($result['success']) {
$success = true;
$transactionId = $result['transaction_id'];
} else {
$error = $result['message'];
}
}
?>
<div class="container" style="max-width: 1200px; padding: 4rem 0;">
<?php if ($success): ?>
<div class="box text-center" style="padding: 6rem;">
<div style="font-size: 6rem; margin-bottom: 2.5rem; filter: drop-shadow(0 10px 20px rgba(0,0,0,0.3));">🚀</div>
<h1 class="text-gold fw-black mb-1" style="font-size: 3.5rem;">Purchase Initiated!</h1>
<p class="text-secondary mb-3" style="font-size: 1.3rem; max-width: 750px; margin-left: auto; margin-right: auto; line-height: 1.8; font-weight: 600;">
Your secure transaction <strong class="text-gold"><?= htmlspecialchars($transactionId) ?></strong> has been created.
The car is reserved for you. Please proceed with payment verification.
</p>
<div class="flex justify-center gap-1 mt-3">
<a href="receipt.php?tx=<?= $transactionId ?>" class="btn btn-primary btn-lg">View Invoice</a>
<a href="dashboard.php" class="btn btn-outline btn-lg">Go to Dashboard</a>
</div>
</div>
<?php else: ?>
<div class="grid" style="grid-template-columns: 1fr 1.6fr; gap: 4rem; align-items: start;">
<div class="glass" style="padding: 2.5rem; position: sticky; top: 120px; border-top: 5px solid var(--primary-color);">
<h3 class="fw-black mb-2 text-gold" style="text-transform: uppercase; letter-spacing: 2px; font-size: 1rem;">Enterprise Checkout</h3>
<div class="mb-2" style="width: 100%; height: 220px; background-image: url('<?= htmlspecialchars($car['image_path']) ?>'); background-size: cover; background-position: center; border-radius: 20px; border: 1px solid var(--glass-border);"></div>
<h2 class="fw-black mb-1" style="font-size: 1.8rem; color: #fff;"><?= htmlspecialchars($car['brand'] . ' ' . $car['model']) ?></h2>
<p class="text-secondary mb-2 fw-bold" style="font-size: 1.1rem;"><?= $car['year'] ?> Model • <?= $car['city'] ?></p>
<div class="mt-2 pt-2" style="border-top: 1px solid var(--glass-border);">
<div class="flex justify-between mb-1">
<span class="text-secondary">Car Price</span>
<span class="text-white fw-bold">$<?= number_format($costs['base_price'], 2) ?></span>
</div>
<div class="flex justify-between mb-1">
<span class="text-secondary">Marketplace Fee (<?= $purchaseService->calculateFees($car['price'])['fee'] / $car['price'] * 100 ?>%)</span>
<span class="text-white fw-bold">$<?= number_format($costs['fee'], 2) ?></span>
</div>
<div class="flex justify-between mb-1">
<span class="text-secondary">Tax (<?= $purchaseService->calculateFees($car['price'])['tax'] / $car['price'] * 100 ?>%)</span>
<span class="text-white fw-bold">$<?= number_format($costs['tax'], 2) ?></span>
</div>
<div class="flex justify-between align-center mt-1 pt-1" style="border-top: 2px dashed var(--glass-border);">
<span class="text-gold fw-black" style="text-transform: uppercase; font-size: 0.85rem;">Total Payable</span>
<span class="price-tag" style="font-size: 1.8rem;">$<?= number_format($costs['total'], 2) ?></span>
</div>
</div>
<div class="mt-2 p-1 text-center" style="background: rgba(255,0,0,0.1); border-radius: 10px;">
<p class="text-sm text-white m-0">Reservation expires in: <span id="timer">15:00</span></p>
</div>
</div>
<div class="glass" style="padding: 4.5rem;">
<div class="flex align-center gap-1 mb-2">
<span class="badge badge-primary">ESCROW PROTECTION ACTIVE</span>
<span class="text-secondary text-sm">Transaction ID: Securely Generated</span>
</div>
<h1 class="fw-black mb-1" style="font-size: 3rem; color: #fff;">Buyer Verification</h1>
<p class="text-secondary mb-3" style="font-size: 1.15rem; font-weight: 500;">Provide your legal documentation and banking details to proceed with this secure purchase.</p>
<?php if ($error): ?>
<div class="alert alert-error mb-2"><?= $error ?></div>
<?php endif; ?>
<form method="POST">
<div class="grid grid-2">
<div class="form-group">
<label>Full Legal Name (as on ID Card)</label>
<input type="text" name="buyer_name" class="form-control" value="<?= htmlspecialchars($_SESSION['user_name'] ?? '') ?>" required placeholder="Enter your full name">
</div>
<div class="form-group">
<label>Phone Number</label>
<input type="text" name="buyer_phone" class="form-control" required placeholder="+93 7xx xxx xxx">
</div>
</div>
<div class="form-group">
<label>Payment Method</label>
<select name="payment_method" class="form-control" required>
<option value="bank_transfer">Bank Transfer (Escrow Mode)</option>
<option value="card">Credit/Debit Card</option>
<option value="wallet">Digital Wallet</option>
</select>
</div>
<div class="form-group">
<label>Bank Reference ID / Account Number</label>
<input type="text" name="bank_id" class="form-control" required placeholder="Azizi Bank / Kabul Bank Transaction ID">
<p class="text-sm text-secondary mt-1 fw-bold">This reference will be verified with the Afghan banking systems.</p>
</div>
<div class="form-group">
<label>Legal Identification & Address</label>
<textarea name="personal_info" class="form-control" rows="4" required placeholder="Enter Tazkira/Passport number and current residential address for official sale documentation..."></textarea>
</div>
<div class="mt-3 mb-3" style="padding: 2.5rem; background: rgba(212, 175, 55, 0.05); border-left: 5px solid var(--primary-color); border-radius: 20px;">
<p class="text-secondary text-sm" style="line-height: 1.8; margin: 0; font-weight: 600;">
<strong class="text-gold" style="font-size: 1.1rem; display: block; margin-bottom: 0.5rem;">ENTERPRISE ESCROW SYSTEM:</strong>
Your payment will be held securely in Escrow. Funds are only released to the seller once you confirm receipt of the vehicle and the admin verifies all documentation.
</p>
</div>
<div class="flex align-center gap-1 mt-3">
<button type="submit" class="btn btn-primary btn-lg" style="flex: 2; font-weight: 900; letter-spacing: 1px;">SECURE CHECKOUT & PAY</button>
<a href="car_detail.php?id=<?= $id ?>" class="btn btn-outline btn-lg" style="flex: 1; font-weight: 700;">CANCEL</a>
</div>
</form>
</div>
</div>
<?php endif; ?>
</div>
<script>
let timeLeft = 15 * 60;
const timerElement = document.getElementById('timer');
const countdown = setInterval(() => {
if (timeLeft <= 0) {
clearInterval(countdown);
alert('Reservation expired. Please refresh the page to try again.');
window.location.reload();
} else {
const minutes = Math.floor(timeLeft / 60);
const seconds = timeLeft % 60;
timerElement.innerText = `${minutes}:${seconds < 10 ? '0' : ''}${seconds}`;
timeLeft--;
}
}, 1000);
</script>
<?php require_once __DIR__ . '/includes/footer.php'; ?>

View File

@ -1,155 +0,0 @@
<?php
require_once __DIR__ . '/includes/header.php';
use App\Repositories\PurchaseRepository;
use App\Services\PaymentService;
if (!isset($_SESSION['user_id'])) {
header('Location: login.php');
exit;
}
$txId = $_GET['tx'] ?? '';
$purchaseRepo = new PurchaseRepository();
$paymentService = new PaymentService();
// Fetch purchase details
$stmt = db()->prepare("
SELECT p.*, c.brand, c.model, c.year, c.city, u.name as seller_name, u.phone as seller_phone
FROM purchases p
JOIN cars c ON p.car_id = c.id
JOIN users u ON c.user_id = u.id
WHERE p.transaction_id = ? AND (p.user_id = ? OR ?)
");
$isAdmin = isset($_SESSION['role']) && $_SESSION['role'] === 'admin';
$stmt->execute([$txId, $_SESSION['user_id'], $isAdmin]);
$data = $stmt->fetch();
if (!$data) {
echo "<div class='container' style='padding: 5rem; text-align: center;'><h1>Invoice not found.</h1><a href='dashboard.php' class='btn btn-primary'>Back to Dashboard</a></div>";
require_once __DIR__ . '/includes/footer.php';
exit;
}
// Generate verification hash if missing (for legacy or just-in-time check)
$verificationHash = $data['verification_token'] ?: $paymentService->generateVerificationToken($data['transaction_id'], $data['total_amount']);
?>
<div class="container" style="max-width: 900px; padding: 4rem 0;">
<div id="receipt" class="glass receipt-box" style="padding: 4rem; background: #fff; color: #1a1a1a; position: relative; overflow: hidden; border-radius: 0; border: 1px solid #ddd; box-shadow: 0 20px 50px rgba(0,0,0,0.1);">
<!-- Watermark -->
<div class="receipt-watermark" style="position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%) rotate(-45deg); font-size: 8rem; font-weight: 900; color: rgba(46, 213, 115, 0.08); pointer-events: none; z-index: 0; white-space: nowrap;">ENTERPRISE VERIFIED</div>
<div class="flex justify-between align-center mb-3" style="position: relative; z-index: 1; border-bottom: 2px solid #f0f0f0; padding-bottom: 2rem;">
<div>
<h1 class="fw-black text-gold" style="font-size: 2.5rem; margin: 0; filter: brightness(0.8);">AfgCars Enterprise</h1>
<p style="color: #666; font-weight: 600; letter-spacing: 1px; text-transform: uppercase; font-size: 0.8rem; margin-top: 0.5rem;">Secure Vehicle Transaction Module</p>
</div>
<div style="text-align: right;">
<h2 class="fw-black" style="margin: 0; color: #333;">OFFICIAL INVOICE</h2>
<p style="color: #888; font-weight: 700; margin-top: 0.5rem;">Invoice #: <span style="color: #333;"><?= htmlspecialchars($data['reference_number'] ?: 'INV-'.$data['id']) ?></span></p>
<p style="color: #888; font-weight: 700;">Date: <span style="color: #333;"><?= date('M d, Y', strtotime($data['created_at'])) ?></span></p>
<p style="color: #888; font-weight: 700;">Status: <span class="badge badge-primary"><?= strtoupper($data['status']) ?></span></p>
</div>
</div>
<div class="grid grid-2 mb-3" style="position: relative; z-index: 1; gap: 4rem;">
<div>
<h4 style="border-bottom: 1px solid #eee; padding-bottom: 0.5rem; margin-bottom: 1.5rem; color: #aaa; font-size: 0.75rem; text-transform: uppercase; letter-spacing: 2px; font-weight: 800;">Buyer Information</h4>
<p class="fw-black" style="font-size: 1.2rem; margin-bottom: 0.5rem; color: #333;"><?= htmlspecialchars($data['buyer_name']) ?></p>
<p style="margin-bottom: 0.3rem; color: #666; font-weight: 500;"><?= htmlspecialchars($data['buyer_email']) ?></p>
<p style="margin-bottom: 0.3rem; color: #666; font-weight: 500;"><?= htmlspecialchars($data['buyer_phone']) ?></p>
<p class="fw-black" style="color: var(--primary-color); margin-top: 1.5rem; filter: brightness(0.8);">Transaction ID: <br><span style="font-size: 0.8rem; font-family: monospace;"><?= htmlspecialchars($data['transaction_id']) ?></span></p>
</div>
<div>
<h4 style="border-bottom: 1px solid #eee; padding-bottom: 0.5rem; margin-bottom: 1.5rem; color: #aaa; font-size: 0.75rem; text-transform: uppercase; letter-spacing: 2px; font-weight: 800;">Seller Information</h4>
<p class="fw-black" style="font-size: 1.2rem; margin-bottom: 0.5rem; color: #333;"><?= htmlspecialchars($data['seller_name']) ?></p>
<p style="margin-bottom: 0.3rem; color: #666; font-weight: 500;">Status: Verified Premium Merchant</p>
<p style="margin-bottom: 0.3rem; color: #666; font-weight: 500;"><?= htmlspecialchars($data['seller_phone']) ?></p>
<p style="margin-bottom: 0.3rem; color: #666; font-weight: 500;"><?= htmlspecialchars($data['city']) ?>, Afghanistan</p>
</div>
</div>
<div class="mb-3" style="position: relative; z-index: 1;">
<table style="width: 100%; border-collapse: collapse; border: 1px solid #eee;">
<thead>
<tr style="background: #fcfcfc; text-align: left;">
<th style="padding: 1.2rem; border-bottom: 2px solid #eee; color: #333;">Item Description</th>
<th style="padding: 1.2rem; border-bottom: 2px solid #eee; text-align: right; color: #333;">Amount (USD)</th>
</tr>
</thead>
<tbody>
<tr>
<td style="padding: 1.5rem 1.2rem; border-bottom: 1px solid #eee;">
<div class="fw-black" style="font-size: 1.3rem; color: #333;"><?= htmlspecialchars($data['brand'] . ' ' . $data['model']) ?></div>
<div style="color: #888; font-size: 0.9rem; margin-top: 0.5rem; font-weight: 500;"><?= $data['year'] ?> Model Vehicle - Base Price</div>
</td>
<td style="padding: 1.5rem 1.2rem; border-bottom: 1px solid #eee; text-align: right; font-weight: 800; font-size: 1.3rem; color: #333;">$<?= number_format($data['base_price'], 2) ?></td>
</tr>
<tr>
<td style="padding: 1rem 1.2rem; border-bottom: 1px solid #eee;">
<div style="color: #666; font-weight: 600;">Marketplace Service Fee</div>
</td>
<td style="padding: 1rem 1.2rem; border-bottom: 1px solid #eee; text-align: right; font-weight: 700; color: #333;">$<?= number_format($data['marketplace_fee'], 2) ?></td>
</tr>
<tr>
<td style="padding: 1rem 1.2rem; border-bottom: 1px solid #eee;">
<div style="color: #666; font-weight: 600;">Automotive Sales Tax</div>
</td>
<td style="padding: 1rem 1.2rem; border-bottom: 1px solid #eee; text-align: right; font-weight: 700; color: #333;">$<?= number_format($data['tax'], 2) ?></td>
</tr>
</tbody>
<tfoot>
<tr style="background: #fafafa;">
<td style="padding: 2.5rem 1.2rem; text-align: right; font-weight: 700; font-size: 1.2rem; color: #666;">Total Payable Amount</td>
<td style="padding: 2.5rem 1.2rem; text-align: right; font-weight: 900; font-size: 2.2rem; color: var(--primary-color); filter: brightness(0.8);">$<?= number_format($data['total_amount'], 2) ?></td>
</tr>
</tfoot>
</table>
</div>
<div class="grid" style="grid-template-columns: 1fr 3fr; gap: 2rem; margin-top: 3rem; position: relative; z-index: 1;">
<div style="background: #f9f9f9; padding: 1.5rem; display: flex; align-items: center; justify-content: center; border: 1px solid #eee; border-radius: 10px;">
<!-- Placeholder for QR Code -->
<div style="text-align: center;">
<div style="width: 120px; height: 120px; background: #333; padding: 10px; border-radius: 5px; position: relative;">
<div style="width: 100%; height: 100%; background: #fff; border: 5px solid #333; display: grid; grid-template-columns: repeat(4, 1fr);">
<?php for($i=0;$i<16;$i++): ?>
<div style="background: <?= rand(0,1) ? '#000' : '#fff' ?>;"></div>
<?php endfor; ?>
</div>
</div>
<p style="font-size: 0.6rem; margin-top: 0.5rem; color: #888; font-weight: 700; text-transform: uppercase;">Scan to Verify</p>
</div>
</div>
<div style="display: flex; flex-direction: column; justify-content: center;">
<h5 style="margin: 0 0 0.5rem 0; color: #aaa; text-transform: uppercase; font-size: 0.7rem; letter-spacing: 1px; font-weight: 800;">SHA256 Verification Code</h5>
<p style="font-family: monospace; font-size: 0.75rem; word-break: break-all; color: #666; margin: 0; padding: 1rem; background: #f0f0f0; border-radius: 5px;"><?= $verificationHash ?></p>
</div>
</div>
<div class="mt-3 text-center" style="border-top: 2px dashed #eee; padding-top: 2.5rem; color: #aaa; font-size: 0.85rem; font-weight: 600; position: relative; z-index: 1; letter-spacing: 0.5px;">
<p style="margin-bottom: 0.5rem;">This official document is computer-generated and verified by AfgCars Enterprise Systems.</p>
<p style="color: #ccc;">ESCROW STATUS: <?= strtoupper($data['escrow_status'] ?: 'held_in_escrow') ?> • PAYMENT METHOD: <?= strtoupper($data['payment_method'] ?: 'bank_transfer') ?></p>
</div>
<!-- Status Badge -->
<div style="position: absolute; bottom: 120px; right: 60px; border: 6px double #2ed573; color: #2ed573; padding: 15px 30px; font-size: 2.5rem; font-weight: 900; transform: rotate(-15deg); border-radius: 12px; opacity: 0.6; pointer-events: none; text-transform: uppercase;"><?= $data['status'] ?></div>
</div>
<div class="mt-3 flex justify-center gap-1">
<button onclick="window.print()" class="btn btn-primary btn-lg">Print Documentation</button>
<a href="dashboard.php" class="btn btn-outline btn-lg">Return to Dashboard</a>
</div>
</div>
<style>
@media print {
nav, footer, .btn, .nav-actions { display: none !important; }
body { background: #fff !important; color: #000 !important; }
.container { max-width: 100% !important; padding: 0 !important; margin: 0 !important; }
.glass { border: none !important; box-shadow: none !important; background: #fff !important; border-radius: 0 !important; }
}
</style>
<?php require_once __DIR__ . '/includes/footer.php'; ?>

View File

@ -1,68 +0,0 @@
<?php
require_once __DIR__ . '/includes/header.php';
$error = '';
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$name = $_POST['name'] ?? '';
$email = $_POST['email'] ?? '';
$password = $_POST['password'] ?? '';
$pdo = db();
// Check if user exists
$stmt = $pdo->prepare("SELECT id FROM users WHERE email = ?");
$stmt->execute([$email]);
if ($stmt->fetch()) {
$error = "Email already registered.";
} else {
$hashed = password_hash($password, PASSWORD_DEFAULT);
$stmt = $pdo->prepare("INSERT INTO users (name, email, password) VALUES (?, ?, ?)");
if ($stmt->execute([$name, $email, $hashed])) {
$_SESSION['user_id'] = $pdo->lastInsertId();
$_SESSION['user_name'] = $name;
$_SESSION['user_email'] = $email;
$_SESSION['role'] = 'user';
header('Location: dashboard.php');
exit;
} else {
$error = "Registration failed. Please try again.";
}
}
}
?>
<div class="container" style="display: flex; justify-content: center; align-items: center; min-height: 80vh; padding: 4rem 0;">
<div class="box" style="width: 100%; max-width: 550px; padding: 4.5rem;">
<div class="text-center mb-3">
<h2 class="fw-black" style="font-size: 2.8rem; color: #fff; margin-bottom: 0.5rem; line-height: 1.1;">Join AfgCars</h2>
<p class="text-secondary fw-bold" style="font-size: 1.1rem;">Create your premium automotive portal today</p>
</div>
<?php if ($error): ?>
<div class="alert alert-error mb-2 text-center" style="justify-content: center;">
<?= $error ?>
</div>
<?php endif; ?>
<form method="POST">
<div class="form-group">
<label class="text-secondary fw-black mb-1" style="text-transform: uppercase; letter-spacing: 2px; font-size: 0.75rem;">Full Legal Name</label>
<input type="text" name="name" class="form-control" required placeholder="John Doe">
</div>
<div class="form-group">
<label class="text-secondary fw-black mb-1" style="text-transform: uppercase; letter-spacing: 2px; font-size: 0.75rem;">Email Address</label>
<input type="email" name="email" class="form-control" required placeholder="name@example.com">
</div>
<div class="form-group">
<label class="text-secondary fw-black mb-1" style="text-transform: uppercase; letter-spacing: 2px; font-size: 0.75rem;">Security Password</label>
<input type="password" name="password" class="form-control" required placeholder="••••••••">
</div>
<button type="submit" class="btn btn-primary w-full mt-2 fw-black" style="padding: 1.3rem; font-size: 1.1rem; letter-spacing: 1px;">CREATE PREMIUM ACCOUNT</button>
</form>
<p class="text-center mt-3 text-secondary fw-bold" style="font-size: 1rem;">
Already registered? <a href="login.php" class="text-gold" style="text-decoration: none; border-bottom: 1px solid var(--primary-color);">Sign in here</a>
</p>
</div>
</div>
<?php require_once __DIR__ . '/includes/footer.php'; ?>