403Webshell
Server IP : 72.60.21.38  /  Your IP : 216.73.216.164
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 :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ Back ]     

Current File : /home/u390967363/domains/aibenproperties.com/public_html/app/estate-details.php
<?php
require 'includes/header.php';
require_once 'includes/db.php';
require_once 'includes/functions.php';

$__plots_fallback_defined = function_exists('ensurePlotsTable');
if (!$__plots_fallback_defined) {
    function ensurePlotsTable() {
        global $pdo;
        try {
            $pdo->exec("CREATE TABLE IF NOT EXISTS plots (
                id INT AUTO_INCREMENT PRIMARY KEY,
                estate_id INT NOT NULL,
                block VARCHAR(50) NOT NULL,
                plot_number VARCHAR(50) NOT NULL,
                size_sqm DECIMAL(12,2) NOT NULL,
                status ENUM('available','reserved','allocated','locked','revoked') DEFAULT 'available',
                assigned_allocation_id INT NULL,
                company_id INT NULL,
                created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
                updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
                UNIQUE KEY uniq_plot (estate_id, block, plot_number)
            )");
        } catch (Exception $e) {}
    }
}

$isDemo = (getSetting('demo_mode', 'off') === 'on') || (isset($_GET['demo']) && $_GET['demo'] === '1');
$id = $_GET['id'] ?? null;
if (!$id && !$isDemo) {
    header('Location: estates.php');
    exit;
}

$companyId = getCurrentCompanyId();
$companyFilter = $companyId ? "AND company_id = $companyId" : "";

if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action']) && !$isDemo) {
    $estateId = (int)($id ?? 0);
    $role = strtolower((string)($_SESSION['user_role'] ?? 'guest'));
    if (!in_array($role, ['admin','super_admin','estate_manager'])) {
        header("Location: estate-details.php?id=" . $estateId . "&msg=forbidden");
        exit;
    }
    $action = $_POST['action'];
    if ($action === 'delete_estate') {
        try {
            deleteEstateSafely($estateId);
            header("Location: properties.php?notice=" . urlencode('Estate deleted successfully.') . "&type=success");
            exit;
        } catch (Throwable $e) {
            header("Location: estate-details.php?id=" . $estateId . "&msg=" . urlencode($e->getMessage()));
            exit;
        }
    } elseif ($action === 'plots_generate') {
        $block = trim($_POST['block'] ?? '');
        $start = (int)($_POST['start_no'] ?? 0);
        $end = (int)($_POST['end_no'] ?? 0);
        $size = (float)($_POST['size_sqm'] ?? 0);
        if ($block !== '' && $start > 0 && $end > 0 && $size > 0) {
            try { bulkGeneratePlots($estateId, $block, $start, $end, $size); } catch (Exception $e) {}
            header("Location: estate-details.php?id=" . $estateId . "&msg=plots_generated");
            exit;
        } else {
            header("Location: estate-details.php?id=" . $estateId . "&msg=invalid_input");
            exit;
        }
    } elseif ($action === 'plots_add_single') {
        $block = trim($_POST['block'] ?? '');
        $plotNo = trim($_POST['plot_no'] ?? '');
        $size = (float)($_POST['size_sqm'] ?? 0);
        if ($block !== '' && $plotNo !== '' && $size > 0) {
            try {
                ensurePlotsTable();
                $cid = getCurrentCompanyId();
                $st = $pdo->prepare("INSERT IGNORE INTO plots (estate_id, block, plot_number, size_sqm, status, company_id) VALUES (?, ?, ?, ?, 'available', ?)");
                $st->execute([$estateId, $block, $plotNo, $size, $cid]);
            } catch (Exception $e) {}
            header("Location: estate-details.php?id=" . $estateId . "&msg=plot_added");
            exit;
        } else {
            header("Location: estate-details.php?id=" . $estateId . "&msg=invalid_input");
            exit;
        }
    }
}

