38348-vm/invoices.php
2026-02-11 01:46:33 +00:00

168 lines
7.0 KiB
PHP

<?php
$page_title = "Invoices";
require_once 'includes/header.php';
$search = $_GET['search'] ?? '';
$where = "WHERE i.deleted_at IS NULL";
$params = [];
if ($search) {
$where .= " AND (i.invoice_number LIKE ? OR c.name LIKE ?)";
$params[] = "%$search%";
$params[] = "%$search%";
}
$query = "SELECT i.*, c.name as customer_name, c.email as customer_email
FROM invoices i
JOIN customers c ON i.customer_id = c.id
$where
ORDER BY i.created_at DESC";
$stmt = db()->prepare($query);
$stmt->execute($params);
$invoices = $stmt->fetchAll();
$msg = $_GET['msg'] ?? '';
$error = $_GET['error'] ?? '';
?>
<div class="d-flex justify-content-between align-items-center mb-4">
<h2 class="h3 mb-0">Invoices</h2>
</div>
<?php if ($msg): ?>
<div class="alert alert-success alert-dismissible fade show" role="alert">
<?= e($msg) ?>
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div>
<?php endif; ?>
<?php if ($error): ?>
<div class="alert alert-danger alert-dismissible fade show" role="alert">
<?= e($error) ?>
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div>
<?php endif; ?>
<div class="card border-0 shadow-sm mb-4">
<div class="card-body">
<form method="GET" class="row g-3">
<div class="col-md-10">
<div class="input-group">
<span class="input-group-text bg-transparent border-end-0">
<i class="bi bi-search text-muted"></i>
</span>
<input type="text" name="search" class="form-control border-start-0 ps-0"
placeholder="Search by number or customer..." value="<?= e($search) ?>">
</div>
</div>
<div class="col-md-2">
<button type="submit" class="btn btn-light w-100">Search</button>
</div>
</form>
</div>
</div>
<div class="card border-0 shadow-sm">
<div class="table-responsive">
<table class="table table-hover align-middle mb-0">
<thead class="bg-light">
<tr>
<th class="ps-4">Invoice #</th>
<th>Customer</th>
<th>Date</th>
<th>Due Date</th>
<th>Status</th>
<th class="text-end">Total</th>
<th class="text-end pe-4">Actions</th>
</tr>
</thead>
<tbody>
<?php if (empty($invoices)): ?>
<tr>
<td colspan="7" class="text-center py-5 text-muted">
No invoices found.
</td>
</tr>
<?php else: ?>
<?php foreach ($invoices as $i): ?>
<tr>
<td class="ps-4 fw-medium"><?= e($i['invoice_number']) ?></td>
<td>
<div><?= e($i['customer_name']) ?></div>
<small class="text-muted"><?= e($i['customer_email']) ?></small>
</td>
<td><?= date('M d, Y', strtotime($i['issue_date'])) ?></td>
<td><?= date('M d, Y', strtotime($i['due_date'])) ?></td>
<td>
<?php
$badge_class = 'bg-secondary';
switch($i['status']) {
case 'Paid': $badge_class = 'bg-success'; break;
case 'Unpaid': $badge_class = 'bg-warning text-dark'; break;
case 'Partial': $badge_class = 'bg-info text-dark'; break;
case 'Overdue': $badge_class = 'bg-danger'; break;
}
?>
<span class="badge rounded-pill <?= $badge_class ?>">
<?= $i['status'] ?>
</span>
</td>
<td class="text-end fw-bold"><?= format_currency($i['total_amount']) ?></td>
<td class="text-end pe-4">
<div class="btn-group">
<a href="invoice_pdf.php?id=<?= $i['id'] ?>" class="btn btn-sm btn-outline-primary" title="Download PDF" target="_blank">
<i class="bi bi-file-pdf"></i>
</a>
<a href="send_document.php?type=invoice&id=<?= $i['id'] ?>" class="btn btn-sm btn-outline-info" title="Email to Customer" onclick="return confirm('Email this invoice to <?= e($i['customer_email']) ?>?')">
<i class="bi bi-envelope"></i>
</a>
<?php if ($i['status'] !== 'Paid'): ?>
<button type="button" class="btn btn-sm btn-outline-success" title="Mark as Paid" onclick="markAsPaid(<?= $i['id'] ?>)">
<i class="bi bi-check-circle"></i>
</button>
<a href="send_document.php?type=invoice&id=<?= $i['id'] ?>&reminder=1" class="btn btn-sm btn-outline-warning" title="Send Reminder" onclick="return confirm('Send payment reminder to <?= e($i['customer_email']) ?>?')">
<i class="bi bi-bell"></i>
</a>
<?php endif; ?>
</div>
</td>
</tr>
<?php endforeach; ?>
<?php endif; ?>
</tbody>
</table>
</div>
</div>
<script>
function markAsPaid(id) {
if (confirm('Mark this invoice as paid?')) {
const form = document.createElement('form');
form.method = 'POST';
form.action = 'invoice_update_status.php';
const idInput = document.createElement('input');
idInput.type = 'hidden';
idInput.name = 'id';
idInput.value = id;
form.appendChild(idInput);
const statusInput = document.createElement('input');
statusInput.type = 'hidden';
statusInput.name = 'status';
statusInput.value = 'Paid';
form.appendChild(statusInput);
const csrfInput = document.createElement('input');
csrfInput.type = 'hidden';
csrfInput.name = 'csrf_token';
csrfInput.value = '<?= csrf_token() ?>';
form.appendChild(csrfInput);
document.body.appendChild(form);
form.submit();
}
}
</script>
<?php require_once 'includes/footer.php'; ?>