%PDF- <> %âãÏÓ endobj 2 0 obj <> endobj 3 0 obj <>/ExtGState<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/Annots[ 28 0 R 29 0 R] /MediaBox[ 0 0 595.5 842.25] /Contents 4 0 R/Group<>/Tabs/S>> endobj ºaâÚÎΞ-ÌE1ÍØÄ÷{òò2ÿ ÛÖ^ÔÀá TÎ{¦?§®¥kuµùÕ5sLOšuY>endobj 2 0 obj<>endobj 2 0 obj<>endobj 2 0 obj<>endobj 2 0 obj<> endobj 2 0 obj<>endobj 2 0 obj<>es 3 0 R>> endobj 2 0 obj<> ox[ 0.000000 0.000000 609.600000 935.600000]/Fi endobj 3 0 obj<> endobj 7 1 obj<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI]>>/Subtype/Form>> stream
<?php
/**
* Admin: form tambah / edit Galeri Kegiatan (judul + banyak foto, tanpa narasi).
*/
require_once dirname(__DIR__) . '/config/config.php';
require_once dirname(__DIR__) . '/includes/auth.php';
require_once dirname(__DIR__) . '/includes/queries.php';
require_once dirname(__DIR__) . '/includes/upload.php';
require_central();
$id = (int) get_param('id', '0');
$isEdit = $id > 0;
$errors = [];
$data = ['judul' => '', 'tanggal' => date('Y-m-d')];
$existing = null;
if ($isEdit) {
$stmt = db()->prepare('SELECT * FROM galeri WHERE id = ?');
$stmt->execute([$id]);
$existing = $stmt->fetch();
if (!$existing) {
set_flash('error', 'Galeri tidak ditemukan.');
redirect('admin/galeri.php');
}
$data = [
'judul' => $existing['judul'],
'tanggal' => date('Y-m-d', strtotime($existing['tanggal'] ?: $existing['created_at'])),
];
}
$MAX_FOTO = 5;
$imgExt = ['jpg', 'jpeg', 'png', 'webp'];
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
csrf_verify();
$data = [
'judul' => post_param('judul'),
'tanggal' => post_param('tanggal'),
];
if ($data['judul'] === '') {
$errors['judul'] = 'Judul kegiatan wajib diisi.';
}
if ($data['tanggal'] === '') {
$data['tanggal'] = date('Y-m-d');
}
$dtCek = DateTime::createFromFormat('Y-m-d', $data['tanggal']);
if (!$dtCek || $dtCek->format('Y-m-d') !== $data['tanggal']) {
$errors['tanggal'] = 'Tanggal tidak valid.';
}
// Normalisasi file multi-upload.
$normFiles = static function ($f): array {
$out = [];
if (!isset($f['name'])) { return $out; }
foreach (array_keys((array) $f['name']) as $k) {
if (($f['error'][$k] ?? UPLOAD_ERR_NO_FILE) === UPLOAD_ERR_NO_FILE) { continue; }
$out[] = ['name' => $f['name'][$k], 'type' => $f['type'][$k] ?? '', 'tmp_name' => $f['tmp_name'][$k], 'error' => $f['error'][$k], 'size' => $f['size'][$k]];
}
return $out;
};
$existingFotos = [];
if ($isEdit) {
$st = db()->prepare('SELECT id, file FROM galeri_foto WHERE galeri_id = ? ORDER BY urutan ASC, id ASC');
$st->execute([$id]);
$existingFotos = $st->fetchAll();
}
$hapusIds = array_map('intval', (array) ($_POST['hapus_foto'] ?? []));
$sisaFotos = array_values(array_filter($existingFotos, static fn ($r) => !in_array((int) $r['id'], $hapusIds, true)));
$newFiles = $normFiles($_FILES['foto'] ?? []);
foreach ($newFiles as $nf) {
$ext = strtolower(pathinfo($nf['name'], PATHINFO_EXTENSION));
if (!in_array($ext, $imgExt, true)) { $errors['foto'] = 'Hanya gambar JPG, PNG, atau WEBP yang diperbolehkan.'; break; }
if ($nf['size'] > MAX_UPLOAD_SIZE) { $errors['foto'] = 'Setiap foto maksimal ' . format_size(MAX_UPLOAD_SIZE) . '.'; break; }
}
// Minimal 1 foto saat galeri baru.
if (!$isEdit && !$newFiles) {
$errors['foto'] = 'Unggah minimal 1 foto kegiatan.';
}
if (count($sisaFotos) + count($newFiles) > $MAX_FOTO) {
$errors['foto'] = 'Maksimal ' . $MAX_FOTO . ' foto per kegiatan. Kurangi unggahan atau hapus sebagian foto.';
}
if (empty($errors)) {
// Slug unik dari judul.
$base = slugify($data['judul']);
$slug = $base !== '' ? $base : 'kegiatan';
$i = 2;
while (true) {
$chk = db()->prepare('SELECT COUNT(*) FROM galeri WHERE slug = ? AND id <> ?');
$chk->execute([$slug, $id]);
if ((int) $chk->fetchColumn() === 0) { break; }
$slug = $base . '-' . $i++;
}
if ($isEdit) {
db()->prepare('UPDATE galeri SET judul = ?, slug = ?, tanggal = ? WHERE id = ?')
->execute([$data['judul'], $slug, $data['tanggal'], $id]);
$galeriId = $id;
foreach ($existingFotos as $r) {
if (in_array((int) $r['id'], $hapusIds, true)) {
delete_upload('galeri', $r['file']);
db()->prepare('DELETE FROM galeri_foto WHERE id = ?')->execute([(int) $r['id']]);
}
}
} else {
db()->prepare('INSERT INTO galeri (judul, slug, tanggal, created_by) VALUES (?, ?, ?, ?)')
->execute([$data['judul'], $slug, $data['tanggal'], current_admin()['id']]);
$galeriId = (int) db()->lastInsertId();
}
$urutan = (int) db()->query('SELECT COALESCE(MAX(urutan), -1) + 1 FROM galeri_foto WHERE galeri_id = ' . (int) $galeriId)->fetchColumn();
foreach ($newFiles as $nf) {
$up = handle_upload($nf, 'galeri', $imgExt);
if ($up['ok']) {
db()->prepare('INSERT INTO galeri_foto (galeri_id, file, urutan) VALUES (?, ?, ?)')->execute([$galeriId, $up['filename'], $urutan++]);
}
}
set_flash('success', $isEdit ? 'Galeri kegiatan berhasil diperbarui.' : 'Galeri kegiatan berhasil ditambahkan.');
redirect('admin/galeri.php');
}
}
$pageTitle = ($isEdit ? 'Edit' : 'Tambah') . ' Galeri Kegiatan — CMS PPID';
$activeMenu = 'galeri';
require __DIR__ . '/partials/head.php';
$val = static fn (string $k) => e($data[$k] ?? '');
$galeri = [];
if ($isEdit) {
$g = db()->prepare('SELECT id, file FROM galeri_foto WHERE galeri_id = ? ORDER BY urutan ASC, id ASC');
$g->execute([$id]);
$galeri = array_values(array_filter($g->fetchAll(), static fn ($r) => is_file(UPLOAD_PATH . '/galeri/' . $r['file'])));
}
$hapusDipilih = array_map('intval', (array) ($_POST['hapus_foto'] ?? []));
?>
<div class="mb-6">
<a href="<?= e(url('admin/galeri.php')) ?>" class="text-sm text-slate-500 hover:text-mateng-green inline-flex items-center gap-2 mb-3"><i class="fas fa-arrow-left"></i> Kembali ke daftar</a>
<h2 class="text-2xl font-bold text-slate-900"><?= $isEdit ? 'Edit Galeri Kegiatan' : 'Tambah Galeri Kegiatan' ?></h2>
</div>
<form method="post" enctype="multipart/form-data" class="max-w-3xl bg-white border border-slate-100 rounded-xl shadow-sm p-6 sm:p-8 space-y-5">
<?= csrf_field() ?>
<div>
<label class="block text-sm font-medium text-slate-700 mb-1.5">Judul Kegiatan <span class="text-red-500">*</span></label>
<input type="text" name="judul" value="<?= $val('judul') ?>" placeholder="mis. Sosialisasi Keterbukaan Informasi Publik 2026" class="w-full rounded-lg border px-4 py-2.5 outline-none focus:ring-4 <?= isset($errors['judul']) ? 'border-red-300 focus:ring-red-100' : 'border-slate-300 focus:border-mateng-green focus:ring-green-100' ?>">
<?php if (isset($errors['judul'])): ?><p class="text-xs text-red-500 mt-1"><?= e($errors['judul']) ?></p><?php endif; ?>
</div>
<div>
<label class="block text-sm font-medium text-slate-700 mb-1.5">Tanggal Kegiatan</label>
<input type="date" name="tanggal" value="<?= $val('tanggal') ?>" class="w-full sm:w-56 rounded-lg border px-4 py-2.5 outline-none focus:ring-4 <?= isset($errors['tanggal']) ? 'border-red-300 focus:ring-red-100' : 'border-slate-300 focus:border-mateng-green focus:ring-green-100' ?>">
<?php if (isset($errors['tanggal'])): ?><p class="text-xs text-red-500 mt-1"><?= e($errors['tanggal']) ?></p><?php endif; ?>
</div>
<div>
<label class="block text-sm font-medium text-slate-700 mb-1.5">Foto Kegiatan <span class="text-xs text-slate-400">(maks <?= $MAX_FOTO ?> foto — foto pertama menjadi sampul)</span></label>
<?php if ($isEdit && $galeri): ?>
<div class="grid grid-cols-3 sm:grid-cols-5 gap-3 mb-2">
<?php foreach ($galeri as $gi => $g): ?>
<div class="relative">
<img src="<?= e(UPLOAD_URL . '/galeri/' . $g['file']) ?>" class="w-full h-20 object-cover rounded-lg border border-slate-200" alt="">
<?php if ($gi === 0): ?><span class="absolute top-1 left-1 bg-mateng-green text-white text-[10px] font-bold px-1.5 py-0.5 rounded shadow">Sampul</span><?php endif; ?>
<label class="absolute bottom-1 right-1 flex items-center gap-1 bg-white/90 text-red-600 text-[10px] font-semibold px-1.5 py-0.5 rounded shadow cursor-pointer">
<input type="checkbox" name="hapus_foto[]" value="<?= (int) $g['id'] ?>" class="accent-red-600" <?= in_array((int) $g['id'], $hapusDipilih, true) ? 'checked' : '' ?>> Hapus
</label>
</div>
<?php endforeach; ?>
</div>
<p class="text-xs text-slate-400 mb-2">Centang <span class="text-red-600 font-medium">Hapus</span> pada foto yang ingin dibuang. Tambahkan foto baru di bawah.</p>
<?php endif; ?>
<input type="file" name="foto[]" accept="image/*" multiple class="js-img-preview w-full text-sm text-slate-600 file:mr-3 file:py-2 file:px-4 file:rounded-lg file:border-0 file:bg-mateng-green/10 file:text-mateng-green file:font-semibold hover:file:bg-mateng-green/20 file:cursor-pointer" data-target="#fotoPreviewGaleri">
<div id="fotoPreviewGaleri" class="grid grid-cols-3 sm:grid-cols-5 gap-3 mt-3 empty:hidden"></div>
<?php if (isset($errors['foto'])): ?><p class="text-xs text-red-500 mt-1"><?= e($errors['foto']) ?></p><?php endif; ?>
<p class="text-xs text-slate-400 mt-1">Format: JPG, PNG, WEBP. Maks <?= format_size(MAX_UPLOAD_SIZE) ?>/foto. Bisa pilih beberapa file sekaligus.</p>
</div>
<div class="flex gap-3 pt-2">
<button type="submit" class="bg-mateng-green hover:bg-green-700 text-white font-bold px-6 py-3 rounded-lg transition-colors flex items-center gap-2"><i class="fas fa-save"></i> <?= $isEdit ? 'Perbarui' : 'Simpan' ?></button>
<a href="<?= e(url('admin/galeri.php')) ?>" class="bg-slate-100 hover:bg-slate-200 text-slate-700 font-semibold px-6 py-3 rounded-lg transition-colors">Batal</a>
</div>
</form>
<?php require __DIR__ . '/partials/foot.php'; ?>