if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['save_payment_settings']) && !$isDemo) {
    $role = $_SESSION['user_role'] ?? 'guest';
    $allowed = in_array(strtolower((string)$role), ['admin','super_admin','estate_manager']);
    if ($allowed) {
        $estateId = (int)($_POST['estate_id'] ?? 0);
        if ($estateId > 0) {
            $cur = getEstateConfig($estateId);
            $new = $cur;
            $new['installment_allowed'] = isset($_POST['installment_allowed']) ? 1 : 0;
            $new['excavation_fee_enabled'] = isset($_POST['excavation_fee_enabled']) ? 1 : 0;
            $new['infrastructure_fee'] = isset($_POST['infrastructure_fee']) ? (float)$_POST['infrastructure_fee'] : 0.0;
            $new['late_penalty_percent'] = isset($_POST['late_penalty_percent']) ? (float)$_POST['late_penalty_percent'] : ($new['late_penalty_percent'] ?? 0.0);
            $plans = [];
            foreach (['plan3','plan6','plan8'] as $k) { if (isset($_POST[$k])) { $plans[] = (int)substr($k,4); } }
            $new['default_plans'] = $plans;
            $new['custom_months_default'] = isset($_POST['custom_months_default']) && ctype_digit($_POST['custom_months_default']) ? (int)$_POST['custom_months_default'] : ($new['custom_months_default'] ?? 0);
            setEstateConfig($estateId, $new);
            auditLogDetailed('estate_config', $estateId, $cur, $new, 'Payment settings updated');
            header("Location: estate-details.php?id=" . $estateId . "&msg=updated");
            exit;
        }
    }
}

if ($isDemo) {
    $estate = [
        'id' => 999,
        'name' => 'Aiben Gardens Showcase',
        'location' => 'Lekki, Lagos',
        'status' => 'active',
        'description' => 'Showcase estate demonstrating premium UI and filtering.',
        'image' => 'https://picsum.photos/seed/demoestate/1200/600'
    ];
    $properties = [
        ['id'=>3001,'title'=>'Showcase Unit A','address'=>'Block A','status'=>'available','price'=>45000000],
        ['id'=>3002,'title'=>'Showcase Unit B','address'=>'Block B','status'=>'reserved','price'=>52000000],
        ['id'=>3003,'title'=>'Showcase Penthouse','address'=>'Tower 1','status'=>'sold','price'=>150000000],
        ['id'=>3004,'title'=>'Showcase Villa','address'=>'Villa Row','status'=>'available','price'=>80000000],
        ['id'=>3005,'title'=>'Showcase Suite','address'=>'Residences','status'=>'sold','price'=>110000000],
        ['id'=>3006,'title'=>'Showcase Townhouse','address'=>'Court','status'=>'reserved','price'=>60000000],
    ];
    $total_units = count($properties);
    $status_counts = ['available'=>3,'reserved'=>2,'sold'=>2];
    $available = $status_counts['available'];
    $reserved = $status_counts['reserved'];
    $sold = $status_counts['sold'];
    $sold_percentage = $total_units > 0 ? round(($sold / $total_units) * 100) : 0;
    $total_value = array_sum(array_map(function($p){ return $p['price']; }, $properties));
    $sold_value = array_sum(array_map(function($p){ return $p['status']==='sold' ? $p['price'] : 0; }, $properties));
} else {
    $stmt = $pdo->prepare("SELECT * FROM estates WHERE id = ? $companyFilter");
    $stmt->execute([$id]);
    $estate = $stmt->fetch();
    if (!$estate) {
        echo "<div class='container py-5'><div class='alert alert-danger'>Estate not found or access denied.</div></div>";
        require 'includes/footer.php';
        exit;
    }
    $stmt = $pdo->prepare("SELECT COUNT(*) FROM properties WHERE estate_id = ? $companyFilter");
    $stmt->execute([$id]);
    $total_units = $stmt->fetchColumn();
    $stmt = $pdo->prepare("SELECT status, COUNT(*) as count FROM properties WHERE estate_id = ? $companyFilter GROUP BY status");
    $stmt->execute([$id]);
    $status_counts = $stmt->fetchAll(PDO::FETCH_KEY_PAIR);
    $available = $status_counts['available'] ?? 0;
    $sold = $status_counts['sold'] ?? 0;
    $reserved = $status_counts['reserved'] ?? 0;
    $sold_percentage = $total_units > 0 ? round(($sold / $total_units) * 100) : 0;
    $stmt = $pdo->prepare("SELECT SUM(price) FROM properties WHERE estate_id = ? $companyFilter");
    $stmt->execute([$id]);
    $total_value = $stmt->fetchColumn() ?: 0;
    $stmt = $pdo->prepare("SELECT SUM(price) FROM properties WHERE estate_id = ? AND status = 'sold' $companyFilter");
    $stmt->execute([$id]);
    $sold_value = $stmt->fetchColumn() ?: 0;
    $stmt = $pdo->prepare("SELECT * FROM properties WHERE estate_id = ? $companyFilter ORDER BY sort_order ASC, id ASC");
    $stmt->execute([$id]);
    $properties = $stmt->fetchAll();
}

