enforceAccess('cuti')) !== null) { return $deny; } $status = (string) ($this->request->getGet('status') ?? 'Waiting'); $page = max(1, (int) ($this->request->getGet('page') ?? 1)); $errors = []; $payload = null; $r = $this->apiAdminGet('cuti', [ 'status' => $status, 'page' => (string) $page, 'per_page' => '30', ]); if ($r['transport_ok'] && ApiClient::isSuccess($r['json'])) { $payload = $r['json']['data'] ?? null; } else { $errors[] = $r['error'] ?? (is_array($r['json']) ? (string) ($r['json']['pesan'] ?? 'Gagal memuat cuti') : 'Gagal memuat cuti'); } helper('cuti_display'); return view('admin/cuti/index', [ 'payload' => $payload, 'errors' => $errors, 'status' => $status, 'page' => $page, ]); } /** * Layani dokumen cuti dari disk (setara file statis CI3 di assets/uploads/dokcuti/). * Dipakai saat berkas belum dilayani langsung oleh web server (mis. file belum di-copy ke public). */ public function dokumen(string $file): ResponseInterface { if (($deny = $this->enforceAccess('cuti')) !== null) { return $deny; } $safe = basename(rawurldecode($file)); if ($safe === '' || $safe === '.' || $safe === '..') { throw PageNotFoundException::forPageNotFound(); } if (! preg_match('/^[A-Za-z0-9._-]+$/', $safe)) { throw PageNotFoundException::forPageNotFound(); } $path = FCPATH . 'assets' . DIRECTORY_SEPARATOR . 'uploads' . DIRECTORY_SEPARATOR . 'dokcuti' . DIRECTORY_SEPARATOR . $safe; if (! is_file($path)) { throw PageNotFoundException::forPageNotFound( 'Berkas tidak ada di server. Salin isi folder dokcuti dari CI3 ke: public/assets/uploads/dokcuti/', ); } $ext = strtolower((string) pathinfo($safe, PATHINFO_EXTENSION)); $mime = match ($ext) { 'jpg', 'jpeg' => 'image/jpeg', 'png' => 'image/png', 'gif' => 'image/gif', 'webp' => 'image/webp', 'pdf' => 'application/pdf', default => 'application/octet-stream', }; $this->response->setHeader('Content-Type', $mime); $this->response->setHeader('Content-Disposition', 'inline; filename="' . addcslashes($safe, '"\\') . '"'); return $this->response->setBody((string) file_get_contents($path)); } public function detail(int $id): ResponseInterface|string { if (($deny = $this->enforceAccess('cuti')) !== null) { return $deny; } $errors = []; $bundle = null; $r = $this->apiAdminGet('cuti/' . $id); if ($r['transport_ok'] && ApiClient::isSuccess($r['json'])) { $bundle = $r['json']['data'] ?? null; } else { $errors[] = $r['error'] ?? (is_array($r['json']) ? (string) ($r['json']['pesan'] ?? 'Gagal memuat detail') : 'Gagal memuat detail'); } helper('cuti_display'); return view('admin/cuti/detail', [ 'bundle' => is_array($bundle) ? $bundle : null, 'errors' => $errors, 'id' => $id, ]); } public function approve(int $id): ResponseInterface { if (($deny = $this->enforceAccess('cuti')) !== null) { return $deny; } $res = $this->apiAdminPost('cuti/approve', ['id_cuti' => (string) $id]); if ($res['transport_ok'] && ApiClient::isSuccess($res['json'])) { return redirect()->to(site_url('admin/cuti'))->with('message', (string) ($res['json']['pesan'] ?? 'Disetujui')); } $msg = is_array($res['json']) ? (string) ($res['json']['pesan'] ?? 'Gagal') : ($res['error'] ?? 'Gagal'); return redirect()->back()->with('error', $msg); } public function reject(int $id): ResponseInterface { if (($deny = $this->enforceAccess('cuti')) !== null) { return $deny; } $alasan = (string) ($this->request->getPost('alasan_tolak') ?? ''); $res = $this->apiAdminPost('cuti/reject', [ 'id_cuti' => (string) $id, 'alasan_tolak' => $alasan, ]); if ($res['transport_ok'] && ApiClient::isSuccess($res['json'])) { return redirect()->to(site_url('admin/cuti'))->with('message', (string) ($res['json']['pesan'] ?? 'Ditolak')); } $msg = is_array($res['json']) ? (string) ($res['json']['pesan'] ?? 'Gagal') : ($res['error'] ?? 'Gagal'); return redirect()->back()->withInput()->with('error', $msg); } }