416 lines
20 KiB
PHP
416 lines
20 KiB
PHP
<?php
|
|
require_once 'session.php';
|
|
require_once 'db/config.php';
|
|
|
|
$page = $_GET['page'] ?? 'dashboard';
|
|
|
|
|
|
$properties = [];
|
|
$tenants = [];
|
|
$payments = [];
|
|
|
|
try {
|
|
$db = db();
|
|
if ($page === 'properties') {
|
|
$stmt = $db->query('SELECT * FROM properties ORDER BY created_at DESC');
|
|
$properties = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
|
} elseif ($page === 'dashboard') {
|
|
$stmt = $db->query('SELECT COUNT(*) FROM properties');
|
|
$total_properties = $stmt->fetchColumn();
|
|
$stmt = $db->query('SELECT COUNT(*) FROM tenants');
|
|
$total_tenants = $stmt->fetchColumn();
|
|
$stmt = $db->query('SELECT COUNT(*) FROM maintenance_requests');
|
|
$total_requests = $stmt->fetchColumn();
|
|
$stmt = $db->query('SELECT SUM(amount) FROM payments');
|
|
$total_payments = $stmt->fetchColumn();
|
|
|
|
// Data for Payments Chart
|
|
$stmt = $db->query("SELECT MONTH(payment_date) as month, SUM(amount) as total FROM payments WHERE YEAR(payment_date) = YEAR(CURDATE()) GROUP BY MONTH(payment_date)");
|
|
$payment_chart_data = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
|
$payment_labels = [];
|
|
$payment_values = [];
|
|
foreach ($payment_chart_data as $data) {
|
|
$payment_labels[] = date('F', mktime(0, 0, 0, $data['month'], 10));
|
|
$payment_values[] = $data['total'];
|
|
}
|
|
|
|
// Data for Maintenance Requests Chart
|
|
$stmt = $db->query("SELECT status, COUNT(*) as count FROM maintenance_requests GROUP BY status");
|
|
$request_chart_data = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
|
$request_labels = [];
|
|
$request_values = [];
|
|
foreach ($request_chart_data as $data) {
|
|
$request_labels[] = $data['status'];
|
|
$request_values[] = $data['count'];
|
|
}
|
|
|
|
} elseif ($page === 'tenants') {
|
|
$stmt = $db->query('SELECT t.*, p.name AS property_name FROM tenants t LEFT JOIN properties p ON t.property_id = p.id ORDER BY t.created_at DESC');
|
|
$tenants = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
|
} elseif ($page === 'payments') {
|
|
$stmt = $db->query('SELECT pay.*, t.name AS tenant_name, p.name AS property_name FROM payments pay JOIN tenants t ON pay.tenant_id = t.id JOIN properties p ON pay.property_id = p.id ORDER BY pay.payment_date DESC');
|
|
$payments = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
|
} elseif ($page === 'maintenance') {
|
|
$stmt = $db->query('SELECT mr.*, p.name AS property_name, t.name AS tenant_name FROM maintenance_requests mr LEFT JOIN properties p ON mr.property_id = p.id LEFT JOIN tenants t ON mr.tenant_id = t.id ORDER BY mr.reported_date DESC');
|
|
$maintenance_requests = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
|
}
|
|
} catch (PDOException $e) {
|
|
die("DB ERROR: " . $e->getMessage());
|
|
}
|
|
|
|
$success_message = '';
|
|
if (isset($_GET['success'])) {
|
|
switch ($_GET['success']) {
|
|
case 1: $success_message = "Payment added successfully!"; break;
|
|
case 2: $success_message = "Payment updated successfully!"; break;
|
|
case 3: $success_message = "Payment deleted successfully!"; break;
|
|
}
|
|
}
|
|
|
|
$error_message = '';
|
|
if (isset($_GET['error'])) {
|
|
switch ($_GET['error']) {
|
|
case 1: $error_message = "Error: Missing payment ID."; break;
|
|
case 2: $error_message = "Error: Could not delete payment."; break;
|
|
}
|
|
}
|
|
|
|
require_once 'templates/header.php';
|
|
?>
|
|
|
|
<main class="container mt-4 flex-grow-1">
|
|
<?php if ($success_message): ?>
|
|
<div class="alert alert-success"><?= $success_message ?></div>
|
|
<?php endif; ?>
|
|
<?php if ($error_message): ?>
|
|
<div class="alert alert-danger"><?= $error_message ?></div>
|
|
<?php endif; ?>
|
|
|
|
<ul class="nav nav-tabs" id="myTab" role="tablist">
|
|
<li class="nav-item" role="presentation">
|
|
<a class="nav-link <?= ($page === 'dashboard') ? 'active' : '' ?>" href="?page=dashboard">Dashboard</a>
|
|
</li>
|
|
<li class="nav-item" role="presentation">
|
|
<a class="nav-link <?= ($page === 'properties') ? 'active' : '' ?>" href="?page=properties">Properties</a>
|
|
</li>
|
|
<li class="nav-item" role="presentation">
|
|
<a class="nav-link <?= ($page === 'tenants') ? 'active' : '' ?>" href="?page=tenants">Tenants</a>
|
|
</li>
|
|
<li class="nav-item" role="presentation">
|
|
<a class="nav-link <?= ($page === 'payments') ? 'active' : '' ?>" href="?page=payments">Payments</a>
|
|
</li>
|
|
<li class="nav-item" role="presentation">
|
|
<a class="nav-link <?= ($page === 'maintenance') ? 'active' : '' ?>" href="?page=maintenance">Maintenance</a>
|
|
</li>
|
|
</ul>
|
|
|
|
<div class="tab-content" id="myTabContent">
|
|
<div class="tab-pane fade <?php echo ($page === 'dashboard') ? 'show active' : ''; ?>" id="dashboard" role="tabpanel">
|
|
<div class="d-flex justify-content-between align-items-center my-4">
|
|
<h1>Dashboard</h1>
|
|
</div>
|
|
<div class="row">
|
|
<div class="col-md-3">
|
|
<div class="card mb-3">
|
|
<div class="card-body">
|
|
<h5 class="card-title">Total Properties</h5>
|
|
<p class="card-text fs-4"><?= $total_properties ?? 0 ?></p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-3">
|
|
<div class="card mb-3">
|
|
<div class="card-body">
|
|
<h5 class="card-title">Total Tenants</h5>
|
|
<p class="card-text fs-4"><?= $total_tenants ?? 0 ?></p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-3">
|
|
<div class="card mb-3">
|
|
<div class="card-body">
|
|
<h5 class="card-title">Maintenance Requests</h5>
|
|
<p class="card-text fs-4"><?= $total_requests ?? 0 ?></p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-3">
|
|
<div class="card mb-3">
|
|
<div class="card-body">
|
|
<h5 class="card-title">Total Payments</h5>
|
|
<p class="card-text fs-4">$<?= number_format($total_payments ?? 0, 2) ?></p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row">
|
|
<div class="col-md-6">
|
|
<div class="card">
|
|
<div class="card-body">
|
|
<h5 class="card-title">Monthly Payments (Current Year)</h5>
|
|
<canvas id="paymentsChart"></canvas>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<div class="card">
|
|
<div class="card-body">
|
|
<h5 class="card-title">Maintenance Requests Status</h5>
|
|
<canvas id="requestsChart"></canvas>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="tab-pane fade <?php echo ($page === 'properties') ? 'show active' : ''; ?>" id="properties" role="tabpanel">
|
|
<div class="d-flex justify-content-between align-items-center my-4">
|
|
<h1>Properties</h1>
|
|
<?php if (is_admin()): ?>
|
|
<a href="add_property.php" class="btn btn-primary"><i class="bi bi-plus-circle"></i> Add New Property</a>
|
|
<?php endif; ?>
|
|
</div>
|
|
<div class="card">
|
|
<div class="card-body">
|
|
<table class="table table-hover">
|
|
<thead>
|
|
<tr>
|
|
<th>Name</th>
|
|
<th>Address</th>
|
|
<th>Rent</th>
|
|
<th>Actions</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<?php foreach ($properties as $property): ?>
|
|
<tr>
|
|
<td><?php echo htmlspecialchars($property['name']); ?></td>
|
|
<td><?php echo htmlspecialchars($property['address']); ?></td>
|
|
<td>$<?php echo htmlspecialchars(number_format($property['rent_amount'], 2)); ?></td>
|
|
<td>
|
|
<a href="edit_property.php?id=<?php echo $property['id']; ?>" class="btn btn-sm btn-secondary"><i class="bi bi-pencil-square"></i> Edit</a>
|
|
<?php if (is_admin()): ?>
|
|
<form action="delete_property.php" method="POST" class="d-inline" onsubmit="return confirm('Are you sure you want to delete this property?');">
|
|
<input type="hidden" name="id" value="<?php echo $property['id']; ?>">
|
|
<button type="submit" class="btn btn-sm btn-danger"><i class="bi bi-trash"></i> Delete</button>
|
|
</form>
|
|
<?php endif; ?>
|
|
</td>
|
|
</tr>
|
|
<?php endforeach; ?>
|
|
<?php if (empty($properties)): ?>
|
|
<tr><td colspan="4" class="text-center">No properties found.</td></tr>
|
|
<?php endif; ?>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="tab-pane fade <?php echo ($page === 'tenants') ? 'show active' : ''; ?>" id="tenants" role="tabpanel">
|
|
<div class="d-flex justify-content-between align-items-center my-4">
|
|
<h1>Tenants</h1>
|
|
<?php if (is_admin()): ?>
|
|
<a href="add_tenant.php" class="btn btn-primary"><i class="bi bi-plus-circle"></i> Add New Tenant</a>
|
|
<?php endif; ?>
|
|
</div>
|
|
<div class="card">
|
|
<div class="card-body">
|
|
<table class="table table-hover">
|
|
<thead>
|
|
<tr>
|
|
<th>Name</th>
|
|
<th>Email</th>
|
|
<th>Property</th>
|
|
<th>Lease End</th>
|
|
<th>Status</th>
|
|
<th>Actions</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<?php foreach ($tenants as $tenant): ?>
|
|
<tr>
|
|
<td><?php echo htmlspecialchars($tenant['name']); ?></td>
|
|
<td><?php echo htmlspecialchars($tenant['email']); ?></td>
|
|
<td><?php echo htmlspecialchars($tenant['property_name'] ?? 'N/A'); ?></td>
|
|
<td><?php echo htmlspecialchars($tenant['lease_end']); ?></td>
|
|
<td><span class="badge bg-primary"><?php echo htmlspecialchars($tenant['status']); ?></span></td>
|
|
<td>
|
|
<a href="edit_tenant.php?id=<?php echo $tenant['id']; ?>" class="btn btn-sm btn-secondary"><i class="bi bi-pencil-square"></i> Edit</a>
|
|
<?php if (is_admin()): ?>
|
|
<form action="delete_tenant.php" method="POST" class="d-inline" onsubmit="return confirm('Are you sure you want to delete this tenant?');">
|
|
<input type="hidden" name="id" value="<?php echo $tenant['id']; ?>">
|
|
<button type="submit" class="btn btn-sm btn-danger"><i class="bi bi-trash"></i> Delete</button>
|
|
</form>
|
|
<?php endif; ?>
|
|
</td>
|
|
</tr>
|
|
<?php endforeach; ?>
|
|
<?php if (empty($tenants)): ?>
|
|
<tr><td colspan="6" class="text-center">No tenants found.</td></tr>
|
|
<?php endif; ?>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="tab-pane fade <?= ($page === 'payments') ? 'show active' : '' ?>" id="payments" role="tabpanel">
|
|
<div class="d-flex justify-content-between align-items-center my-4">
|
|
<h1>Payments</h1>
|
|
<?php if (is_admin()): ?>
|
|
<a href="add_payment.php" class="btn btn-primary"><i class="bi bi-plus-circle"></i> Add New Payment</a>
|
|
<?php endif; ?>
|
|
</div>
|
|
<div class="card">
|
|
<div class="card-body">
|
|
<table class="table table-hover">
|
|
<thead>
|
|
<tr>
|
|
<th>Tenant</th>
|
|
<th>Property</th>
|
|
<th>Amount</th>
|
|
<th>Payment Date</th>
|
|
<th>Actions</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<?php foreach ($payments as $payment): ?>
|
|
<tr>
|
|
<td><?= htmlspecialchars($payment['tenant_name']) ?></td>
|
|
<td><?= htmlspecialchars($payment['property_name']) ?></td>
|
|
<td>$<?= htmlspecialchars(number_format($payment['amount'], 2)) ?></td>
|
|
<td><?= htmlspecialchars($payment['payment_date']) ?></td>
|
|
<td>
|
|
<a href="edit_payment.php?id=<?= $payment['id'] ?>" class="btn btn-sm btn-secondary"><i class="bi bi-pencil-square"></i> Edit</a>
|
|
<?php if (is_admin()): ?>
|
|
<form action="delete_payment.php" method="POST" class="d-inline" onsubmit="return confirm('Are you sure you want to delete this payment?');">
|
|
<input type="hidden" name="id" value="<?= $payment['id'] ?>">
|
|
<button type="submit" class="btn btn-sm btn-danger"><i class="bi bi-trash"></i> Delete</button>
|
|
</form>
|
|
<?php endif; ?>
|
|
</td>
|
|
</tr>
|
|
<?php endforeach; ?>
|
|
<?php if (empty($payments)): ?>
|
|
<tr><td colspan="5" class="text-center">No payments found.</td></tr>
|
|
<?php endif; ?>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="tab-pane fade <?php echo ($page === 'maintenance') ? 'show active' : ''; ?>" id="maintenance" role="tabpanel">
|
|
<div class="d-flex justify-content-between align-items-center my-4">
|
|
<h1>Maintenance Requests</h1>
|
|
<a href="add_request.php" class="btn btn-primary"><i class="bi bi-plus-circle"></i> Add New Request</a>
|
|
</div>
|
|
<div class="card">
|
|
<div class="card-body">
|
|
<table class="table table-hover">
|
|
<thead>
|
|
<tr>
|
|
<th>Property</th>
|
|
<th>Tenant</th>
|
|
<th>Description</th>
|
|
<th>Status</th>
|
|
<th>Reported Date</th>
|
|
<th>Actions</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<?php if (isset($maintenance_requests)): ?>
|
|
<?php foreach ($maintenance_requests as $request): ?>
|
|
<tr>
|
|
<td><?php echo htmlspecialchars($request['property_name'] ?? 'N/A'); ?></td>
|
|
<td><?php echo htmlspecialchars($request['tenant_name'] ?? 'N/A'); ?></td>
|
|
<td><?php echo htmlspecialchars($request['description']); ?></td>
|
|
<td><span class="badge bg-info"><?php echo htmlspecialchars($request['status']); ?></span></td>
|
|
<td><?php echo htmlspecialchars($request['reported_date']); ?></td>
|
|
<td>
|
|
<a href="edit_request.php?id=<?php echo $request['id']; ?>" class="btn btn-sm btn-secondary"><i class="bi bi-pencil-square"></i> Edit</a>
|
|
<?php if (is_admin()): ?>
|
|
<form action="delete_request.php" method="POST" class="d-inline" onsubmit="return confirm('Are you sure you want to delete this request?');">
|
|
<input type="hidden" name="id" value="<?php echo $request['id']; ?>">
|
|
<button type="submit" class="btn btn-sm btn-danger"><i class="bi bi-trash"></i> Delete</button>
|
|
</form>
|
|
<?php endif; ?>
|
|
</td>
|
|
</tr>
|
|
<?php endforeach; ?>
|
|
<?php if (empty($maintenance_requests)): ?>
|
|
<tr><td colspan="6" class="text-center">No maintenance requests found.</td></tr>
|
|
<?php endif; ?>
|
|
<?php endif; ?>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</main>
|
|
|
|
<?php require_once 'templates/footer.php'; ?>
|
|
|
|
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
|
<script>
|
|
document.addEventListener('DOMContentLoaded', function () {
|
|
const primaryColor = getComputedStyle(document.documentElement).getPropertyValue('--primary-color').trim();
|
|
const secondaryColor = getComputedStyle(document.documentElement).getPropertyValue('--secondary-color').trim();
|
|
|
|
// Payments Chart
|
|
const paymentsCtx = document.getElementById('paymentsChart');
|
|
if (paymentsCtx) {
|
|
new Chart(paymentsCtx, {
|
|
type: 'bar',
|
|
data: {
|
|
labels: <?= json_encode($payment_labels ?? []) ?>,
|
|
datasets: [{
|
|
label: 'Total Payments',
|
|
data: <?= json_encode($payment_values ?? []) ?>,
|
|
backgroundColor: primaryColor + '33', // Adding alpha for fill
|
|
borderColor: primaryColor,
|
|
borderWidth: 1
|
|
}]
|
|
},
|
|
options: {
|
|
scales: {
|
|
y: {
|
|
beginAtZero: true
|
|
}
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
// Maintenance Requests Chart
|
|
const requestsCtx = document.getElementById('requestsChart');
|
|
if (requestsCtx) {
|
|
new Chart(requestsCtx, {
|
|
type: 'pie',
|
|
data: {
|
|
labels: <?= json_encode($request_labels ?? []) ?>,
|
|
datasets: [{
|
|
label: 'Request Status',
|
|
data: <?= json_encode($request_values ?? []) ?>,
|
|
backgroundColor: [
|
|
primaryColor + '33',
|
|
secondaryColor + '33',
|
|
'#36A2EB33',
|
|
'#FFCE5633'
|
|
],
|
|
borderColor: [
|
|
primaryColor,
|
|
secondaryColor,
|
|
'#36A2EB',
|
|
'#FFCE56'
|
|
],
|
|
borderWidth: 1
|
|
}]
|
|
}
|
|
});
|
|
}
|
|
});
|
|
</script>
|