if (!$estate) {
    echo "<div class='container py-5'><div class='alert alert-danger'>Estate not found or access denied.</div></div>";
    require 'includes/footer.php';
    exit;
}

$deleteGuard = function_exists('getEstateDeleteGuard') ? getEstateDeleteGuard((int)$estate['id']) : ['can_delete' => false, 'counts' => [], 'reasons' => []];
$pageMessage = trim((string)($_GET['msg'] ?? ''));
$pageMessageType = 'info';
if ($pageMessage !== '') {
    $pageMessageType = in_array($pageMessage, ['forbidden','invalid_input'], true) ? 'danger' : 'success';
    if (in_array($pageMessage, ['plots_generated','plot_added','updated'], true)) {
        $pageMessageType = 'success';
    } elseif (!in_array($pageMessage, ['forbidden','invalid_input'], true)) {
        $pageMessageType = 'warning';
    }
}

// Fetch Statistics
// Total Units
$stmt = $pdo->prepare("SELECT COUNT(*) FROM properties WHERE estate_id = ? $companyFilter");
$stmt->execute([$id]);
$total_units = $stmt->fetchColumn();

// Status Breakdown
$stmt = $pdo->prepare("SELECT status, COUNT(*) as count FROM properties WHERE estate_id = ? $companyFilter GROUP BY status");
$stmt->execute([$id]);
$status_counts = $stmt->fetchAll(PDO::FETCH_KEY_PAIR);

$available = $status_counts['available'] ?? 0;
$sold = $status_counts['sold'] ?? 0;
$reserved = $status_counts['reserved'] ?? 0;
$sold_percentage = $total_units > 0 ? round(($sold / $total_units) * 100) : 0;

// Financials (Potential Value vs Realized)
$stmt = $pdo->prepare("SELECT SUM(price) FROM properties WHERE estate_id = ? $companyFilter");
$stmt->execute([$id]);
$total_value = $stmt->fetchColumn() ?: 0;

$stmt = $pdo->prepare("SELECT SUM(price) FROM properties WHERE estate_id = ? AND status = 'sold' $companyFilter");
$stmt->execute([$id]);
$sold_value = $stmt->fetchColumn() ?: 0;

// Fetch Properties List
$stmt = $pdo->prepare("SELECT * FROM properties WHERE estate_id = ? $companyFilter ORDER BY sort_order ASC, id ASC");
$stmt->execute([$id]);
$properties = $stmt->fetchAll();

?>

