<?php
include 'includes/db.php';
include 'includes/header.php';
// --- Filtering Logic ---
$sql = "SELECT c.id, c.name, c.brand, c.model, c.year, c.category, c.description, c.video_url, c.created_at,
b.logo as brand_logo,
MIN(t.price) as min_price,
MAX(t.price) as max_price,
GROUP_CONCAT(DISTINCT t.fuel_type SEPARATOR ' / ') as fuel_type,
GROUP_CONCAT(DISTINCT t.car_condition SEPARATOR ' / ') as car_condition
FROM cars c
LEFT JOIN brands b ON c.brand = b.name
LEFT JOIN car_trims t ON c.id = t.car_id";
$conditions = []; // No default conditions
$params = [];
$types = '';
// Brand filter
if (!empty($_GET['brand']) && trim($_GET['brand']) !== '') {
$conditions[] = "c.brand = ?";
$params[] = trim($_GET['brand']);
$types .= 's';
}
// Category filter
if (!empty($_GET['category']) && trim($_GET['category']) !== '') {
$conditions[] = "c.category = ?";
$params[] = trim($_GET['category']);
$types .= 's';
}
// Fuel type filter
if (!empty($_GET['fuel_type']) && trim($_GET['fuel_type']) !== '') {
$conditions[] = "t.fuel_type = ?";
$params[] = trim($_GET['fuel_type']);
$types .= 's';
}
// Car condition filter
if (!empty($_GET['car_condition']) && trim($_GET['car_condition']) !== '') {
$conditions[] = "t.car_condition = ?";
$params[] = trim($_GET['car_condition']);
$types .= 's';
}
// Min price filter
if (!empty($_GET['min_price']) && trim($_GET['min_price']) !== '') {
$conditions[] = "t.price >= ?";
$params[] = (float)$_GET['min_price'];
$types .= 'd';
}
// Max price filter
if (!empty($_GET['max_price']) && trim($_GET['max_price']) !== '') {
$conditions[] = "t.price <= ?";
$params[] = (float)$_GET['max_price'];
$types .= 'd';
}
if (count($conditions) > 0) {
$sql .= " WHERE " . implode(' AND ', $conditions);
}
$sql .= " GROUP BY c.id, c.name, c.brand, c.model, c.year, c.category, c.description, c.video_url, c.created_at, b.logo";
$sql .= " ORDER BY c.created_at DESC";
$stmt = $conn->prepare($sql);
if ($types) {
$stmt->bind_param($types, ...$params);
}
$stmt->execute();
if ($stmt->error) {
echo "<div class='alert alert-danger'>Database Error: " . $stmt->error . "</div>";
}
$cars_result = $stmt->get_result();
// --- Fetch values for filters from the new tables ---
$brands = $conn->query("SELECT name, logo FROM brands ORDER BY name");
$categories = $conn->query("SELECT name FROM categories ORDER BY name");
$fuel_types = $conn->query("SELECT DISTINCT fuel_type FROM car_trims WHERE fuel_type IS NOT NULL AND fuel_type != '' ORDER BY fuel_type");
$car_conditions = $conn->query("SELECT DISTINCT car_condition FROM car_trims WHERE car_condition IS NOT NULL AND car_condition != '' ORDER BY car_condition");
?>
<main class="container my-5 pt-5">
<div class="row">
<!-- Filters Sidebar -->
<aside class="col-lg-3">
<div class="glass-card p-4 sticky-top" style="top: 100px;">
<h4><i class="fas fa-filter me-2"></i>فلترة البحث</h4>
<hr>
<form id="filter-form">
<!-- Brand Filter -->
<div class="mb-3">
<label for="brand" class="form-label">الماركة</label>
<select class="form-select filter-input" name="brand" id="brand">
<option value="">كل الماركات</option>
<?php while($brand_row = $brands->fetch_assoc()): ?>
<option value="<?= htmlspecialchars($brand_row['name']) ?>"
data-logo="<?= htmlspecialchars($brand_row['logo']) ?>"
<?= (isset($_GET['brand']) && $_GET['brand'] == $brand_row['name']) ? 'selected' : '' ?>>
<?= htmlspecialchars($brand_row['name']) ?>
</option>
<?php endwhile; ?>
</select>
<div id="brand-logo-preview" class="mt-2" style="display: none;">
<div class="d-flex align-items-center">
<img id="brand-logo-img" src="" alt="Brand Logo"
style="width: 40px; height: 40px; object-fit: contain; border-radius: 5px; background: white; padding: 2px; margin-left: 8px;">
<small class="text-muted" id="brand-name-display"></small>
</div>
</div>
</div>
<!-- Category Filter -->
<div class="mb-3">
<label for="category" class="form-label">الفئة</label>
<select class="form-select filter-input" name="category" id="category">
<option value="">كل الفئات</option>
<?php while($category_row = $categories->fetch_assoc()): ?>
<option value="<?= htmlspecialchars($category_row['name']) ?>" <?= (isset($_GET['category']) && $_GET['category'] == $category_row['name']) ? 'selected' : '' ?>><?= htmlspecialchars($category_row['name']) ?></option>
<?php endwhile; ?>
</select>
</div>
<!-- Fuel Type Filter -->
<div class="mb-3">
<label for="fuel_type" class="form-label">نوع الوقود</label>
<select class="form-select filter-input" name="fuel_type" id="fuel_type">
<option value="">كل أنواع الوقود</option>
<?php while($fuel_row = $fuel_types->fetch_assoc()): ?>
<option value="<?= htmlspecialchars($fuel_row['fuel_type']) ?>" <?= (isset($_GET['fuel_type']) && $_GET['fuel_type'] == $fuel_row['fuel_type']) ? 'selected' : '' ?>><?= htmlspecialchars($fuel_row['fuel_type']) ?></option>
<?php endwhile; ?>
</select>
</div>
<!-- Car Condition Filter -->
<div class="mb-3">
<label for="car_condition" class="form-label">حالة السيارة</label>
<select class="form-select filter-input" name="car_condition" id="car_condition">
<option value="">كل الحالات</option>
<?php while($condition_row = $car_conditions->fetch_assoc()): ?>
<option value="<?= htmlspecialchars($condition_row['car_condition']) ?>" <?= (isset($_GET['car_condition']) && $_GET['car_condition'] == $condition_row['car_condition']) ? 'selected' : '' ?>><?= htmlspecialchars($condition_row['car_condition']) ?></option>
<?php endwhile; ?>
</select>
</div>
<!-- Price Filter -->
<div class="mb-3">
<label class="form-label">السعر</label>
<div class="row">
<div class="col-6">
<input type="number" class="form-control filter-input" name="min_price" id="min_price" placeholder="أقل سعر" value="<?= htmlspecialchars($_GET['min_price'] ?? '') ?>">
</div>
<div class="col-6">
<input type="number" class="form-control filter-input" name="max_price" id="max_price" placeholder="أعلى سعر" value="<?= htmlspecialchars($_GET['max_price'] ?? '') ?>">
</div>
</div>
</div>
<div class="d-grid gap-2">
<button type="button" id="reset-filters" class="btn btn-outline-light">إعادة تعيين</button>
</div>
</form>
</div>
</aside>
<!-- Cars Grid -->
<section class="col-lg-9">
<h2 class="mb-4">السيارات المتوفرة (<span id="cars-count"><?= $cars_result->num_rows ?></span>)</h2>
<div id="loading-spinner" class="text-center" style="display: none;">
<div class="spinner-border text-danger" role="status">
<span class="visually-hidden">جاري التحميل...</span>
</div>
</div>
<div id="cars-container" class="row row-cols-1 row-cols-md-2 row-cols-xl-3 g-4">
<?php if ($cars_result->num_rows > 0): ?>
<?php while($car = $cars_result->fetch_assoc()): ?>
<div class="col" data-aos="fade-up">
<div class="card h-100 text-white car-card">
<?php
// Get primary image from car_images table or fallback to old image field
$primary_image_query = $conn->prepare("SELECT image_name FROM car_images WHERE car_id = ? AND is_primary = 1 LIMIT 1");
$primary_image_query->bind_param("i", $car['id']);
$primary_image_query->execute();
$primary_result = $primary_image_query->get_result();
if ($primary_result->num_rows > 0) {
$primary_image = $primary_result->fetch_assoc()['image_name'];
$image_src = 'uploads/cars/' . htmlspecialchars($primary_image);
} else {
$image_src = !empty($car['image']) ? 'uploads/cars/' . htmlspecialchars($car['image']) : 'https://via.placeholder.com/400x300';
}
$primary_image_query->close();
?>
<img src="<?= $image_src ?>" class="card-img-top" alt="<?= htmlspecialchars($car['name']) ?>"
style="height: 250px; object-fit: cover;">
<div class="card-body d-flex flex-column">
<h5 class="card-title"><?= htmlspecialchars($car['name']) ?></h5>
<div class="d-flex align-items-center mb-2">
<?php if (!empty($car['brand_logo'])): ?>
<img src="uploads/brands/<?= htmlspecialchars($car['brand_logo']) ?>"
alt="<?= htmlspecialchars($car['brand']) ?>"
style="width: 35px; height: 35px; object-fit: contain; margin-left: 10px; border-radius: 5px; background: white; padding: 2px;">
<?php endif; ?>
<p class="card-text text-muted mb-0">
<strong><?= htmlspecialchars($car['brand']) ?></strong> - <?= htmlspecialchars($car['model']) ?>
</p>
</div>
<!-- Category Badge -->
<?php if (!empty($car['category'])): ?>
<div class="mb-2">
<span class="badge bg-primary"><i class="fas fa-tag me-1"></i><?= htmlspecialchars($car['category']) ?></span>
</div>
<?php endif; ?>
<div class="d-flex justify-content-between align-items-center mb-2">
<?php if (!empty($car['fuel_type'])): ?>
<small class="text-info"><i class="fas fa-gas-pump me-1"></i><?= htmlspecialchars($car['fuel_type']) ?></small>
<?php endif; ?>
<?php if (!empty($car['car_condition'])): ?>
<small class="text-warning"><i class="fas fa-star me-1"></i><?= htmlspecialchars($car['car_condition']) ?></small>
<?php endif; ?>
</div>
<h4 class="card-price mt-auto">
<?php
if (empty($car['min_price'])) {
echo 'غير متوفر';
} elseif ($car['min_price'] == $car['max_price']) {
echo number_format($car['min_price']) . ' جنيه';
} else {
echo number_format($car['min_price']) . ' - ' . number_format($car['max_price']) . ' جنيه';
}
?>
</h4>
<a href="car_details.php?id=<?= $car['id'] ?>" class="btn btn-danger stretched-link">عرض التفاصيل</a>
</div>
</div>
</div>
<?php endwhile; ?>
<?php else: ?>
<div class="col-12">
<div class="glass-card p-5 text-center">
<h3>لا توجد سيارات معروضة حالياً</h3>
<p>لم يتم العثور على سيارات تطابق الفلاتر الحالية. حاول تغيير شروط الفلترة أو إعادة تعيينها لعرض جميع السيارات.</p>
<a href="cars.php" class="btn btn-danger mt-3">عرض كل السيارات</a>
</div>
</div>
<?php endif; ?>
</div>
</section>
</div>
</main>
<style>
/* تحسينات للفلتر اللحظي */
#cars-container {
transition: opacity 0.3s ease;
}
#loading-spinner {
padding: 2rem 0;
}
.filter-input {
transition: border-color 0.2s ease;
}
.filter-input:focus {
border-color: #dc3545;
box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.25);
}
/* تحسين مظهر البطاقات أثناء التحميل */
.car-card {
transition: transform 0.2s ease, box-shadow 0.2s ease;
}
.car-card:hover {
transform: translateY(-5px);
box-shadow: 0 8px 25px rgba(0,0,0,0.3);
}
/* تحسين مظهر الفلتر */
.glass-card {
backdrop-filter: blur(10px);
background: rgba(255, 255, 255, 0.1);
border: 1px solid rgba(255, 255, 255, 0.2);
}
/* تحسين مظهر الأزرار */
#reset-filters {
transition: all 0.3s ease;
}
#reset-filters:hover {
background-color: rgba(255, 255, 255, 0.1);
border-color: #fff;
}
</style>
<script>
document.addEventListener('DOMContentLoaded', function() {
// Brand logo preview functionality
const brandSelect = document.getElementById('brand');
const logoPreview = document.getElementById('brand-logo-preview');
const logoImg = document.getElementById('brand-logo-img');
const brandNameDisplay = document.getElementById('brand-name-display');
// Show logo on page load if brand is already selected
if (brandSelect.value) {
const selectedOption = brandSelect.options[brandSelect.selectedIndex];
const logoPath = selectedOption.getAttribute('data-logo');
if (logoPath) {
logoImg.src = 'uploads/brands/' + logoPath;
brandNameDisplay.textContent = brandSelect.value;
logoPreview.style.display = 'block';
}
}
// Show logo when brand is changed
brandSelect.addEventListener('change', function() {
const selectedOption = this.options[this.selectedIndex];
const logoPath = selectedOption.getAttribute('data-logo');
if (logoPath && this.value) {
logoImg.src = 'uploads/brands/' + logoPath;
brandNameDisplay.textContent = this.value;
logoPreview.style.display = 'block';
} else {
logoPreview.style.display = 'none';
}
});
// Real-time filtering functionality
const filterInputs = document.querySelectorAll('.filter-input');
const carsContainer = document.getElementById('cars-container');
const carsCount = document.getElementById('cars-count');
const loadingSpinner = document.getElementById('loading-spinner');
const resetButton = document.getElementById('reset-filters');
let filterTimeout;
// Function to apply filters
function applyFilters() {
// Show loading spinner
loadingSpinner.style.display = 'block';
carsContainer.style.opacity = '0.5';
// Collect filter values
const params = new URLSearchParams();
filterInputs.forEach(input => {
const value = input.value.trim();
if (value !== '' && value !== null && value !== undefined) {
params.append(input.name, value);
}
});
// Try AJAX first, fallback to page reload if it fails
fetch('ajax_filter_cars.php?' + params.toString())
.then(response => {
if (!response.ok) {
throw new Error('AJAX endpoint not available');
}
return response.text();
})
.then(text => {
try {
const data = JSON.parse(text);
if (data.error) {
throw new Error(data.error);
}
// Update cars container
carsContainer.innerHTML = data.html;
carsCount.textContent = data.count;
// Hide loading spinner
loadingSpinner.style.display = 'none';
carsContainer.style.opacity = '1';
// Update URL without page reload
const newUrl = params.toString() ?
window.location.pathname + '?' + params.toString() :
window.location.pathname;
window.history.pushState({}, '', newUrl);
// Re-initialize AOS animations if available
if (typeof AOS !== 'undefined') {
AOS.refresh();
}
} catch (jsonError) {
console.error('JSON Parse Error:', jsonError);
throw new Error('Invalid response from server');
}
})
.catch(error => {
console.error('AJAX failed, falling back to page reload:', error);
// Fallback: redirect to page with filters
const newUrl = params.toString() ?
window.location.pathname + '?' + params.toString() :
window.location.pathname;
window.location.href = newUrl;
});
}
// Add event listeners to all filter inputs
filterInputs.forEach(input => {
if (input.type === 'number') {
// For number inputs, use debouncing to avoid too many requests
input.addEventListener('input', function() {
clearTimeout(filterTimeout);
filterTimeout = setTimeout(applyFilters, 500); // Wait 500ms after user stops typing
});
} else {
// For select inputs, apply filter immediately
input.addEventListener('change', applyFilters);
}
});
// Reset filters functionality
resetButton.addEventListener('click', function() {
filterInputs.forEach(input => {
input.value = '';
});
// Hide brand logo preview
logoPreview.style.display = 'none';
// Apply filters (which will show all cars)
applyFilters();
});
// Add visual feedback for active filters
function updateFilterStatus() {
let hasActiveFilters = false;
filterInputs.forEach(input => {
if (input.value.trim() !== '') {
hasActiveFilters = true;
input.classList.add('border-danger');
} else {
input.classList.remove('border-danger');
}
});
// Update reset button visibility
if (hasActiveFilters) {
resetButton.classList.remove('btn-outline-light');
resetButton.classList.add('btn-outline-danger');
resetButton.innerHTML = '<i class="fas fa-times me-2"></i>إعادة تعيين';
} else {
resetButton.classList.remove('btn-outline-danger');
resetButton.classList.add('btn-outline-light');
resetButton.innerHTML = 'إعادة تعيين';
}
}
// Update filter status on input change
filterInputs.forEach(input => {
input.addEventListener('input', updateFilterStatus);
input.addEventListener('change', updateFilterStatus);
});
// Initial filter status update
updateFilterStatus();
});
</script>
<?php include 'includes/footer.php'; ?>