| Server IP : 72.60.21.38 / Your IP : 216.73.217.140 Web Server : LiteSpeed System : Linux uk-fast-web1372.main-hosting.eu 4.18.0-553.121.1.lve.el8.x86_64 #1 SMP Thu Apr 30 16:40:41 UTC 2026 x86_64 User : u390967363 ( 390967363) PHP Version : 8.2.30 Disable Function : system, exec, shell_exec, passthru, mysql_list_dbs, ini_alter, dl, symlink, link, chgrp, leak, popen, apache_child_terminate, virtual, mb_send_mail MySQL : OFF | cURL : ON | WGET : ON | Perl : OFF | Python : OFF | Sudo : OFF | Pkexec : OFF Directory : /home/u390967363/domains/aibenproperties.com/public_html/app/ |
Upload File : |
<?php
if (session_status() === PHP_SESSION_NONE) { session_start(); }
header("Location: properties.php");
exit;
try {
if (function_exists('seedAibenPropertiesListings')) {
seedAibenPropertiesListings($pdo);
}
} catch (Throwable $eSeed) {}
// Filter Logic
$where_clauses = [];
$params = [];
$isDemo = (getSetting('demo_mode', 'off') === 'on') || (isset($_GET['demo']) && $_GET['demo'] === '1');
$companyId = getCurrentCompanyId();
if ($companyId) {
$where_clauses[] = "company_id = ?";
$params[] = $companyId;
}
if (isset($_GET['search']) && !empty($_GET['search'])) {
$where_clauses[] = "(name LIKE ? OR location LIKE ?)";
$params[] = "%" . $_GET['search'] . "%";
$params[] = "%" . $_GET['search'] . "%";
}
if (isset($_GET['status']) && !empty($_GET['status'])) {
$where_clauses[] = "status = ?";
$params[] = $_GET['status'];
}
$where_sql = "";
if (!empty($where_clauses)) {
$where_sql = "WHERE " . implode(" AND ", $where_clauses);
}
$perPage = isset($_GET['per_page']) ? max(1, (int)$_GET['per_page']) : 9;
$page = isset($_GET['page']) ? max(1, (int)$_GET['page']) : 1;
$offset = ($page - 1) * $perPage;
try {
$countStmt = $pdo->prepare("SELECT COUNT(*) FROM (SELECT MAX(id) AS id FROM estates $where_sql GROUP BY LOWER(TRIM(name))) t");
$countStmt->execute($params);
$totalRows = (int)$countStmt->fetchColumn();
$stmt = $pdo->prepare("SELECT e.* FROM estates e JOIN (SELECT MAX(id) AS id FROM estates $where_sql GROUP BY LOWER(TRIM(name))) t ON t.id = e.id ORDER BY e.created_at DESC LIMIT ? OFFSET ?");
$execParams = array_merge($params, [$perPage, $offset]);
$stmt->execute($execParams);
$estates = $stmt->fetchAll();
$totalPages = (int)ceil($totalRows / $perPage);
} catch (Exception $e) {
$estates = [];
$totalRows = 0;
$totalPages = 1;
$error = "Error fetching estates: " . $e->getMessage();
}
if ($isDemo) {
$estates = [
['id'=>101,'name'=>'Aiben Gardens Phase 1','location'=>'Lekki, Lagos','status'=>'active','description'=>'Premium residential estate with modern amenities.','image'=>'https://picsum.photos/seed/estate1/800/400'],
['id'=>102,'name'=>'Skyline Apartments','location'=>'Victoria Island','status'=>'active','description'=>'Luxury high-rise apartments with ocean views.','image'=>'https://picsum.photos/seed/estate2/800/400'],
['id'=>103,'name'=>'Cedar Park Villas','location'=>'Ajah','status'=>'inactive','description'=>'Family-friendly gated community.','image'=>'https://picsum.photos/seed/estate3/800/400'],
['id'=>104,'name'=>'Harborview Residences','location'=>'Ikoyi','status'=>'sold_out','description'=>'Exclusive residences, fully sold.','image'=>'https://picsum.photos/seed/estate4/800/400'],
['id'=>105,'name'=>'Palm Crest Court','location'=>'Ikeja','status'=>'active','description'=>'Contemporary living close to business district.','image'=>'https://picsum.photos/seed/estate5/800/400'],
['id'=>106,'name'=>'Willow Gardens','location'=>'Yaba','status'=>'inactive','description'=>'Upcoming smart home community.','image'=>'https://picsum.photos/seed/estate6/800/400'],
['id'=>107,'name'=>'Summit Heights','location'=>'Surulere','status'=>'active','description'=>'Affordable luxury apartments.','image'=>'https://picsum.photos/seed/estate7/800/400'],
['id'=>108,'name'=>'Lagoon View Homes','location'=>'Lekki Phase 2','status'=>'reserved','description'=>'Waterfront homes with premium finishes.','image'=>'https://picsum.photos/seed/estate8/800/400'],
['id'=>109,'name'=>'Marina Bay Towers','location'=>'Eko Atlantic','status'=>'active','description'=>'Iconic towers with executive amenities.','image'=>'https://picsum.photos/seed/estate9/800/400'],
];
$totalRows = count($estates);
$totalPages = 1;
}
?>
<div class="container-fluid px-4 py-4">
<!-- PAGE HEADER -->
<div class="d-flex flex-column flex-md-row justify-content-between align-items-md-center mb-4 gap-3">
<div>
<h1 class="h3 fw-bold text-white mb-1">Estate Projects</h1>
<nav aria-label="breadcrumb">
<ol class="breadcrumb mb-0 text-muted small">
<li class="breadcrumb-item"><a href="dashboard.php" class="text-decoration-none text-muted">Home</a></li>
<li class="breadcrumb-item active" aria-current="page">Estates</li>
</ol>
</nav>
</div>
<div class="d-flex flex-wrap gap-2 align-self-start align-self-md-auto">
<button class="btn btn-white border shadow-sm text-dark" type="button" data-bs-toggle="collapse" data-bs-target="#filterPanel">
<i class="fa-solid fa-filter me-2"></i>Filters
</button>
<?php if (!isRestrictedMode()): ?>
<a href="estate-add.php" class="btn btn-primary shadow-sm hover-elevate hover-shimmer">
<i class="fa-solid fa-plus me-2"></i>Add New Estate
</a>
<?php endif; ?>
<ul class="nav nav-pills ms-md-2" id="estateStatusFilters">
<li class="nav-item"><a class="nav-link active" href="#" data-filter="all">All</a></li>
<li class="nav-item"><a class="nav-link" href="#" data-filter="active">Active</a></li>
<li class="nav-item"><a class="nav-link" href="#" data-filter="inactive">Inactive</a></li>
<li class="nav-item"><a class="nav-link" href="#" data-filter="sold_out">Sold Out</a></li>
</ul>
</div>
</div>
<?php if (isset($error)): ?>
<div class="alert alert-danger"><?= $error ?></div>
<?php endif; ?>
<?php if ($isDemo): ?>
<div class="alert alert-info border-0 shadow-sm"><i class="fa-solid fa-flask me-2"></i>Demo content active. Use <span class="badge bg-light text-dark border">?demo=1</span> in URL to preview.</div>
<?php endif; ?>
<!-- FILTER PANEL -->
<div class="collapse mb-4" id="filterPanel">
<div class="card border-0 shadow-sm">
<div class="card-body">
<form method="GET" class="row g-3">
<div class="col-md-4">
<label class="form-label small text-muted fw-bold">Search</label>
<div class="input-group">
<span class="input-group-text bg-light border-end-0"><i class="fa-solid fa-magnifying-glass text-muted"></i></span>
<input type="text" name="search" class="form-control border-start-0 bg-light" placeholder="Name, Location..." value="<?= htmlspecialchars($_GET['search'] ?? '') ?>">
</div>
</div>
<div class="col-md-3">
<label class="form-label small text-muted fw-bold">Status</label>
<select name="status" class="form-select bg-light">
<option value="">All Statuses</option>
<option value="active" <?= (isset($_GET['status']) && $_GET['status'] == 'active') ? 'selected' : '' ?>>Active</option>
<option value="inactive" <?= (isset($_GET['status']) && $_GET['status'] == 'inactive') ? 'selected' : '' ?>>Inactive</option>
<option value="sold_out" <?= (isset($_GET['status']) && $_GET['status'] == 'sold_out') ? 'selected' : '' ?>>Sold Out</option>
</select>
</div>
<div class="col-md-2 d-flex align-items-end">
<button type="submit" class="btn btn-primary w-100">Apply Filters</button>
</div>
<div class="col-md-2 d-flex align-items-end">
<a href="estates.php" class="btn btn-light w-100">Reset</a>
</div>
</form>
</div>
</div>
</div>
<!-- ESTATES GRID -->
<div class="row g-4 animate-stagger">
<?php if (empty($estates)): ?>
<div class="col-12">
<div class="text-center py-5 text-muted">
<i class="fa-solid fa-city fa-3x mb-3 opacity-25"></i>
<p class="mb-0">No estate projects found.</p>
</div>
</div>
<?php else: ?>
<?php foreach ($estates as $estate): ?>
<div class="col-12 col-md-6 col-lg-4" data-status="<?= htmlspecialchars($estate['status']) ?>">
<div class="card h-100 border-0 shadow-sm animate-card hover-elevate gold-outline">
<div class="position-relative">
<?php
$imgSrc = $estate['image'] ?? '';
if (!empty($imgSrc)) {
$imgSrc = str_replace('\\', '/', $imgSrc);
if (preg_match('#^[A-Za-z]:/#', $imgSrc)) {
$imgSrc = 'uploads/estates/' . basename($imgSrc);
}
}
?>
<?php if (!empty($imgSrc)): ?>
<img src="<?= htmlspecialchars($imgSrc) ?>" class="card-img-top" alt="<?= htmlspecialchars($estate['name']) ?>" style="height: 200px; object-fit: cover;">
<?php else: ?>
<div class="bg-light d-flex align-items-center justify-content-center text-muted" style="height: 200px;">
<i class="fa-solid fa-image fa-2x opacity-25"></i>
</div>
<?php endif; ?>
<span class="position-absolute top-0 end-0 m-3 badge bg-white text-dark shadow-sm">
<?= ucfirst($estate['status']) ?>
</span>
</div>
<div class="card-body">
<h5 class="fw-bold text-dark mb-1"><?= htmlspecialchars($estate['name']) ?></h5>
<p class="text-muted small mb-3"><i class="fa-solid fa-location-dot me-1"></i> <?= htmlspecialchars($estate['location']) ?></p>
<p class="card-text text-muted small mb-3">
<?= mb_strimwidth(strip_tags($estate['description']), 0, 100, "...") ?>
</p>
<div class="d-flex justify-content-between align-items-center pt-3 border-top">
<div>
<!-- Placeholder for phase count / unit count -->
<span class="badge bg-light text-dark border me-1"><i class="fa-solid fa-layer-group me-1"></i> Phases</span>
</div>
<div>
<?php if (!isRestrictedMode() && !$isDemo): ?>
<a href="estate-edit.php?id=<?= $estate['id'] ?>" class="btn btn-sm btn-light border hover-elevate">Edit</a>
<?php endif; ?>
<?php if ($isDemo): ?>
<a href="estate-details.php?demo=1" class="btn btn-sm btn-primary">Manage</a>
<?php else: ?>
<a href="estate-details.php?id=<?= $estate['id'] ?>" class="btn btn-sm btn-primary">Manage</a>
<?php endif; ?>
</div>
</div>
</div>
</div>
</div>
<?php endforeach; ?>
<?php endif; ?>
</div>
<?php if (!empty($estates) && $totalPages > 1): ?>
<div class="d-flex justify-content-center mt-4">
<nav aria-label="Pagination">
<ul class="pagination pagination-sm">
<?php
$qs = $_GET;
$qs['per_page'] = $perPage;
?>
<li class="page-item <?= $page <= 1 ? 'disabled' : '' ?>">
<a class="page-link" href="?<?= http_build_query(array_merge($qs, ['page' => max(1, $page - 1)])) ?>">Prev</a>
</li>
<?php for ($p = 1; $p <= $totalPages; $p++): ?>
<li class="page-item <?= $p == $page ? 'active' : '' ?>">
<a class="page-link" href="?<?= http_build_query(array_merge($qs, ['page' => $p])) ?>"><?= $p ?></a>
</li>
<?php endfor; ?>
<li class="page-item <?= $page >= $totalPages ? 'disabled' : '' ?>">
<a class="page-link" href="?<?= http_build_query(array_merge($qs, ['page' => min($totalPages, $page + 1)])) ?>">Next</a>
</li>
</ul>
</nav>
</div>
<?php endif; ?>
</div>
<?php require 'includes/footer.php'; ?>
<script>
document.addEventListener('DOMContentLoaded', function() {
var searchInput = document.querySelector('input[name="search"]');
var cols = document.querySelectorAll('.row.g-4 [data-status]');
var filterNav = document.getElementById('estateStatusFilters');
var filter = 'all';
function applyFilters() {
var q = (searchInput && searchInput.value ? searchInput.value.toLowerCase() : '');
cols.forEach(function(col) {
var text = col.textContent.toLowerCase();
var status = col.getAttribute('data-status') || '';
var matchStatus = filter === 'all' || status === filter;
var matchSearch = !q || text.indexOf(q) !== -1;
col.style.display = (matchStatus && matchSearch) ? '' : 'none';
});
}
if (searchInput) {
searchInput.addEventListener('input', applyFilters);
}
if (filterNav) {
filterNav.querySelectorAll('.nav-link').forEach(function(link) {
link.addEventListener('click', function(e) {
e.preventDefault();
filterNav.querySelectorAll('.nav-link').forEach(function(l) { l.classList.remove('active'); });
this.classList.add('active');
filter = this.getAttribute('data-filter') || 'all';
applyFilters();
});
});
}
});
</script>
<script>
document.addEventListener('DOMContentLoaded', function() {
var searchInput = document.querySelector('input[name="search"]');
var cards = document.querySelectorAll('.row.g-4 .card');
function filterCards() {
var q = (searchInput && searchInput.value ? searchInput.value.toLowerCase() : '');
cards.forEach(function(card) {
var text = card.textContent.toLowerCase();
card.parentElement.style.display = (!q || text.indexOf(q) !== -1) ? '' : 'none';
});
}
if (searchInput) {
searchInput.addEventListener('input', filterCards);
}
});
</script>