<div class="container-fluid px-4 py-4">
    <!-- HEADER -->
    <div class="d-flex flex-column flex-md-row justify-content-between align-items-md-center mb-4 gap-3">
        <div>
            <div class="d-flex align-items-center gap-2 mb-1">
                <h1 class="h3 fw-bold text-primary mb-0"><?= htmlspecialchars($estate['name']) ?></h1>
                <span class="badge bg-<?= $estate['status'] == 'active' ? 'success' : 'secondary' ?>-soft text-<?= $estate['status'] == 'active' ? 'success' : 'secondary' ?>">
                    <?= ucfirst($estate['status']) ?>
                </span>
            </div>
            <p class="text-muted mb-0"><i class="fa-solid fa-location-dot me-1"></i> <?= htmlspecialchars($estate['location']) ?></p>
        </div>
        <div class="d-flex gap-2 flex-wrap">
            <a href="estates.php" class="btn btn-light border shadow-sm">
                <i class="fa-solid fa-arrow-left me-2"></i>Back
            </a>
            <?php if (!isRestrictedMode() && !$isDemo): ?>
                <a href="estate-edit.php?id=<?= $estate['id'] ?>" class="btn btn-white border shadow-sm hover-elevate hover-shimmer">
                    <i class="fa-solid fa-pen me-2"></i>Edit Details
                </a>
                <a href="estate-layout-management.php?estate_id=<?= $estate['id'] ?>" class="btn btn-white border shadow-sm hover-elevate hover-shimmer">
                    <i class="fa-solid fa-layer-group me-2"></i>Estate Layout
                </a>
                <a href="property-add.php?estate_id=<?= $estate['id'] ?>" class="btn btn-primary shadow-sm hover-elevate hover-shimmer">
                    <i class="fa-solid fa-plus me-2"></i>Add Unit
                </a>
                <form method="post" onsubmit="return confirm('Delete this estate project? This will only work if there are no linked properties, allocations, payments, or layout records.');">
                    <input type="hidden" name="action" value="delete_estate">
                    <button type="submit" class="btn btn-outline-danger shadow-sm" <?= !empty($deleteGuard['can_delete']) ? '' : 'disabled' ?>>
                        <i class="fa-solid fa-trash me-2"></i>Delete Estate
                    </button>
                </form>
            <?php endif; ?>
        </div>
    </div>

    <?php if ($pageMessage !== ''): ?>
        <?php
        $messageText = $pageMessage;
        if ($pageMessage === 'plots_generated') { $messageText = 'Plots generated successfully.'; }
        elseif ($pageMessage === 'plot_added') { $messageText = 'Plot added successfully.'; }
        elseif ($pageMessage === 'updated') { $messageText = 'Estate payment settings updated successfully.'; }
        elseif ($pageMessage === 'invalid_input') { $messageText = 'Please complete all required fields correctly.'; }
        elseif ($pageMessage === 'forbidden') { $messageText = 'You do not have permission to perform this action.'; }
        ?>
        <div class="alert alert-<?= htmlspecialchars($pageMessageType) ?>"><?= htmlspecialchars($messageText) ?></div>
    <?php endif; ?>

    <?php if (!empty($deleteGuard['can_delete'])): ?>
        <div class="alert alert-success">This estate can be deleted because no linked properties, allocations, payments, or estate layout records were found.</div>
    <?php elseif (!$isDemo && !empty($deleteGuard['reasons'])): ?>
        <div class="alert alert-warning">
            <div class="fw-semibold mb-1">Delete Estate is currently blocked.</div>
            <div class="small mb-2"><?= htmlspecialchars(implode(' ', $deleteGuard['reasons'])) ?></div>
            <div class="small text-muted">
                Properties: <?= (int)($deleteGuard['counts']['properties'] ?? 0) ?> |
                Allocations: <?= (int)($deleteGuard['counts']['allocations'] ?? 0) ?> |
                Payments: <?= (int)($deleteGuard['counts']['payments'] ?? 0) ?> |
                Layout Versions: <?= (int)($deleteGuard['counts']['layout_versions'] ?? 0) ?> |
                Zones: <?= (int)($deleteGuard['counts']['zones'] ?? 0) ?> |
                Plots: <?= (int)($deleteGuard['counts']['plots'] ?? 0) ?>
            </div>
        </div>
    <?php endif; ?>

    <!-- METRIC CARDS -->
    <div class="row g-4 mb-4 animate-stagger">
        <!-- Total Units -->
        <div class="col-xl-3 col-md-6">
            <div class="card metric-card h-100 border-0 shadow-sm animate-card hover-elevate">
                <div class="card-body">
                    <div class="d-flex justify-content-between align-items-start mb-3">
                        <div>
                            <div class="metric-label text-muted small fw-bold text-uppercase">Total Units</div>
                            <div class="metric-value h2 fw-bold text-dark mb-0"><?= number_format($total_units) ?></div>
                        </div>
                        <div class="metric-icon bg-primary-soft text-primary rounded p-2">
                            <i class="fa-solid fa-layer-group"></i>
                        </div>
                    </div>
                    <div class="progress" style="height: 6px;">
                        <div class="progress-bar bg-primary" role="progressbar" style="width: 100%"></div>
                    </div>
                </div>
            </div>
        </div>

        <!-- Availability -->
        <div class="col-xl-3 col-md-6">
            <div class="card metric-card h-100 border-0 shadow-sm animate-card hover-elevate">
                <div class="card-body">
                    <div class="d-flex justify-content-between align-items-start mb-3">
                        <div>
                            <div class="metric-label text-muted small fw-bold text-uppercase">Available</div>
                            <div class="metric-value h2 fw-bold text-dark mb-0"><?= number_format($available) ?></div>
                        </div>
                        <div class="metric-icon bg-success-soft text-success rounded p-2">
                            <i class="fa-solid fa-check-circle"></i>
                        </div>
                    </div>
                    <div class="progress" style="height: 6px;">
                        <div class="progress-bar bg-success" role="progressbar" style="width: <?= $total_units > 0 ? ($available/$total_units)*100 : 0 ?>%"></div>
                    </div>
                </div>
            </div>
        </div>

        <!-- Sold / Reserved -->
        <div class="col-xl-3 col-md-6">
            <div class="card metric-card h-100 border-0 shadow-sm animate-card hover-elevate">
                <div class="card-body">
                    <div class="d-flex justify-content-between align-items-start mb-3">
                        <div>
                            <div class="metric-label text-muted small fw-bold text-uppercase">Sold / Reserved</div>
                            <div class="metric-value h2 fw-bold text-dark mb-0"><?= number_format($sold + $reserved) ?></div>
                        </div>
                        <div class="metric-icon bg-warning-soft text-warning rounded p-2">
                            <i class="fa-solid fa-handshake"></i>
                        </div>
                    </div>
                    <div class="progress" style="height: 6px;">
                        <div class="progress-bar bg-warning" role="progressbar" style="width: <?= $total_units > 0 ? (($sold+$reserved)/$total_units)*100 : 0 ?>%"></div>
                    </div>
                </div>
            </div>
        </div>

        <!-- Project Value -->
        <div class="col-xl-3 col-md-6">
            <div class="card metric-card h-100 border-0 shadow-sm animate-card hover-elevate">
                <div class="card-body">
                    <div class="d-flex justify-content-between align-items-start mb-3">
                        <div>
                            <div class="metric-label text-muted small fw-bold text-uppercase">Project Value</div>
                            <div class="metric-value h2 fw-bold text-dark mb-0"><?= formatCurrency($total_value) ?></div>
                        </div>
                        <div class="metric-icon bg-info-soft text-info rounded p-2">
                            <i class="fa-solid fa-wallet"></i>
                        </div>
                    </div>
                    <div class="small text-muted">
                        <span class="text-success fw-bold"><?= formatCurrency($sold_value) ?></span> realized
                    </div>
                </div>
            </div>
        </div>
    </div>

    <div class="row g-4">
        <!-- LEFT COLUMN: OVERVIEW & IMAGE -->
        <div class="col-lg-4">
            <!-- Image Card -->
            <div class="card border-0 shadow-sm mb-4 animate-card hover-elevate">
                <?php if (!empty($estate['image'])): ?>
                    <img src="<?= htmlspecialchars($estate['image']) ?>" class="card-img-top" alt="Estate Layout" style="height: 250px; object-fit: cover;">
                <?php else: ?>
                    <div class="bg-light d-flex align-items-center justify-content-center text-muted card-img-top" style="height: 250px;">
                        <i class="fa-solid fa-map fa-3x opacity-25"></i>
                    </div>
                <?php endif; ?>
                <div class="card-body">
                    <h6 class="fw-bold text-dark">About Project</h6>
                    <p class="text-muted small mb-0">
                        <?= nl2br(htmlspecialchars($estate['description'])) ?>
                    </p>
                </div>
            </div>

            <?php if (!$isDemo): ?>
            <?php $cfg = getEstateConfig((int)$estate['id']); ?>
            <div class="card border-0 shadow-sm mb-4 animate-card hover-elevate">
                <div class="card-header bg-white border-bottom py-3 d-flex justify-content-between align-items-center">
                    <h6 class="mb-0 fw-bold">Payment Settings</h6>
                    <span class="badge bg-light text-dark">Project</span>
                </div>
                <div class="card-body">
                    <form method="POST">
                        <input type="hidden" name="estate_id" value="<?= (int)$estate['id'] ?>">
                        <div class="form-check form-switch mb-3">
                            <input class="form-check-input" type="checkbox" name="installment_allowed" id="installment_allowed" <?= !empty($cfg['installment_allowed']) ? 'checked' : '' ?>>
                            <label class="form-check-label" for="installment_allowed">Installment Allowed</label>
                        </div>
                        <div class="mb-3">
                            <label class="form-label fw-bold small text-muted">Preset Plans</label>
                            <div class="d-flex gap-3">
                                <?php $d = $cfg['default_plans'] ?? []; ?>
                                <div class="form-check">
                                    <input class="form-check-input" type="checkbox" name="plan3" id="plan3" <?= in_array(3, $d ?? [], true) ? 'checked' : '' ?>>
                                    <label class="form-check-label" for="plan3">3 Months</label>
                                </div>
                                <div class="form-check">
                                    <input class="form-check-input" type="checkbox" name="plan6" id="plan6" <?= in_array(6, $d ?? [], true) ? 'checked' : '' ?>>
                                    <label class="form-check-label" for="plan6">6 Months</label>
                                </div>
                                <div class="form-check">
                                    <input class="form-check-input" type="checkbox" name="plan8" id="plan8" <?= in_array(8, $d ?? [], true) ? 'checked' : '' ?>>
                                    <label class="form-check-label" for="plan8">8 Months</label>
                                </div>
                            </div>
                        </div>
                        <div class="mb-3">
                            <label class="form-label">Custom Months (default)</label>
                            <input type="number" class="form-control" name="custom_months_default" min="0" step="1" value="<?= (int)($cfg['custom_months_default'] ?? 0) ?>">
                        </div>
                        <div class="form-check form-switch mb-3">
                            <input class="form-check-input" type="checkbox" name="excavation_fee_enabled" id="excavation_fee_enabled" <?= !empty($cfg['excavation_fee_enabled']) ? 'checked' : '' ?>>
                            <label class="form-check-label" for="excavation_fee_enabled">Excavation Fee</label>
                        </div>
                        <div class="mb-3">
                            <label class="form-label">Infrastructure Fee</label>
                            <div class="input-group">
                                <span class="input-group-text">₦</span>
                                <input type="number" class="form-control" name="infrastructure_fee" step="0.01" value="<?= htmlspecialchars((string)($cfg['infrastructure_fee'] ?? 0)) ?>">
                            </div>
                        </div>
                        <div class="mb-3">
                            <label class="form-label">Late Penalty %</label>
                            <div class="input-group">
                                <input type="number" class="form-control" name="late_penalty_percent" step="0.01" min="0" max="100" value="<?= htmlspecialchars((string)($cfg['late_penalty_percent'] ?? 0)) ?>">
                                <span class="input-group-text">%</span>
                            </div>
                        </div>
                        <div class="d-grid">
                            <button type="submit" name="save_payment_settings" class="btn btn-primary">Save Settings</button>
                        </div>
                    </form>
                </div>
            </div>
            <?php endif; ?>

            <?php if (!$isDemo): ?>
            <div class="card border-0 shadow-sm mb-4 animate-card hover-elevate">
                <div class="card-header bg-white border-bottom py-3 d-flex justify-content-between align-items-center">
                    <h6 class="mb-0 fw-bold">Plot Bank Management</h6>
                    <span class="badge bg-light text-dark">Inventory</span>
                </div>
                <div class="card-body">
                    <div class="row g-3">
                        <div class="col-12">
                            <form method="POST" class="row g-2 align-items-end">
                                <input type="hidden" name="action" value="plots_generate">
                                <div class="col-3">
                                    <label class="form-label">Block</label>
                                    <input type="text" name="block" class="form-control" placeholder="A" required>
                                </div>
                                <div class="col-3">
                                    <label class="form-label">Start No</label>
                                    <input type="number" name="start_no" class="form-control" required>
                                </div>
                                <div class="col-3">
                                    <label class="form-label">End No</label>
                                    <input type="number" name="end_no" class="form-control" required>
                                </div>
                                <div class="col-3">
                                    <label class="form-label">Size (SQM)</label>
                                    <input type="number" step="0.01" name="size_sqm" class="form-control" required>
                                </div>
                                <div class="col-12">
                                    <button class="btn btn-dark w-100" type="submit">Bulk Generate</button>
                                </div>
                            </form>
                        </div>
                        <div class="col-12">
                            <form method="POST" class="row g-2 align-items-end">
                                <input type="hidden" name="action" value="plots_add_single">
                                <div class="col-4">
                                    <label class="form-label">Block</label>
                                    <input type="text" name="block" class="form-control" required>
                                </div>
                                <div class="col-4">
                                    <label class="form-label">Plot No</label>
                                    <input type="text" name="plot_no" class="form-control" required>
                                </div>
                                <div class="col-4">
                                    <label class="form-label">Size (SQM)</label>
                                    <input type="number" step="0.01" name="size_sqm" class="form-control" required>
                                </div>
                                <div class="col-12">
                                    <button class="btn btn-outline-dark w-100" type="submit">Add Single Plot</button>
                                </div>
                            </form>
                        </div>
                        <div class="col-12">
                            <?php
                                ensurePlotsTable();
                                $plots = [];
                                try {
                                    $st = $pdo->prepare("SELECT block, size_sqm, status, COUNT(*) as cnt FROM plots WHERE estate_id = ? GROUP BY block, size_sqm, status ORDER BY block, size_sqm");
                                    $st->execute([(int)$id]);
                                    $plots = $st->fetchAll(PDO::FETCH_ASSOC);
                                } catch (Exception $e) {}
                            ?>
                            <div class="table-responsive">
                                <table class="table table-sm">
                                    <thead class="table-light">
                                        <tr>
                                            <th>Block</th>
                                            <th>Size (SQM)</th>
                                            <th>Status</th>
                                            <th>Count</th>
                                        </tr>
                                    </thead>
                                    <tbody>
                                        <?php if (empty($plots)): ?>
                                            <tr><td colspan="4" class="text-center text-muted">No plots</td></tr>
                                        <?php else: foreach ($plots as $p): ?>
                                            <tr>
                                                <td><?= htmlspecialchars($p['block']) ?></td>
                                                <td><?= number_format($p['size_sqm'],2) ?></td>
                                                <td><?= ucfirst($p['status']) ?></td>
                                                <td class="fw-bold"><?= (int)$p['cnt'] ?></td>
                                            </tr>
                                        <?php endforeach; endif; ?>
                                    </tbody>
                                </table>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
            <?php endif; ?>

            <!-- Progress Card -->
            <div class="card border-0 shadow-sm animate-card hover-elevate">
                <div class="card-body">
                    <h6 class="fw-bold text-dark mb-4">Sales Progress</h6>
                    <div class="text-center position-relative mb-4">
                        <div class="display-4 fw-bold text-primary pulse-on-load"><?= $sold_percentage ?>%</div>
                        <div class="text-muted small text-uppercase tracking-wide">Sold Out</div>
                    </div>
                    <div class="d-flex justify-content-between small text-muted mb-2">
                        <span>0%</span>
                        <span>50%</span>
                        <span>100%</span>
                    </div>
                    <div class="progress" style="height: 10px;">
                        <div class="progress-bar bg-primary progress-bar-striped progress-bar-animated" role="progressbar" style="width: <?= $sold_percentage ?>%"></div>
                    </div>
                </div>
            </div>
        </div>

        <!-- RIGHT COLUMN: UNITS INVENTORY -->
        <div class="col-lg-8">
            <div class="card border-0 shadow-sm h-100 animate-card hover-elevate">
                <div class="card-header bg-white border-bottom py-3">
                    <div class="d-flex flex-wrap justify-content-between align-items-center gap-2">
                        <h6 class="mb-0 fw-bold">Property Units Inventory</h6>
                        <div class="d-flex flex-wrap align-items-center gap-2">
                            <ul class="nav nav-pills" id="statusFilters">
                                <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="available">Available</a></li>
                                <li class="nav-item"><a class="nav-link" href="#" data-filter="reserved">Reserved</a></li>
                                <li class="nav-item"><a class="nav-link" href="#" data-filter="sold">Sold</a></li>
                            </ul>
                            <div class="input-group input-group-sm w-auto">
                                <span class="input-group-text bg-light border-end-0"><i class="fa-solid fa-search"></i></span>
                                <input type="text" class="form-control bg-light border-start-0" placeholder="Search units..." id="unitsSearch">
                            </div>
                        </div>
                    </div>
                </div>
                <div class="card-body p-0">
                    <div class="table-responsive">
                        <table class="table table-hover align-middle mb-0 table-appear">
                            <thead class="bg-light">
                                <tr>
                                    <th class="ps-4">Unit / Plot</th>
                                    <th>Type</th>
                                    <th>Price</th>
                                    <th>Status</th>
                                    <th class="text-end pe-4">Actions</th>
                                </tr>
                            </thead>
                            <tbody>
                                <?php if (empty($properties)): ?>
                                    <tr>
                                        <td colspan="5" class="text-center py-5 text-muted">
                                            <i class="fa-solid fa-box-open fa-2x mb-3 opacity-25"></i>
                                            <p class="mb-0">No units added yet.</p>
                                        </td>
                                    </tr>
                                <?php else: ?>
                                    <?php foreach ($properties as $prop): ?>
                                        <tr data-status="<?= htmlspecialchars($prop['status']) ?>">
                                            <td class="ps-4">
                                                <div class="fw-bold text-dark"><?= htmlspecialchars($prop['title']) ?></div>
                                                <div class="small text-muted"><?= htmlspecialchars($prop['address'] ?? '') ?></div>
                                            </td>
                                            <td>
                                                <span class="badge badge-soft bg-light text-dark border">
                                                    <?= ucfirst($prop['type'] ?? 'Plot') ?>
                                                </span>
                                            </td>
                                            <td class="fw-bold text-dark">
                                                <?= formatCurrency($prop['price']) ?>
                                            </td>
                                            <td>
                                                <?php
                                                $statusClass = match($prop['status']) {
                                                    'available' => 'success',
                                                    'sold' => 'danger',
                                                    'reserved' => 'warning',
                                                    default => 'secondary'
                                                };
                                                ?>
                                                <span class="badge badge-soft bg-<?= $statusClass ?>-soft text-<?= $statusClass ?>">
                                                    <?= ucfirst($prop['status']) ?>
                                                </span>
                                            </td>
                                            <td class="text-end pe-4">
                                                <div class="dropdown">
                                                    <button class="btn btn-sm btn-light border hover-elevate" type="button" data-bs-toggle="dropdown">
                                                        <i class="fa-solid fa-ellipsis-vertical"></i>
                                                    </button>
                                                    <ul class="dropdown-menu dropdown-menu-end border-0 shadow-lg">
                                                        <?php if (!isRestrictedMode() && !$isDemo): ?>
                                                            <li><a class="dropdown-item" href="property-edit.php?id=<?= $prop['id'] ?>"><i class="fa-solid fa-pen-to-square me-2 text-muted"></i>Edit</a></li>
                                                            <li><a class="dropdown-item" href="allocation-add.php?property_id=<?= $prop['id'] ?>"><i class="fa-solid fa-user-check me-2 text-muted"></i>Allocate</a></li>
                                                        <?php endif; ?>
                                                        <li><hr class="dropdown-divider"></li>
                                                        <?php if (!isRestrictedMode() && !$isDemo): ?>
                                                            <li><a class="dropdown-item text-danger" href="property-delete.php?id=<?= $prop['id'] ?>" onclick="return confirm('Are you sure?')"><i class="fa-solid fa-trash me-2"></i>Delete</a></li>
                                                        <?php endif; ?>
                                                    </ul>
                                                </div>
                                            </td>
                                        </tr>
                                    <?php endforeach; ?>
                                <?php endif; ?>
                            </tbody>
                        </table>
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>

<?php require 'includes/footer.php'; ?>
<script>
document.addEventListener('DOMContentLoaded', function() {
  var searchInput = document.getElementById('unitsSearch');
  var filterNav = document.getElementById('statusFilters');
  var tbody = document.querySelector('.table-appear tbody');
  var filter = 'all';
  function applyFilters() {
    var q = (searchInput && searchInput.value ? searchInput.value.toLowerCase() : '');
    var rows = tbody ? tbody.querySelectorAll('tr') : [];
    rows.forEach(function(row) {
      var status = row.getAttribute('data-status') || '';
      var text = row.textContent.toLowerCase();
      var matchStatus = filter === 'all' || status === filter;
      var matchSearch = !q || text.indexOf(q) !== -1;
      row.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>

Youez - 2016 - github.com/yon3zu
LinuXploit