646 lines
23 KiB
PHP
646 lines
23 KiB
PHP
<?php
|
||
|
||
declare(strict_types=1);
|
||
|
||
namespace App\Controllers\Admin;
|
||
|
||
use App\Services\ApiClient;
|
||
use CodeIgniter\Exceptions\PageNotFoundException;
|
||
use CodeIgniter\HTTP\ResponseInterface;
|
||
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
|
||
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
||
use PhpOffice\PhpSpreadsheet\Style\Alignment;
|
||
use PhpOffice\PhpSpreadsheet\Style\Border;
|
||
use PhpOffice\PhpSpreadsheet\Style\Fill;
|
||
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
|
||
|
||
/**
|
||
* Daftar & detail presensi lewat `/api/admin/presensi*`.
|
||
*/
|
||
class Presensi extends BaseAdminController
|
||
{
|
||
public function index(): ResponseInterface|string
|
||
{
|
||
if (($deny = $this->enforceAccess('presensi')) !== null) {
|
||
return $deny;
|
||
}
|
||
|
||
$today = date('Y-m-d');
|
||
$dari = (string) ($this->request->getGet('tanggal_dari') ?? $today);
|
||
$sampai = (string) ($this->request->getGet('tanggal_sampai') ?? $today);
|
||
$page = max(1, (int) ($this->request->getGet('page') ?? 1));
|
||
$q = (string) ($this->request->getGet('q') ?? '');
|
||
|
||
$errors = [];
|
||
$payload = null;
|
||
|
||
$r = $this->apiAdminGet('presensi', [
|
||
'tanggal_dari' => $dari,
|
||
'tanggal_sampai' => $sampai,
|
||
'page' => (string) $page,
|
||
'per_page' => '30',
|
||
'q' => $q,
|
||
]);
|
||
|
||
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 presensi') : 'Gagal memuat presensi');
|
||
}
|
||
|
||
return view('admin/presensi/index', [
|
||
'payload' => $payload,
|
||
'errors' => $errors,
|
||
'dari' => $dari,
|
||
'sampai' => $sampai,
|
||
'page' => $page,
|
||
'q' => $q,
|
||
]);
|
||
}
|
||
|
||
/**
|
||
* Ambil semua baris presensi untuk ekspor (sama dengan filter list; maks. 100 halaman × 200 baris).
|
||
*
|
||
* @return array{ok: true, rows: list<array<string, mixed>>, dari: string, sampai: string, q: string}|array{ok: false, error: string, dari: string, sampai: string, q: string}
|
||
*/
|
||
private function fetchPresensiExportRows(): array
|
||
{
|
||
$today = date('Y-m-d');
|
||
$dari = (string) ($this->request->getGet('tanggal_dari') ?? $today);
|
||
$sampai = (string) ($this->request->getGet('tanggal_sampai') ?? $today);
|
||
$q = (string) ($this->request->getGet('q') ?? '');
|
||
$per = 200;
|
||
$maxPg = 100;
|
||
$allRows = [];
|
||
$totalPage = 1;
|
||
|
||
for ($page = 1; $page <= $totalPage && $page <= $maxPg; $page++) {
|
||
$r = $this->apiAdminGet('presensi', [
|
||
'tanggal_dari' => $dari,
|
||
'tanggal_sampai' => $sampai,
|
||
'page' => (string) $page,
|
||
'per_page' => (string) $per,
|
||
'q' => $q,
|
||
]);
|
||
|
||
if (! $r['transport_ok'] || ! ApiClient::isSuccess($r['json'])) {
|
||
$msg = $r['error'] ?? (is_array($r['json']) ? (string) ($r['json']['pesan'] ?? 'Gagal mengekspor') : 'Gagal mengekspor');
|
||
|
||
return ['ok' => false, 'error' => $msg, 'dari' => $dari, 'sampai' => $sampai, 'q' => $q];
|
||
}
|
||
|
||
$payload = $r['json']['data'] ?? [];
|
||
$rows = is_array($payload['rows'] ?? null) ? $payload['rows'] : [];
|
||
if ($page === 1) {
|
||
$totalPage = max(1, min($maxPg, (int) ($payload['total_page'] ?? 1)));
|
||
}
|
||
$allRows = array_merge($allRows, $rows);
|
||
}
|
||
|
||
return ['ok' => true, 'rows' => $allRows, 'dari' => $dari, 'sampai' => $sampai, 'q' => $q];
|
||
}
|
||
|
||
/**
|
||
* Unduh CSV semua baris presensi untuk filter yang sama (paginasi digabung, maks. 100 halaman × 200 baris).
|
||
*/
|
||
public function exportCsv(): ResponseInterface
|
||
{
|
||
if (($deny = $this->enforceAccess('presensi')) !== null) {
|
||
return $deny;
|
||
}
|
||
|
||
$fetched = $this->fetchPresensiExportRows();
|
||
if (! $fetched['ok']) {
|
||
return redirect()->to(site_url('admin/presensi?' . http_build_query(array_filter([
|
||
'tanggal_dari' => $fetched['dari'],
|
||
'tanggal_sampai' => $fetched['sampai'],
|
||
'q' => $fetched['q'],
|
||
]))))->with('error', $fetched['error']);
|
||
}
|
||
|
||
$allRows = $fetched['rows'];
|
||
$dari = $fetched['dari'];
|
||
$sampai = $fetched['sampai'];
|
||
|
||
$fh = fopen('php://memory', 'r+b');
|
||
if ($fh === false) {
|
||
return redirect()->to(site_url('admin/presensi'))->with('error', 'Gagal membuat file CSV.');
|
||
}
|
||
|
||
fwrite($fh, "\xEF\xBB\xBF");
|
||
fputcsv($fh, [
|
||
'id_presensi',
|
||
'tanggal',
|
||
'nama_lengkap',
|
||
'nip',
|
||
'status',
|
||
'jam_masuk',
|
||
'ket_masuk',
|
||
'jam_pulang',
|
||
'ket_pulang',
|
||
'istirahat',
|
||
]);
|
||
|
||
foreach ($allRows as $pr) {
|
||
if (! is_array($pr)) {
|
||
continue;
|
||
}
|
||
$jm = $pr['jam_masuk'] ?? null;
|
||
$jp = $pr['jam_pulang'] ?? null;
|
||
$mi = $pr['mulai_istirahat'] ?? null;
|
||
$bi = $pr['beres_istirahat'] ?? null;
|
||
$ist = '';
|
||
if (! empty($mi) || ! empty($bi)) {
|
||
$ist = (empty($mi) ? '—' : self::formatTimeForCsv((string) $mi)) . ' → ' . (empty($bi) ? '—' : self::formatTimeForCsv((string) $bi));
|
||
}
|
||
|
||
fputcsv($fh, [
|
||
(string) ($pr['id_presensi'] ?? ''),
|
||
(string) ($pr['tanggal'] ?? ''),
|
||
(string) ($pr['nama_lengkap'] ?? ''),
|
||
(string) ($pr['nip'] ?? ''),
|
||
self::presensiStatusLabelForCsv($pr),
|
||
self::formatTimeForCsv($jm !== null ? (string) $jm : ''),
|
||
(string) ($pr['ket_masuk'] ?? ''),
|
||
self::formatTimeForCsv($jp !== null ? (string) $jp : ''),
|
||
(string) ($pr['ket_pulang'] ?? ''),
|
||
$ist,
|
||
]);
|
||
}
|
||
|
||
rewind($fh);
|
||
$csv = stream_get_contents($fh) ?: '';
|
||
fclose($fh);
|
||
|
||
$fn = 'presensi_' . preg_replace('/[^0-9-]/', '', $dari) . '_' . preg_replace('/[^0-9-]/', '', $sampai) . '_' . date('His') . '.csv';
|
||
|
||
return $this->response
|
||
->setHeader('Content-Type', 'text/csv; charset=UTF-8')
|
||
->setHeader('Content-Disposition', 'attachment; filename="' . str_replace(['"', "\r", "\n"], '', $fn) . '"')
|
||
->setBody($csv);
|
||
}
|
||
|
||
/**
|
||
* Unduh Excel (.xlsx) dengan kolom rapi: header tebal, filter, lebar kolom, teks ket. dibungkus.
|
||
*/
|
||
public function exportXlsx(): ResponseInterface
|
||
{
|
||
if (($deny = $this->enforceAccess('presensi')) !== null) {
|
||
return $deny;
|
||
}
|
||
|
||
$fetched = $this->fetchPresensiExportRows();
|
||
if (! $fetched['ok']) {
|
||
return redirect()->to(site_url('admin/presensi?' . http_build_query(array_filter([
|
||
'tanggal_dari' => $fetched['dari'],
|
||
'tanggal_sampai' => $fetched['sampai'],
|
||
'q' => $fetched['q'],
|
||
]))))->with('error', $fetched['error']);
|
||
}
|
||
|
||
$allRows = $fetched['rows'];
|
||
$dari = $fetched['dari'];
|
||
$sampai = $fetched['sampai'];
|
||
|
||
$spreadsheet = new Spreadsheet();
|
||
$sheet = $spreadsheet->getActiveSheet();
|
||
$sheet->setTitle('Presensi');
|
||
|
||
$headers = [
|
||
'ID presensi',
|
||
'Tanggal',
|
||
'Nama lengkap',
|
||
'NIP',
|
||
'Status',
|
||
'Jam masuk',
|
||
'Ket. masuk',
|
||
'Jam pulang',
|
||
'Ket. pulang',
|
||
'Istirahat',
|
||
];
|
||
foreach ($headers as $i => $h) {
|
||
$sheet->setCellValue(Coordinate::stringFromColumnIndex($i + 1) . '1', $h);
|
||
}
|
||
|
||
$headerStyle = [
|
||
'font' => ['bold' => true, 'color' => ['rgb' => 'FFFFFF']],
|
||
'fill' => [
|
||
'fillType' => Fill::FILL_SOLID,
|
||
'startColor' => ['rgb' => '1F4E79'],
|
||
],
|
||
'alignment' => [
|
||
'horizontal' => Alignment::HORIZONTAL_CENTER,
|
||
'vertical' => Alignment::VERTICAL_CENTER,
|
||
],
|
||
'borders' => [
|
||
'allBorders' => ['borderStyle' => Border::BORDER_THIN, 'color' => ['rgb' => 'CCCCCC']],
|
||
],
|
||
];
|
||
$sheet->getStyle('A1:J1')->applyFromArray($headerStyle);
|
||
$sheet->getRowDimension(1)->setRowHeight(22);
|
||
|
||
$rowNum = 2;
|
||
foreach ($allRows as $pr) {
|
||
if (! is_array($pr)) {
|
||
continue;
|
||
}
|
||
$jm = $pr['jam_masuk'] ?? null;
|
||
$jp = $pr['jam_pulang'] ?? null;
|
||
$mi = $pr['mulai_istirahat'] ?? null;
|
||
$bi = $pr['beres_istirahat'] ?? null;
|
||
$ist = '';
|
||
if (! empty($mi) || ! empty($bi)) {
|
||
$ist = (empty($mi) ? '—' : self::formatTimeForCsv((string) $mi)) . ' → ' . (empty($bi) ? '—' : self::formatTimeForCsv((string) $bi));
|
||
}
|
||
|
||
$sheet->setCellValue('A' . $rowNum, (string) ($pr['id_presensi'] ?? ''));
|
||
$sheet->setCellValue('B' . $rowNum, (string) ($pr['tanggal'] ?? ''));
|
||
$sheet->setCellValue('C' . $rowNum, (string) ($pr['nama_lengkap'] ?? ''));
|
||
$sheet->setCellValue('D' . $rowNum, (string) ($pr['nip'] ?? ''));
|
||
$sheet->setCellValue('E' . $rowNum, self::presensiStatusLabelForCsv($pr));
|
||
$sheet->setCellValue('F' . $rowNum, self::formatTimeForCsv($jm !== null ? (string) $jm : ''));
|
||
$sheet->setCellValue('G' . $rowNum, (string) ($pr['ket_masuk'] ?? ''));
|
||
$sheet->setCellValue('H' . $rowNum, self::formatTimeForCsv($jp !== null ? (string) $jp : ''));
|
||
$sheet->setCellValue('I' . $rowNum, (string) ($pr['ket_pulang'] ?? ''));
|
||
$sheet->setCellValue('J' . $rowNum, $ist);
|
||
$rowNum++;
|
||
}
|
||
|
||
$lastRow = max(2, $rowNum - 1);
|
||
if ($lastRow >= 2) {
|
||
$sheet->getStyle('A2:J' . $lastRow)->applyFromArray([
|
||
'borders' => [
|
||
'allBorders' => ['borderStyle' => Border::BORDER_THIN, 'color' => ['rgb' => 'DDDDDD']],
|
||
],
|
||
'alignment' => [
|
||
'vertical' => Alignment::VERTICAL_TOP,
|
||
],
|
||
]);
|
||
$sheet->getStyle('G2:G' . $lastRow)->getAlignment()->setWrapText(true);
|
||
$sheet->getStyle('I2:I' . $lastRow)->getAlignment()->setWrapText(true);
|
||
$sheet->getStyle('A2:A' . $lastRow)->getNumberFormat()->setFormatCode('@');
|
||
$sheet->getStyle('D2:D' . $lastRow)->getNumberFormat()->setFormatCode('@');
|
||
}
|
||
|
||
$sheet->freezePane('A2');
|
||
$sheet->setAutoFilter('A1:J1');
|
||
|
||
$sheet->getColumnDimension('A')->setWidth(14);
|
||
$sheet->getColumnDimension('B')->setWidth(12);
|
||
$sheet->getColumnDimension('C')->setWidth(28);
|
||
$sheet->getColumnDimension('D')->setWidth(18);
|
||
$sheet->getColumnDimension('E')->setWidth(14);
|
||
$sheet->getColumnDimension('F')->setWidth(11);
|
||
$sheet->getColumnDimension('G')->setWidth(36);
|
||
$sheet->getColumnDimension('H')->setWidth(11);
|
||
$sheet->getColumnDimension('I')->setWidth(36);
|
||
$sheet->getColumnDimension('J')->setWidth(22);
|
||
|
||
$tmp = tempnam(sys_get_temp_dir(), 'prxlsx');
|
||
if ($tmp === false) {
|
||
return redirect()->to(site_url('admin/presensi'))->with('error', 'Gagal membuat file Excel.');
|
||
}
|
||
|
||
try {
|
||
(new Xlsx($spreadsheet))->save($tmp);
|
||
} catch (\Throwable $e) {
|
||
@unlink($tmp);
|
||
log_message('error', 'exportXlsx: {message}', ['message' => $e->getMessage()]);
|
||
|
||
return redirect()->to(site_url('admin/presensi?' . http_build_query(array_filter([
|
||
'tanggal_dari' => $dari,
|
||
'tanggal_sampai' => $sampai,
|
||
'q' => $fetched['q'],
|
||
]))))->with('error', 'Gagal menulis file Excel. Pastikan ekstensi PHP zip aktif.');
|
||
}
|
||
|
||
$binary = (string) file_get_contents($tmp);
|
||
@unlink($tmp);
|
||
$spreadsheet->disconnectWorksheets();
|
||
|
||
$fn = 'presensi_' . preg_replace('/[^0-9-]/', '', $dari) . '_' . preg_replace('/[^0-9-]/', '', $sampai) . '_' . date('His') . '.xlsx';
|
||
|
||
return $this->response
|
||
->setHeader('Content-Type', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet')
|
||
->setHeader('Content-Disposition', 'attachment; filename="' . str_replace(['"', "\r", "\n"], '', $fn) . '"')
|
||
->setBody($binary);
|
||
}
|
||
|
||
/**
|
||
* @param array<string, mixed> $pr
|
||
*/
|
||
private static function presensiStatusLabelForCsv(array $pr): string
|
||
{
|
||
$jm = $pr['jam_masuk'] ?? null;
|
||
$jp = $pr['jam_pulang'] ?? null;
|
||
$hadirMasuk = $jm !== null && $jm !== '';
|
||
$hadirPulang = $jp !== null && $jp !== '';
|
||
|
||
if ($hadirMasuk && $hadirPulang) {
|
||
return 'Lengkap';
|
||
}
|
||
if ($hadirMasuk || $hadirPulang) {
|
||
return 'Sebagian';
|
||
}
|
||
|
||
return 'Belum rekam';
|
||
}
|
||
|
||
private static function formatTimeForCsv(string $t): string
|
||
{
|
||
if ($t === '') {
|
||
return '';
|
||
}
|
||
$ts = strtotime($t);
|
||
|
||
return $ts ? date('H:i', $ts) : $t;
|
||
}
|
||
|
||
/**
|
||
* Layani foto absen masuk/pulang dari disk (public/assets/uploads/absen/…).
|
||
*/
|
||
public function foto(string $jenis, string $file): ResponseInterface
|
||
{
|
||
if (($deny = $this->enforceAccess('presensi')) !== null) {
|
||
return $deny;
|
||
}
|
||
|
||
$jenis = strtolower($jenis);
|
||
if ($jenis !== 'masuk' && $jenis !== 'pulang') {
|
||
throw PageNotFoundException::forPageNotFound();
|
||
}
|
||
|
||
$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 . 'absen' . DIRECTORY_SEPARATOR . $jenis . DIRECTORY_SEPARATOR . $safe;
|
||
if (! is_file($path)) {
|
||
throw PageNotFoundException::forPageNotFound(
|
||
'Foto tidak ada di server. Salin folder absen/masuk dan absen/pulang dari CI3 ke: public/assets/uploads/absen/',
|
||
);
|
||
}
|
||
|
||
$ext = strtolower((string) pathinfo($safe, PATHINFO_EXTENSION));
|
||
$mime = match ($ext) {
|
||
'jpg', 'jpeg' => 'image/jpeg',
|
||
'png' => 'image/png',
|
||
'gif' => 'image/gif',
|
||
'webp' => 'image/webp',
|
||
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('presensi')) !== null) {
|
||
return $deny;
|
||
}
|
||
|
||
$errors = [];
|
||
$row = null;
|
||
|
||
$r = $this->apiAdminGet('presensi/' . $id);
|
||
if ($r['transport_ok'] && ApiClient::isSuccess($r['json'])) {
|
||
$row = $r['json']['data'] ?? null;
|
||
} else {
|
||
$errors[] = $r['error'] ?? (is_array($r['json']) ? (string) ($r['json']['pesan'] ?? 'Gagal memuat detail') : 'Gagal memuat detail');
|
||
}
|
||
|
||
return view('admin/presensi/detail', [
|
||
'row' => is_array($row) ? $row : null,
|
||
'errors' => $errors,
|
||
]);
|
||
}
|
||
|
||
public function lapangan(): ResponseInterface|string
|
||
{
|
||
if (($deny = $this->enforceAccess('presensi')) !== null) {
|
||
return $deny;
|
||
}
|
||
|
||
$errors = [];
|
||
$payload = null;
|
||
$pegawai = [];
|
||
$r = $this->apiAdminGet('presensi/dilapangan');
|
||
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') : 'Gagal');
|
||
}
|
||
$p = $this->apiAdminGet('pegawai', ['page' => '1', 'per_page' => '500', 'q' => '']);
|
||
if ($p['transport_ok'] && ApiClient::isSuccess($p['json'])) {
|
||
$d = $p['json']['data'] ?? [];
|
||
$pegawai = is_array($d['rows'] ?? null) ? $d['rows'] : [];
|
||
}
|
||
|
||
return view('admin/presensi/lapangan', [
|
||
'payload' => is_array($payload) ? $payload : null,
|
||
'pegawai' => $pegawai,
|
||
'errors' => $errors,
|
||
]);
|
||
}
|
||
|
||
public function lapanganSave(): ResponseInterface
|
||
{
|
||
if (($deny = $this->enforceAccess('presensi')) !== null) {
|
||
return $deny;
|
||
}
|
||
|
||
return $this->toolPost('presensi/dilapangan/save', 'admin/presensi/lapangan');
|
||
}
|
||
|
||
public function lapanganDelete(int $id): ResponseInterface
|
||
{
|
||
if (($deny = $this->enforceAccess('presensi')) !== null) {
|
||
return $deny;
|
||
}
|
||
|
||
return $this->toolPost('presensi/dilapangan/delete/' . $id, 'admin/presensi/lapangan', []);
|
||
}
|
||
|
||
public function lembur(): ResponseInterface|string
|
||
{
|
||
if (($deny = $this->enforceAccess('presensi')) !== null) {
|
||
return $deny;
|
||
}
|
||
|
||
$errors = [];
|
||
$payload = null;
|
||
$pegawai = [];
|
||
$r = $this->apiAdminGet('presensi/lembur');
|
||
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') : 'Gagal');
|
||
}
|
||
$p = $this->apiAdminGet('pegawai', ['page' => '1', 'per_page' => '500', 'q' => '']);
|
||
if ($p['transport_ok'] && ApiClient::isSuccess($p['json'])) {
|
||
$d = $p['json']['data'] ?? [];
|
||
$pegawai = is_array($d['rows'] ?? null) ? $d['rows'] : [];
|
||
}
|
||
|
||
return view('admin/presensi/lembur', [
|
||
'payload' => is_array($payload) ? $payload : null,
|
||
'pegawai' => $pegawai,
|
||
'errors' => $errors,
|
||
]);
|
||
}
|
||
|
||
public function lemburSave(): ResponseInterface
|
||
{
|
||
if (($deny = $this->enforceAccess('presensi')) !== null) {
|
||
return $deny;
|
||
}
|
||
|
||
return $this->toolPost('presensi/lembur/save', 'admin/presensi/lembur');
|
||
}
|
||
|
||
public function lemburDelete(int $id): ResponseInterface
|
||
{
|
||
if (($deny = $this->enforceAccess('presensi')) !== null) {
|
||
return $deny;
|
||
}
|
||
|
||
return $this->toolPost('presensi/lembur/delete/' . $id, 'admin/presensi/lembur', []);
|
||
}
|
||
|
||
public function libur(): ResponseInterface|string
|
||
{
|
||
if (($deny = $this->enforceAccess('presensi_libur')) !== null) {
|
||
return $deny;
|
||
}
|
||
|
||
return $this->toolPage('presensi/libur', 'admin/presensi/libur', false);
|
||
}
|
||
|
||
public function liburSave(): ResponseInterface
|
||
{
|
||
if (($deny = $this->enforceAccess('presensi_libur')) !== null) {
|
||
return $deny;
|
||
}
|
||
|
||
return $this->toolPost('presensi/libur/save', 'admin/presensi/libur');
|
||
}
|
||
|
||
public function liburDelete(int $id): ResponseInterface
|
||
{
|
||
if (($deny = $this->enforceAccess('presensi_libur')) !== null) {
|
||
return $deny;
|
||
}
|
||
|
||
return $this->toolPost('presensi/libur/delete/' . $id, 'admin/presensi/libur', []);
|
||
}
|
||
|
||
public function jadwal(): ResponseInterface|string
|
||
{
|
||
if (($deny = $this->enforceAccess('presensi_jadwal')) !== null) {
|
||
return $deny;
|
||
}
|
||
|
||
return $this->toolPage('presensi/jadwal', 'admin/presensi/jadwal', false);
|
||
}
|
||
|
||
public function jadwalSave(): ResponseInterface
|
||
{
|
||
if (($deny = $this->enforceAccess('presensi_jadwal')) !== null) {
|
||
return $deny;
|
||
}
|
||
|
||
return $this->toolPost('presensi/jadwal/save', 'admin/presensi/jadwal');
|
||
}
|
||
|
||
public function jadwalDelete(int $id): ResponseInterface
|
||
{
|
||
if (($deny = $this->enforceAccess('presensi_jadwal')) !== null) {
|
||
return $deny;
|
||
}
|
||
|
||
return $this->toolPost('presensi/jadwal/delete/' . $id, 'admin/presensi/jadwal', []);
|
||
}
|
||
|
||
public function aktivitas(): ResponseInterface|string
|
||
{
|
||
if (($deny = $this->enforceAccess('presensi')) !== null) {
|
||
return $deny;
|
||
}
|
||
|
||
$page = max(1, (int) ($this->request->getGet('page') ?? 1));
|
||
$errors = [];
|
||
$payload = null;
|
||
$r = $this->apiAdminGet('presensi/aktivitas', ['page' => (string) $page, 'per_page' => '20']);
|
||
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') : 'Gagal');
|
||
}
|
||
|
||
return view('admin/presensi/aktivitas', [
|
||
'payload' => is_array($payload) ? $payload : null,
|
||
'errors' => $errors,
|
||
'page' => $page,
|
||
]);
|
||
}
|
||
|
||
public function aktivitasDelete(int $id): ResponseInterface
|
||
{
|
||
if (($deny = $this->enforceAccess('presensi')) !== null) {
|
||
return $deny;
|
||
}
|
||
|
||
return $this->toolPost('presensi/aktivitas/delete/' . $id, 'admin/presensi/aktivitas', []);
|
||
}
|
||
|
||
/**
|
||
* @return ResponseInterface|string
|
||
*/
|
||
private function toolPage(string $apiPath, string $view, bool $loadRefs)
|
||
{
|
||
$errors = [];
|
||
$payload = null;
|
||
$refs = null;
|
||
$r = $this->apiAdminGet($apiPath);
|
||
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 data') : 'Gagal memuat data');
|
||
}
|
||
if ($loadRefs) {
|
||
$ref = $this->apiAdminGet('references');
|
||
if ($ref['transport_ok'] && ApiClient::isSuccess($ref['json'])) {
|
||
$refs = $ref['json']['data'] ?? null;
|
||
}
|
||
}
|
||
|
||
return view($view, [
|
||
'payload' => is_array($payload) ? $payload : null,
|
||
'refs' => is_array($refs) ? $refs : null,
|
||
'errors' => $errors,
|
||
]);
|
||
}
|
||
|
||
/**
|
||
* @param array<string, scalar|null> $merge
|
||
*/
|
||
private function toolPost(string $apiPath, string $redirectPath, array $merge = []): ResponseInterface
|
||
{
|
||
$post = array_merge($this->request->getPost(), $merge);
|
||
$r = $this->apiAdminPost($apiPath, $post);
|
||
if ($r['transport_ok'] && ApiClient::isSuccess($r['json'])) {
|
||
return redirect()->to(site_url($redirectPath))->with('message', (string) ($r['json']['pesan'] ?? 'OK'));
|
||
}
|
||
$msg = $r['error'] ?? (is_array($r['json']) ? (string) ($r['json']['pesan'] ?? 'Gagal') : 'Gagal');
|
||
|
||
return redirect()->to(site_url($redirectPath))->with('error', $msg);
|
||
}
|
||
}
|