Files
sidak/admin/kartu/add_kartu.php
wartana 7c71bdc1f9 feat: Implement Age Report, Dynamic Headers, KK Auto-Link, and Rebranding
- Added Age Classification Report (admin/laporan/laporan_klasifikasi.php)
- Updated Reports to use Dynamic Village Profile (tb_profil)
- Use 'nama_desa' column for village name
- Enhanced KK Scan to auto-link existing members by NIK
- Updated Index menu for Age Report (Admin & Kaur scope)
- Rebranded Footer to Wartana 2026
- Removed legacy 'Versi 2020' text
2026-01-18 21:51:20 +08:00

328 lines
14 KiB
PHP

<div class="card card-primary">
<div class="card-header">
<h3 class="card-title">
<i class="fa fa-edit"></i> Tambah Data</h3>
</div>
<form action="" method="post" enctype="multipart/form-data">
<div class="card-body">
<div class="form-group row">
<label class="col-sm-2 col-form-label">Foto KK</label>
<div class="col-sm-6">
<img id="preview_kk" src="#" alt="Preview Foto" class="img-fluid mb-2" style="display:none; max-height: 300px; border: 1px solid #ddd; border-radius: 5px;">
<input type="file" class="form-control mb-2" id="foto_kk" name="foto_kk" accept=".jpg, .jpeg, .png">
<button type="button" class="btn btn-success btn-block" id="btnScanKK">
<i class="fas fa-magic"></i> Scan KK dengan AI
</button>
<small class="text-muted">Pilih foto, crop, lalu scan.</small>
<input type="hidden" id="foto_cropped" name="foto_cropped">
</div>
</div>
<?php include 'admin/scanner_modal.php'; ?>
<div class="form-group row">
<label class="col-sm-2 col-form-label">No KK</label>
<div class="col-sm-6">
<input type="text" class="form-control" id="no_kk" name="no_kk" placeholder="No KK" required>
<input type="hidden" id="anggota_json" name="anggota_json">
</div>
</div>
<div class="form-group row">
<label class="col-sm-2 col-form-label">Kpl Keluarga</label>
<div class="col-sm-6">
<input type="text" class="form-control" id="kepala" name="kepala" placeholder="Kpl Keluarga" required>
</div>
</div>
<div class="form-group row">
<label class="col-sm-2 col-form-label">Desa</label>
<div class="col-sm-6">
<input type="text" class="form-control" id="desa" name="desa" placeholder="Desa" required>
</div>
</div>
<div class="form-group row">
<label class="col-sm-2 col-form-label">RT/RW</label>
<div class="col-sm-3">
<input type="text" class="form-control" id="rt" name="rt" placeholder="RT" required>
</div>
<div class="col-sm-3">
<input type="text" class="form-control" id="rw" name="rw" placeholder="RW" required>
</div>
</div>
<div class="form-group row">
<label class="col-sm-2 col-form-label">Kecamatan</label>
<div class="col-sm-6">
<input type="text" class="form-control" id="kec" name="kec" placeholder="Kecamatan" required>
</div>
</div>
<div class="form-group row">
<label class="col-sm-2 col-form-label">Kabupaten</label>
<div class="col-sm-6">
<input type="text" class="form-control" id="kab" name="kab" placeholder="Kabupaten" required>
</div>
</div>
<div class="form-group row">
<label class="col-sm-2 col-form-label">Provinsi</label>
<div class="col-sm-6">
<input type="text" class="form-control" id="prov" name="prov" placeholder="Provinsi" required>
</div>
</div>
</div>
<div class="card-footer">
<input type="submit" name="Simpan" value="Simpan" class="btn btn-info">
<a href="?page=data-kartu" title="Kembali" class="btn btn-secondary">Batal</a>
</div>
</form>
</div>
<script>
window.addEventListener('load', function() {
// Scanner Logic
var inputImage = document.getElementById('foto_kk');
var preview = document.getElementById('preview_kk');
var hiddenInput = document.getElementById('foto_cropped');
window.handleScannerResult = function(base64) {
preview.src = base64;
preview.style.display = 'block'; // Make sure it's visible
hiddenInput.value = base64;
};
inputImage.addEventListener('change', function(e) {
var files = e.target.files;
if (files && files.length > 0) {
if (window.openScanner) {
window.openScanner(files[0]);
}
inputImage.value = '';
}
});
// Scan
document.getElementById('btnScanKK').addEventListener('click', function() {
var fileInput = document.getElementById('foto_kk');
var croppedVal = document.getElementById('foto_cropped').value;
if(fileInput.files.length === 0 && !croppedVal) {
Swal.fire('Info', 'Silakan pilih foto KK terlebih dahulu.', 'warning');
return;
}
var btn = this;
var originalText = btn.innerHTML;
btn.innerHTML = '<i class="fas fa-spinner fa-spin"></i> Menganalisa...';
btn.disabled = true;
var formData = new FormData();
var croppedData = document.getElementById('foto_cropped').value;
if (croppedData) {
var byteString = atob(croppedData.split(',')[1]);
var ab = new ArrayBuffer(byteString.length);
var ia = new Uint8Array(ab);
for (var i = 0; i < byteString.length; i++) {
ia[i] = byteString.charCodeAt(i);
}
var blob = new Blob([ab], { type: 'image/jpeg' });
formData.append('image', blob, 'cropped_kk.jpg');
} else if (fileInput.files.length > 0) {
formData.append('image', fileInput.files[0]);
} else {
Swal.fire('Info', 'Belum ada foto yang dipilih / dicrop.', 'warning');
btn.disabled = false;
btn.innerHTML = originalText;
return;
}
formData.append('type', 'kk');
fetch('admin/api/ocr_helper.php', {
method: 'POST',
body: formData
})
.then(response => response.json())
.then(data => {
if(data.success) {
var d = data.data;
// Show Confirmation
Swal.fire({
title: 'Hasil Scan KK',
html: `
<div style="text-align: left; font-size: 0.9rem;">
<table class="table table-bordered table-sm">
<tr><td width="30%">No KK</td><td><b>${d.no_kk || '-'}</b></td></tr>
<tr><td>Kepala Kel</td><td><b>${d.kepala_keluarga || '-'}</b></td></tr>
<tr><td>Alamat</td><td>${d.desa || '-'}</td></tr>
<tr><td>RT/RW</td><td>${d.rt || '-'}/${d.rw || '-'}</td></tr>
<tr><td>Kecamatan</td><td>${d.kecamatan || '-'}</td></tr>
<tr><td>Kabupaten</td><td>${d.kabupaten || '-'}</td></tr>
<tr><td>Provinsi</td><td>${d.provinsi || '-'}</td></tr>
</table>
<hr>
<strong>Ditemukan ${d.anggota ? d.anggota.length : 0} Anggota:</strong>
<div style="max-height: 150px; overflow-y: auto; background: #f8f9fa; border: 1px solid #ddd; padding: 5px;">
${d.anggota && d.anggota.length > 0 ?
'<ul style="padding-left: 20px; margin-bottom: 0;">' +
d.anggota.map(m => `<li><b>${m.nama}</b><br><small>${m.nik} (${m.hubungan})</small></li>`).join('') +
'</ul>'
: '<i class="text-muted">Tidak ada anggota terdeteksi</i>'}
</div>
<p class="mb-0 text-muted mt-2">Gunakan data ini?</p>
</div>
`,
icon: 'question',
showCancelButton: true,
confirmButtonText: 'Ya, Gunakan',
cancelButtonText: 'Batal'
}).then((result) => {
if (result.value) {
if(d.no_kk) document.getElementsByName('no_kk')[0].value = d.no_kk;
if(d.anggota) document.getElementById('anggota_json').value = JSON.stringify(d.anggota);
if(d.kepala_keluarga) document.getElementsByName('kepala')[0].value = d.kepala_keluarga;
if(d.desa) document.getElementsByName('desa')[0].value = d.desa;
if(d.rt) document.getElementsByName('rt')[0].value = d.rt;
if(d.rw) document.getElementsByName('rw')[0].value = d.rw;
if(d.kecamatan) document.getElementsByName('kec')[0].value = d.kecamatan;
if(d.kabupaten) document.getElementsByName('kab')[0].value = d.kabupaten;
if(d.provinsi) document.getElementsByName('prov')[0].value = d.provinsi;
Swal.fire('Berhasil!', 'Data KK telah masuk ke form.', 'success');
}
});
} else {
Swal.fire('Gagal', data.message, 'error');
}
})
.catch(err => {
console.error(err);
Swal.fire('Error', 'Terjadi kesalahan: ' + err.message, 'error');
})
.finally(() => {
btn.innerHTML = originalText;
btn.disabled = false;
});
});
});
</script>
<?php
if (isset ($_POST['Simpan'])){
$target = 'foto/kk/';
$nama_file = @$_FILES['foto_kk']['name'];
// Cek Crop
if (!empty($_POST['foto_cropped'])) {
$data = $_POST['foto_cropped'];
$parts = explode(',', $data);
$data = $parts[1];
$data = base64_decode($data);
$nama_file = "KK-" . time() . ".jpg";
file_put_contents($target . $nama_file, $data);
} else {
$sumber = @$_FILES['foto_kk']['tmp_name'];
if(!empty($sumber)) {
move_uploaded_file($sumber, $target.$nama_file);
}
}
//mulai proses simpan data
$no_kk = $_POST['no_kk'];
$cek_kk = mysqli_query($koneksi, "SELECT * FROM tb_kk WHERE no_kk='$no_kk'");
if(mysqli_num_rows($cek_kk) > 0){
echo "<script>
Swal.fire({title: 'Gagal',text: 'No KK sudah terdaftar dalam sistem!',icon: 'error',confirmButtonText: 'OK'
}).then((result) => {if (result.value){
window.location = 'index.php?page=add-kartu';
}
})</script>";
return;
}
// Sanitize Inputs
$no_kk = mysqli_real_escape_string($koneksi, $_POST['no_kk']);
$kepala = mysqli_real_escape_string($koneksi, $_POST['kepala']);
$desa = mysqli_real_escape_string($koneksi, $_POST['desa']);
$rt = mysqli_real_escape_string($koneksi, $_POST['rt']);
$rw = mysqli_real_escape_string($koneksi, $_POST['rw']);
$kec = mysqli_real_escape_string($koneksi, $_POST['kec']);
$kab = mysqli_real_escape_string($koneksi, $_POST['kab']);
$prov = mysqli_real_escape_string($koneksi, $_POST['prov']);
$sql_simpan = "INSERT INTO tb_kk (no_kk, kepala, desa, rt, rw, kec, kab, prov, foto_kk) VALUES (
'$no_kk',
'$kepala',
'$desa',
'$rt',
'$rw',
'$kec',
'$kab',
'$prov',
'$nama_file')";
$query_simpan = mysqli_query($koneksi, $sql_simpan);
// Process Auto-Linking Members
$linked_count = 0;
$failed_count = 0;
if ($query_simpan && !empty($_POST['anggota_json'])) {
$id_kk_baru = mysqli_insert_id($koneksi);
$anggota_list = json_decode($_POST['anggota_json'], true);
if (is_array($anggota_list)) {
foreach ($anggota_list as $mem) {
$nik_mem = mysqli_real_escape_string($koneksi, $mem['nik']);
$hub_mem = mysqli_real_escape_string($koneksi, $mem['hubungan']);
// Search Resident by NIK
$sql_cek_pend = "SELECT id_pend FROM tb_pdd WHERE nik='$nik_mem'";
$q_cek_pend = mysqli_query($koneksi, $sql_cek_pend);
if ($row_pend = mysqli_fetch_assoc($q_cek_pend)) {
$id_pend_found = $row_pend['id_pend'];
// Insert into tb_anggota
$sql_add_ang = "INSERT INTO tb_anggota (id_kk, id_pend, hubungan) VALUES ('$id_kk_baru', '$id_pend_found', '$hub_mem')";
mysqli_query($koneksi, $sql_add_ang);
$linked_count++;
} else {
$failed_count++;
}
}
}
}
mysqli_close($koneksi);
if ($query_simpan) {
$msg_add = "";
if($linked_count > 0 || $failed_count > 0) {
$msg_add = "<br>Anggota Terhubung: <b>$linked_count</b><br>Tidak Ditemukan: <b>$failed_count</b>";
}
echo "<script>
Swal.fire({title: 'Tambah Data Berhasil',html: 'Data KK disimpan.$msg_add',icon: 'success',confirmButtonText: 'OK'
}).then((result) => {if (result.value){
window.location = 'index.php?page=data-kartu';
}
})</script>";
}else{
echo "<script>
Swal.fire({title: 'Tambah Data Gagal',text: '',icon: 'error',confirmButtonText: 'OK'
}).then((result) => {if (result.value){
window.location = 'index.php?page=add-kartu';
}
})</script>";
}}
//selesai proses simpan data