100 lines
4.9 KiB
PHP
100 lines
4.9 KiB
PHP
<?php
|
|
declare(strict_types=1);
|
|
require_once __DIR__ . '/includes/app.php';
|
|
|
|
$id = isset($_GET['id']) ? (int)$_GET['id'] : 0;
|
|
$request = $id > 0 ? tenantScopedRequestById($id) : null;
|
|
|
|
if (!$request) {
|
|
flash('warning', 'That request could not be found inside the active tenant.');
|
|
redirectWithCompany('/leave_requests.php');
|
|
}
|
|
|
|
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
|
$action = (string)($_POST['action'] ?? '');
|
|
$reason = trim((string)($_POST['rejection_reason'] ?? ''));
|
|
|
|
if (in_array($action, ['approve', 'reject'], true) && reviewLeaveRequest((int)$request['id'], $action, $reason)) {
|
|
flash('success', $action === 'approve' ? 'Leave request approved.' : 'Leave request rejected with reason recorded.');
|
|
redirectWithCompany('/leave_request.php', ['id' => (int)$request['id']]);
|
|
}
|
|
|
|
flash('danger', 'Unable to update request. Rejections require a reason and only pending items can be reviewed.');
|
|
redirectWithCompany('/leave_request.php', ['id' => (int)$request['id']]);
|
|
}
|
|
|
|
$request = tenantScopedRequestById($id);
|
|
|
|
renderPageStart(
|
|
'Leave Request Detail',
|
|
'Inspect a tenant-scoped leave request, review the audit trail, and approve or reject safely.',
|
|
'requests'
|
|
);
|
|
?>
|
|
<section class="row g-4">
|
|
<div class="col-xl-8">
|
|
<article class="panel-card">
|
|
<div class="panel-head">
|
|
<div>
|
|
<span class="section-kicker">Request detail</span>
|
|
<h2 class="panel-title mb-1"><?= htmlspecialchars($request['employee_name']) ?> · <?= htmlspecialchars($request['leave_type']) ?></h2>
|
|
<p class="text-secondary mb-0">Request #<?= (int)$request['id'] ?> for <?= htmlspecialchars($request['company_name']) ?>.</p>
|
|
</div>
|
|
<span class="badge <?= htmlspecialchars(requestStatusBadgeClass($request['status'])) ?> fs-6"><?= htmlspecialchars(ucfirst($request['status'])) ?></span>
|
|
</div>
|
|
|
|
<div class="detail-grid">
|
|
<div class="detail-card"><span>Employee</span><strong><?= htmlspecialchars($request['employee_name']) ?></strong><small><?= htmlspecialchars($request['employee_email']) ?></small></div>
|
|
<div class="detail-card"><span>Department</span><strong><?= htmlspecialchars($request['department']) ?></strong><small><?= htmlspecialchars($request['submitted_by']) ?> submitted</small></div>
|
|
<div class="detail-card"><span>Dates</span><strong><?= htmlspecialchars(formatDateLabel($request['start_date'])) ?> → <?= htmlspecialchars(formatDateLabel($request['end_date'])) ?></strong><small><?= (int)$request['days_requested'] ?> day(s)</small></div>
|
|
<div class="detail-card"><span>Created</span><strong><?= htmlspecialchars(formatDateLabel($request['created_at'])) ?></strong><small><?= htmlspecialchars(date('H:i', strtotime($request['created_at']))) ?> UTC</small></div>
|
|
</div>
|
|
|
|
<div class="info-block mt-4">
|
|
<div class="small text-secondary text-uppercase mb-2">Reason</div>
|
|
<p class="mb-0"><?= nl2br(htmlspecialchars($request['reason'])) ?></p>
|
|
</div>
|
|
|
|
<?php if ($request['status'] === 'rejected' && $request['rejection_reason']): ?>
|
|
<div class="info-block danger mt-4">
|
|
<div class="small text-danger text-uppercase mb-2">Rejection reason</div>
|
|
<p class="mb-0"><?= nl2br(htmlspecialchars($request['rejection_reason'])) ?></p>
|
|
</div>
|
|
<?php endif; ?>
|
|
</article>
|
|
</div>
|
|
|
|
<div class="col-xl-4">
|
|
<article class="panel-card mb-4">
|
|
<span class="section-kicker">Review actions</span>
|
|
<h3 class="panel-title">Approve or reject</h3>
|
|
<?php if ($request['status'] !== 'pending'): ?>
|
|
<div class="empty-state compact left">
|
|
<h4>Already reviewed</h4>
|
|
<p>This request is locked after status resolution for a cleaner audit trail.</p>
|
|
</div>
|
|
<?php else: ?>
|
|
<form method="post" class="d-grid gap-3">
|
|
<button type="submit" name="action" value="approve" class="btn btn-dark">Approve request</button>
|
|
<div>
|
|
<label for="rejection_reason" class="form-label">Rejection reason</label>
|
|
<textarea class="form-control" id="rejection_reason" name="rejection_reason" rows="4" placeholder="Explain the business reason if you reject."></textarea>
|
|
</div>
|
|
<button type="submit" name="action" value="reject" class="btn btn-outline-danger">Reject request</button>
|
|
</form>
|
|
<?php endif; ?>
|
|
</article>
|
|
|
|
<article class="panel-card">
|
|
<span class="section-kicker">Isolation check</span>
|
|
<h3 class="panel-title">Tenant safety</h3>
|
|
<ul class="feature-list mb-0">
|
|
<li>Detail query is filtered by request id + active <code>company_id</code>.</li>
|
|
<li>List, dashboard, and create flow reuse the same tenant context.</li>
|
|
<li>Switching companies changes visible records without cross-tenant leakage.</li>
|
|
</ul>
|
|
</article>
|
|
</div>
|
|
</section>
|
|
<?php renderPageEnd(); ?>
|