Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| bade6711c5 | |||
| ed732162e0 |
@@ -1,18 +0,0 @@
|
||||
# Docker ignore file
|
||||
.git
|
||||
.gitignore
|
||||
node_modules
|
||||
npm-debug.log
|
||||
yarn-debug.log
|
||||
yarn-error.log
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
.vscode
|
||||
.idea
|
||||
*.log
|
||||
php_server.pid
|
||||
php_server.log
|
||||
.env
|
||||
docker-compose.override.yml
|
||||
*.md
|
||||
README*
|
||||
@@ -1,9 +0,0 @@
|
||||
# Google Gemini API Configuration
|
||||
# Get your API key from: https://makersuite.google.com/app/apikey
|
||||
GEMINI_API_KEY=your_gemini_api_key_here
|
||||
|
||||
# Database Configuration (if needed in future)
|
||||
# DB_HOST=localhost
|
||||
# DB_NAME=sidak_db
|
||||
# DB_USER=root
|
||||
# DB_PASSWORD=
|
||||
8
.gitignore
vendored
Executable file → Normal file
8
.gitignore
vendored
Executable file → Normal file
@@ -13,12 +13,10 @@ Thumbs.db
|
||||
# Dependencies (if any in future)
|
||||
node_modules/
|
||||
vendor/
|
||||
!plugins/vendor/
|
||||
|
||||
# Uploads
|
||||
foto/
|
||||
|
||||
# API Keys and Environment Variables
|
||||
admin/api/config_api.php
|
||||
.env
|
||||
.env.*.local
|
||||
# Debug files
|
||||
debug_ai.txt
|
||||
debug_log.txt
|
||||
|
||||
38
Dockerfile
38
Dockerfile
@@ -1,38 +0,0 @@
|
||||
FROM php:8.2-apache
|
||||
|
||||
# Install necessary PHP extensions and tools
|
||||
RUN apt-get update && apt-get install -y \
|
||||
libpng-dev \
|
||||
libjpeg-dev \
|
||||
libfreetype6-dev \
|
||||
libzip-dev \
|
||||
zip \
|
||||
unzip \
|
||||
curl \
|
||||
git \
|
||||
mariadb-client \
|
||||
&& docker-php-ext-configure gd --with-freetype --with-jpeg \
|
||||
&& docker-php-ext-install -j$(nproc) gd \
|
||||
&& docker-php-ext-install mysqli pdo pdo_mysql zip \
|
||||
&& apt-get clean \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Enable Apache rewrite module
|
||||
RUN a2enmod rewrite
|
||||
|
||||
# Set working directory
|
||||
WORKDIR /var/www/html
|
||||
|
||||
# Copy application files
|
||||
COPY . /var/www/html/
|
||||
|
||||
# Set proper permissions
|
||||
RUN chown -R www-data:www-data /var/www/html \
|
||||
&& chmod -R 755 /var/www/html
|
||||
|
||||
# Update koneksi.php to use environment variables
|
||||
RUN sed -i 's/\$koneksi = new mysqli ("localhost","sidak_user","sidak_pass","data_penduduk");/\$db_host = getenv("DB_HOST") ?: "localhost";\n\$db_user = getenv("DB_USER") ?: "sidak_user";\n\$db_pass = getenv("DB_PASS") ?: "sidak_pass";\n\$db_name = getenv("DB_NAME") ?: "data_penduduk";\n\$koneksi = new mysqli (\$db_host,\$db_user,\$db_pass,\$db_name);/g' inc/koneksi.php
|
||||
|
||||
EXPOSE 80
|
||||
|
||||
CMD ["apache2-foreground"]
|
||||
Binary file not shown.
@@ -1,115 +0,0 @@
|
||||
# 🔐 Keamanan API Key SIDAK
|
||||
|
||||
## **⚠️ PENTING: API Key Terdeteksi di Repository Git**
|
||||
|
||||
File `admin/api/config_api.php` sebelumnya mengandung kunci API Gemini yang terekspos di repository Git. Kunci ini telah diamankan dengan sistem environment variables.
|
||||
|
||||
## **🛡️ Langkah-Langkah Pengamanan yang Telah Dilakukan:**
|
||||
|
||||
1. **API Key dihapus dari Git tracking:**
|
||||
```bash
|
||||
git rm --cached admin/api/config_api.php
|
||||
```
|
||||
|
||||
2. **File konfigurasi dimodifikasi untuk menggunakan environment variables:**
|
||||
- `admin/api/config_api.php` sekarang membaca dari file `.env`
|
||||
- Gunakan template `.env.example` untuk membuat `.env`
|
||||
|
||||
3. **File sensitif ditambahkan ke `.gitignore`:**
|
||||
```
|
||||
admin/api/config_api.php
|
||||
.env
|
||||
.env.*.local
|
||||
```
|
||||
|
||||
## **🚀 Deployment Instructions:**
|
||||
|
||||
### **1. Untuk Development Lokal:**
|
||||
```bash
|
||||
# Salin template .env
|
||||
cp .env.example .env
|
||||
|
||||
# Edit .env dengan API key Anda
|
||||
nano .env # atau editor favorit Anda
|
||||
```
|
||||
|
||||
### **2. Untuk Production Server:**
|
||||
```bash
|
||||
# Buat file .env di server
|
||||
cat > /var/www/sidak/.env << 'EOF'
|
||||
# Google Gemini API Configuration
|
||||
GEMINI_API_KEY=your_actual_production_key_here
|
||||
EOF
|
||||
|
||||
# Pastikan permission aman
|
||||
chmod 600 /var/www/sidak/.env
|
||||
chown www-data:www-data /var/www/sidak/.env
|
||||
```
|
||||
|
||||
### **3. Get New API Key (jika perlu):**
|
||||
1. Kunjungi [Google AI Studio](https://makersuite.google.com/app/apikey)
|
||||
2. Login dengan akun Google
|
||||
3. Create API Key → Copy key baru
|
||||
4. Update file `.env` di server
|
||||
|
||||
## **📁 Struktur File yang Aman:**
|
||||
|
||||
```
|
||||
sidak/
|
||||
├── .env # ⚠️ JANGAN commit (sudah di .gitignore)
|
||||
├── .env.example # ✅ Template aman untuk commit
|
||||
├── .gitignore # ✅ Menyertakan .env dan config_api.php
|
||||
├── admin/
|
||||
│ └── api/
|
||||
│ ├── config_api.php # ✅ Membaca dari environment variables
|
||||
│ └── ocr_helper.php # ✅ Menggunakan GEMINI_API_KEY dari config
|
||||
└── README_API_SECURITY.md # ✅ Dokumentasi ini
|
||||
```
|
||||
|
||||
## **🔧 Testing Configuration:**
|
||||
|
||||
Untuk memastikan konfigurasi bekerja:
|
||||
|
||||
```php
|
||||
<?php
|
||||
// Test script: test_api_config.php
|
||||
require_once 'admin/api/config_api.php';
|
||||
|
||||
echo "GEMINI_API_KEY: " . (defined('GEMINI_API_KEY') ? '✅ Set' : '❌ Not set') . "\n";
|
||||
echo "GEMINI_API_URL: " . GEMINI_API_URL . "\n";
|
||||
|
||||
if (empty(GEMINI_API_KEY)) {
|
||||
echo "❌ ERROR: API key tidak terdeteksi.\n";
|
||||
echo "Pastikan file .env ada dan berisi GEMINI_API_KEY=your_key\n";
|
||||
} else {
|
||||
echo "✅ Konfigurasi API siap digunakan.\n";
|
||||
}
|
||||
?>
|
||||
```
|
||||
|
||||
## **🔄 Jika Terjadi Masalah:**
|
||||
|
||||
### **Masalah: "API key not set"**
|
||||
**Solusi:**
|
||||
1. Pastikan file `.env` ada di root directory
|
||||
2. Pastikan permission file `.env` dapat dibaca oleh PHP
|
||||
3. Restart web server jika perlu: `sudo service apache2 restart`
|
||||
|
||||
### **Masalah: "403 Forbidden" dari Gemini API**
|
||||
**Solusi:**
|
||||
1. Periksa apakah API key valid di [Google AI Studio](https://makersuite.google.com/app/apikey)
|
||||
2. Pastikan billing enabled di Google Cloud Console
|
||||
3. Cek quota usage di Google Cloud Console
|
||||
|
||||
## **📞 Support:**
|
||||
|
||||
Jika menemukan masalah keamanan:
|
||||
1. **Segera putar API key** di Google AI Studio
|
||||
2. Update file `.env` di semua environment
|
||||
3. Hubungi developer: [wartana@example.com]
|
||||
|
||||
---
|
||||
|
||||
**⚠️ REMINDER:** JANGAN pernah commit file `.env` atau `admin/api/config_api.php` ke repository Git. Selalu gunakan `.env.example` sebagai template.
|
||||
|
||||
**Terakhir diperbarui:** 22 Januari 2026
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 148 KiB |
5
admin/api/config_api.php
Normal file
5
admin/api/config_api.php
Normal file
@@ -0,0 +1,5 @@
|
||||
<?php
|
||||
// Google Gemini API Configuration
|
||||
define('GEMINI_API_KEY', 'AIzaSyDp9crq4QWN15xBXbDY2FBXdUoRg1LgM1M');
|
||||
define('GEMINI_API_URL', 'https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent');
|
||||
?>
|
||||
77
admin/api/ocr_helper.php
Executable file → Normal file
77
admin/api/ocr_helper.php
Executable file → Normal file
@@ -1,7 +1,6 @@
|
||||
<?php
|
||||
header('Content-Type: application/json');
|
||||
require_once 'config_api.php';
|
||||
set_time_limit(300);
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
|
||||
echo json_encode(['success' => false, 'message' => 'Invalid request method']);
|
||||
@@ -20,27 +19,31 @@ $mimeType = mime_content_type($imagePath);
|
||||
|
||||
// Construct Prompt based on Type
|
||||
if ($type === 'kk') {
|
||||
$promptText = "Extract strictly from this Indonesian Family Card (Kartu Keluarga). Return ONLY a raw JSON object with these keys: 'no_kk' (16 digits), 'kepala_keluarga' (Name), 'alamat', 'rt', 'rw', 'desa', 'kecamatan', 'kabupaten', 'provinsi', 'kode_pos', 'anggota': [ { 'nik': '...', 'nama': '...', 'hubungan': '...' } ] (Array of all family members found in the table. 'hubungan' examples: KEPALA KELUARGA, ISTRI, ANAK, FAMILI LAIN). Value must be string. If not found, use empty string.";
|
||||
$promptText = "Extract strictly from this Indonesian Family Card (Kartu Keluarga). Return ONLY a raw JSON object with these keys: 'no_kk' (16 digits), 'kepala_keluarga' (Name), 'alamat', 'rt', 'rw', 'desa', 'kecamatan', 'kabupaten', 'provinsi', 'kode_pos', 'anggota': [ { 'nik': '...', 'nama': '...', 'hubungan': '...', 'tempat_lh': '...', 'tgl_lh': 'YYYY-MM-DD', 'jekel': 'LK/PR', 'agama': '...', 'kawin': '...', 'pekerjaan': '...', 'kewarganegaraan': 'WNI/WNA' } ] (Array of all family members found in the table. 'hubungan' examples: KEPALA KELUARGA, ISTRI, ANAK, FAMILI LAIN). Value must be string. If not found, use empty string.";
|
||||
} else {
|
||||
// Default to KTP
|
||||
$promptText = "Extract data from this Indonesian KTP. Return ONLY a raw JSON object with keys: 'nik' (16 digits), 'nama' (Name), 'tempat_lh' (Place of Birth), 'tgl_lh' (YYYY-MM-DD), 'je_kel' (LK/PR), 'alamat' (Street only), 'rt', 'rw', 'desa' (Kel/Desa), 'kecamatan', 'kabupaten' (or Kota), 'provinsi', 'agama', 'status' (Sudah/Belum/Cerai Hidup/Cerai Mati), 'pekerjaan', 'kewarganegaraan' (WNI/WNA). Clean up text. If field is unclear, return empty string.";
|
||||
}
|
||||
|
||||
// Payload for Ollama App
|
||||
// Payload for Gemini
|
||||
$data = [
|
||||
"model" => "qwen2.5vl:3b",
|
||||
"messages" => [
|
||||
"contents" => [
|
||||
[
|
||||
"role" => "user",
|
||||
"content" => $promptText,
|
||||
"images" => [$imageData]
|
||||
"parts" => [
|
||||
["text" => $promptText],
|
||||
[
|
||||
"inline_data" => [
|
||||
"mime_type" => $mimeType,
|
||||
"data" => $imageData
|
||||
]
|
||||
]
|
||||
]
|
||||
]
|
||||
],
|
||||
"stream" => false
|
||||
]
|
||||
];
|
||||
|
||||
// Send Request
|
||||
$ch = curl_init(OLLAMA_API_URL);
|
||||
$ch = curl_init(GEMINI_API_URL . '?key=' . GEMINI_API_KEY);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($ch, CURLOPT_POST, true);
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
|
||||
@@ -64,13 +67,14 @@ if (isset($result['error'])) {
|
||||
exit;
|
||||
}
|
||||
|
||||
if (!isset($result['message']['content'])) {
|
||||
if (!isset($result['candidates'][0]['content']['parts'][0]['text'])) {
|
||||
echo json_encode(['success' => false, 'message' => 'No text returned from AI', 'raw' => $result]);
|
||||
exit;
|
||||
}
|
||||
|
||||
// Parse AI Response
|
||||
$rawText = $result['message']['content'];
|
||||
$rawText = $result['candidates'][0]['content']['parts'][0]['text'];
|
||||
file_put_contents('../../debug_ai.txt', "AI Response:\n" . $rawText . "\n-------------------\n", FILE_APPEND);
|
||||
|
||||
// Remove Markdown Code Blocks if any (```json ... ```)
|
||||
$cleanJson = preg_replace('/^```json\s*|\s*```$/', '', trim($rawText));
|
||||
@@ -88,52 +92,5 @@ if (!$parsedData) {
|
||||
exit;
|
||||
}
|
||||
|
||||
if ($type === 'ktp') {
|
||||
// 1. Parse Status Perkawinan
|
||||
if (!empty($parsedData['status'])) {
|
||||
$st = strtoupper($parsedData['status']);
|
||||
if (strpos($st, 'BELUM') !== false) {
|
||||
$parsedData['status'] = 'Belum';
|
||||
} elseif (strpos($st, 'CERAI MATI') !== false) {
|
||||
$parsedData['status'] = 'Cerai Mati';
|
||||
} elseif (strpos($st, 'CERAI HIDUP') !== false) {
|
||||
$parsedData['status'] = 'Cerai Hidup';
|
||||
} elseif (strpos($st, 'KAWIN') !== false) {
|
||||
$parsedData['status'] = 'Sudah';
|
||||
}
|
||||
}
|
||||
|
||||
// 2. Parse Jenis Kelamin
|
||||
if (!empty($parsedData['je_kel'])) {
|
||||
$jk = strtoupper($parsedData['je_kel']);
|
||||
if (strpos($jk, 'LAKI') !== false || $jk === 'L') {
|
||||
$parsedData['je_kel'] = 'LK';
|
||||
} elseif (strpos($jk, 'PEREMPUAN') !== false || $jk === 'P') {
|
||||
$parsedData['je_kel'] = 'PR';
|
||||
}
|
||||
}
|
||||
|
||||
// 3. Parse Tempat & Tanggal Lahir (KTP format: "TEMPAT, DD-MM-YYYY")
|
||||
if (!empty($parsedData['tempat_lh'])) {
|
||||
$ttl = $parsedData['tempat_lh'];
|
||||
if (strpos($ttl, ',') !== false) {
|
||||
[$tempat, $tgl] = explode(',', $ttl, 2);
|
||||
$parsedData['tempat_lh'] = trim($tempat);
|
||||
if (empty($parsedData['tgl_lh'])) {
|
||||
$parsedData['tgl_lh'] = trim($tgl);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 4. Format Tanggal Lahir to YYYY-MM-DD for HTML input[type=date]
|
||||
if (!empty($parsedData['tgl_lh'])) {
|
||||
$tgl_lh = trim($parsedData['tgl_lh']);
|
||||
// If it looks like DD-MM-YYYY or DD/MM/YYYY
|
||||
if (preg_match('/^(\d{2})[\/\-](\d{2})[\/\-](\d{4})$/', $tgl_lh, $matches)) {
|
||||
$parsedData['tgl_lh'] = $matches[3] . '-' . $matches[2] . '-' . $matches[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
echo json_encode(['success' => true, 'data' => $parsedData]);
|
||||
?>
|
||||
|
||||
166
admin/datang/add_datang.php
Executable file → Normal file
166
admin/datang/add_datang.php
Executable file → Normal file
@@ -1,6 +1,3 @@
|
||||
<?php
|
||||
$selected_id = isset($_GET['selected_id']) ? (int)$_GET['selected_id'] : 0;
|
||||
?>
|
||||
<div class="card card-primary">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">
|
||||
@@ -9,40 +6,37 @@ $selected_id = isset($_GET['selected_id']) ? (int)$_GET['selected_id'] : 0;
|
||||
<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">Pendatang</label>
|
||||
<div class="col-sm-6">
|
||||
<select name="id_pend" id="id_pend" class="form-control select2bs4" required>
|
||||
<option value="" <?php echo ($selected_id == 0) ? 'selected="selected"' : ''; ?>>- Pilih Penduduk -</option>
|
||||
<?php
|
||||
// ambil data dari database
|
||||
$query = "select * from tb_pdd where status='Ada'";
|
||||
$hasil = mysqli_query($koneksi, $query);
|
||||
while ($row = mysqli_fetch_array($hasil)) {
|
||||
?>
|
||||
<option value="<?php echo $row['id_pend'] ?>" <?php echo ($row['id_pend'] == $selected_id) ? 'selected="selected"' : ''; ?>>
|
||||
<?php echo $row['nik'] ?>
|
||||
-
|
||||
<?php echo $row['nama'] ?>
|
||||
</option>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-sm-2">
|
||||
<a href="?page=add-pend&return_to=add-datang" class="btn btn-outline-primary btn-sm">
|
||||
<i class="fa fa-plus"></i> Tambah Penduduk Baru
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group row">
|
||||
<label class="col-sm-2 col-form-label">Tgl Datang</label>
|
||||
<div class="col-sm-3">
|
||||
<input type="date" class="form-control" id="tgl_datang" name="tgl_datang" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<label class="col-sm-2 col-form-label">NIK</label>
|
||||
<div class="col-sm-6">
|
||||
<input type="text" class="form-control" id="nik" name="nik" placeholder="NIK" required>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group row">
|
||||
<label class="col-sm-2 col-form-label">Nama</label>
|
||||
<div class="col-sm-6">
|
||||
<input type="text" class="form-control" id="nama_datang" name="nama_datang" placeholder="Nama Pendatang" required>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group row">
|
||||
<label class="col-sm-2 col-form-label">Jenis Kelain</label>
|
||||
<div class="col-sm-3">
|
||||
<select name="jekel" id="jekel" class="form-control">
|
||||
<option>- Pilih -</option>
|
||||
<option>LK</option>
|
||||
<option>PR</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group row">
|
||||
<label class="col-sm-2 col-form-label">Tgl Datang</label>
|
||||
<div class="col-sm-3">
|
||||
<input type="date" class="form-control" id="tgl_datang" name="tgl_datang" required>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group row">
|
||||
<label class="col-sm-2 col-form-label">Pelapor</label>
|
||||
@@ -56,9 +50,9 @@ $selected_id = isset($_GET['selected_id']) ? (int)$_GET['selected_id'] : 0;
|
||||
while ($row = mysqli_fetch_array($hasil)) {
|
||||
?>
|
||||
<option value="<?php echo $row['id_pend'] ?>">
|
||||
<?php echo htmlspecialchars($row['nik'], ENT_QUOTES); ?>
|
||||
<?php echo $row['nik'] ?>
|
||||
-
|
||||
<?php echo htmlspecialchars($row['nama'], ENT_QUOTES); ?>
|
||||
<?php echo $row['nama'] ?>
|
||||
</option>
|
||||
<?php
|
||||
}
|
||||
@@ -77,51 +71,51 @@ $selected_id = isset($_GET['selected_id']) ? (int)$_GET['selected_id'] : 0;
|
||||
|
||||
<?php
|
||||
|
||||
if (isset ($_POST['Simpan'])){
|
||||
//mulai proses simpan data
|
||||
|
||||
// Sanitize Input to prevent SQL Injection & Syntax Errors
|
||||
$id_pend = (int)$_POST['id_pend']; // Cast to integer for safety
|
||||
$tgl_datang = mysqli_real_escape_string($koneksi, trim($_POST['tgl_datang']));
|
||||
$pelapor = (int)$_POST['pelapor']; // Cast to integer for safety
|
||||
|
||||
// Ambil data penduduk yang dipilih
|
||||
$sql_pend = "SELECT nik, nama, jekel FROM tb_pdd WHERE id_pend='$id_pend'";
|
||||
$q_pend = mysqli_query($koneksi, $sql_pend);
|
||||
$d_pend = mysqli_fetch_array($q_pend);
|
||||
|
||||
if (!$d_pend) {
|
||||
die("Data penduduk tidak ditemukan. Silakan pilih penduduk yang valid.");
|
||||
}
|
||||
|
||||
$nik = mysqli_real_escape_string($koneksi, trim($d_pend['nik']));
|
||||
$nama_datang = mysqli_real_escape_string($koneksi, trim($d_pend['nama']));
|
||||
$jekel = mysqli_real_escape_string($koneksi, trim($d_pend['jekel']));
|
||||
|
||||
$sql_simpan = "INSERT INTO tb_datang (id_pend, nik, nama_datang, jekel, tgl_datang, pelapor) VALUES (
|
||||
'$id_pend',
|
||||
'$nik',
|
||||
'$nama_datang',
|
||||
'$jekel',
|
||||
'$tgl_datang',
|
||||
'$pelapor')";
|
||||
$query_simpan = mysqli_query($koneksi, $sql_simpan);
|
||||
|
||||
mysqli_close($koneksi);
|
||||
|
||||
if ($query_simpan) {
|
||||
echo "<script>
|
||||
Swal.fire({title: 'Tambah Data Berhasil',text: '',icon: 'success',confirmButtonText: 'OK'
|
||||
}).then((result) => {if (result.value){
|
||||
window.location = 'index.php?page=data-datang';
|
||||
}
|
||||
})</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-datang';
|
||||
}
|
||||
})</script>";
|
||||
}}
|
||||
if (isset ($_POST['Simpan'])){
|
||||
//mulai proses simpan data
|
||||
$sql_simpan = "INSERT INTO tb_datang (nik, nama_datang, jekel, tgl_datang, pelapor) VALUES (
|
||||
'".$_POST['nik']."',
|
||||
'".$_POST['nama_datang']."',
|
||||
'".$_POST['jekel']."',
|
||||
'".$_POST['tgl_datang']."',
|
||||
'".$_POST['pelapor']."')";
|
||||
$query_simpan = mysqli_query($koneksi, $sql_simpan);
|
||||
|
||||
// Otomatis tambah ke Data Penduduk
|
||||
// Ambil data alamat dari pelapor
|
||||
$id_pelapor = $_POST['pelapor'];
|
||||
$sql_pelapor = "SELECT desa, rt, rw FROM tb_pdd WHERE id_pend='$id_pelapor'";
|
||||
$q_pelapor = mysqli_query($koneksi, $sql_pelapor);
|
||||
$d_pelapor = mysqli_fetch_array($q_pelapor);
|
||||
$desa = $d_pelapor['desa'];
|
||||
$rt = $d_pelapor['rt'];
|
||||
$rw = $d_pelapor['rw'];
|
||||
|
||||
$sql_pdd = "INSERT INTO tb_pdd (nik, nama, tempat_lh, tgl_lh, jekel, desa, rt, rw, agama, kawin, pekerjaan, status) VALUES (
|
||||
'".$_POST['nik']."',
|
||||
'".$_POST['nama_datang']."',
|
||||
'-',
|
||||
'0000-00-00',
|
||||
'".$_POST['jekel']."',
|
||||
'$desa', '$rt', '$rw',
|
||||
'-', '-', '-', 'Ada')";
|
||||
$query_pdd = mysqli_query($koneksi, $sql_pdd);
|
||||
|
||||
mysqli_close($koneksi);
|
||||
|
||||
if ($query_simpan && $query_pdd) {
|
||||
echo "<script>
|
||||
Swal.fire({title: 'Tambah Data Berhasil',text: '',icon: 'success',confirmButtonText: 'OK'
|
||||
}).then((result) => {if (result.value){
|
||||
window.location = 'index.php?page=data-datang';
|
||||
}
|
||||
})</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-datang';
|
||||
}
|
||||
})</script>";
|
||||
}}
|
||||
//selesai proses simpan data
|
||||
|
||||
43
admin/datang/data_datang.php
Executable file → Normal file
43
admin/datang/data_datang.php
Executable file → Normal file
@@ -17,7 +17,7 @@
|
||||
<th>No</th>
|
||||
<th>NIK</th>
|
||||
<th>Nama</th>
|
||||
<th>Jenis Kelamin</th>
|
||||
<th>Jekel</th>
|
||||
<th>Tanggal</th>
|
||||
<th>Pelapor</th>
|
||||
<th>Aksi</th>
|
||||
@@ -43,15 +43,7 @@
|
||||
<?php echo $data['nama_datang']; ?>
|
||||
</td>
|
||||
<td>
|
||||
<?php
|
||||
if ($data['jekel'] == 'LK') {
|
||||
echo 'LAKI-LAKI';
|
||||
} elseif ($data['jekel'] == 'PR') {
|
||||
echo 'PEREMPUAN';
|
||||
} else {
|
||||
echo $data['jekel'];
|
||||
}
|
||||
?>
|
||||
<?php echo $data['jekel']; ?>
|
||||
</td>
|
||||
<td>
|
||||
<?php echo $data['tgl_datang']; ?>
|
||||
@@ -64,10 +56,10 @@
|
||||
class="btn btn-success btn-sm">
|
||||
<i class="fa fa-edit"></i>
|
||||
</a>
|
||||
<a href="?page=del-datang&kode=<?php echo $data['id_datang']; ?>" onclick="confirmDelete(event)"
|
||||
<a href="?page=del-datang&kode=<?php echo $data['id_datang']; ?>" onclick="return confirm('Apakah anda yakin hapus data ini ?')"
|
||||
title="Hapus" class="btn btn-danger btn-sm">
|
||||
<i class="fa fa-trash"></i>
|
||||
</a>
|
||||
</>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
@@ -76,26 +68,7 @@
|
||||
?>
|
||||
</tbody>
|
||||
</tfoot>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<!-- /.card-body -->
|
||||
<script>
|
||||
function confirmDelete(event) {
|
||||
event.preventDefault();
|
||||
Swal.fire({
|
||||
title: 'Konfirmasi Hapus',
|
||||
text: 'Apakah Anda yakin ingin menghapus data ini?',
|
||||
icon: 'warning',
|
||||
showCancelButton: true,
|
||||
confirmButtonColor: '#d33',
|
||||
cancelButtonColor: '#3085d6',
|
||||
confirmButtonText: 'Ya, Hapus',
|
||||
cancelButtonText: 'Batal'
|
||||
}).then((result) => {
|
||||
if (result.isConfirmed) {
|
||||
window.location.href = event.currentTarget.href;
|
||||
}
|
||||
});
|
||||
}
|
||||
</script>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<!-- /.card-body -->
|
||||
0
admin/datang/del_datang.php
Executable file → Normal file
0
admin/datang/del_datang.php
Executable file → Normal file
173
admin/datang/edit_datang.php
Executable file → Normal file
173
admin/datang/edit_datang.php
Executable file → Normal file
@@ -1,14 +1,11 @@
|
||||
<?php
|
||||
|
||||
if(isset($_GET['kode'])){
|
||||
$sql_cek = "SELECT d.id_datang, d.id_pend, d.nik, d.nama_datang, d.jekel, d.tgl_datang, p.id_pend as id_pelapor, p.nama as nama_pelapor, pd.tgl_lh
|
||||
FROM tb_datang d
|
||||
INNER JOIN tb_pdd p ON d.pelapor=p.id_pend
|
||||
LEFT JOIN tb_pdd pd ON d.id_pend=pd.id_pend
|
||||
WHERE d.id_datang='".$_GET['kode']."'";
|
||||
$query_cek = mysqli_query($koneksi, $sql_cek);
|
||||
$data_cek = mysqli_fetch_array($query_cek,MYSQLI_BOTH);
|
||||
}
|
||||
if(isset($_GET['kode'])){
|
||||
$sql_cek = "SELECT d.id_datang, d.nik, d.nama_datang, d.jekel, d.tgl_datang, p.id_pend, p.nama from
|
||||
tb_datang d inner join tb_pdd p on d.pelapor=p.id_pend WHERE id_datang='".$_GET['kode']."'";
|
||||
$query_cek = mysqli_query($koneksi, $sql_cek);
|
||||
$data_cek = mysqli_fetch_array($query_cek,MYSQLI_BOTH);
|
||||
}
|
||||
?>
|
||||
|
||||
<div class="card card-success">
|
||||
@@ -27,51 +24,43 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<input type="hidden" id="id_pend" name="id_pend" value="<?php echo isset($data_cek['id_pend']) ? $data_cek['id_pend'] : ''; ?>">
|
||||
|
||||
<div class="form-group row">
|
||||
<label class="col-sm-2 col-form-label">NIK</label>
|
||||
<div class="col-sm-6">
|
||||
<input type="text" class="form-control" value="<?php echo htmlspecialchars($data_cek['nik'], ENT_QUOTES); ?>" readonly>
|
||||
<input type="hidden" name="nik" value="<?php echo htmlspecialchars($data_cek['nik'], ENT_QUOTES); ?>">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group row">
|
||||
<label class="col-sm-2 col-form-label">Nama</label>
|
||||
<div class="col-sm-6">
|
||||
<input type="text" class="form-control" value="<?php echo htmlspecialchars($data_cek['nama_datang'], ENT_QUOTES); ?>" readonly>
|
||||
<input type="hidden" name="nama_datang" value="<?php echo htmlspecialchars($data_cek['nama_datang'], ENT_QUOTES); ?>">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group row">
|
||||
<label class="col-sm-2 col-form-label">Jenis Kelamin</label>
|
||||
<div class="col-sm-3">
|
||||
<input type="text" class="form-control" value="<?php
|
||||
$display_jekel = $data_cek['jekel'];
|
||||
if ($display_jekel == 'LK') {
|
||||
$display_jekel = 'LAKI-LAKI';
|
||||
} elseif ($display_jekel == 'PR') {
|
||||
$display_jekel = 'PEREMPUAN';
|
||||
}
|
||||
echo htmlspecialchars($display_jekel, ENT_QUOTES);
|
||||
?>" readonly>
|
||||
<input type="hidden" name="jekel" value="<?php echo htmlspecialchars($data_cek['jekel'], ENT_QUOTES); ?>">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group row">
|
||||
<label class="col-sm-2 col-form-label">Tgl Lahir</label>
|
||||
<div class="col-sm-3">
|
||||
<input type="text" class="form-control" value="<?php echo htmlspecialchars(isset($data_cek['tgl_lh']) ? $data_cek['tgl_lh'] : '-', ENT_QUOTES); ?>" readonly>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group row">
|
||||
<label class="col-sm-2 col-form-label">Tgl Datang</label>
|
||||
<div class="form-group row">
|
||||
<label class="col-sm-2 col-form-label">NIK</label>
|
||||
<div class="col-sm-6">
|
||||
<input type="text" class="form-control" id="nik" name="nik" value="<?php echo $data_cek['nik']; ?>"
|
||||
required>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group row">
|
||||
<label class="col-sm-2 col-form-label">Nama</label>
|
||||
<div class="col-sm-6">
|
||||
<input type="text" class="form-control" id="nama_datang" name="nama_datang" value="<?php echo $data_cek['nama_datang']; ?>"
|
||||
required>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group row">
|
||||
<label class="col-sm-2 col-form-label">Jenis Kelamin</label>
|
||||
<div class="col-sm-3">
|
||||
<input type="date" class="form-control" id="tgl_datang" name="tgl_datang" value="<?php echo htmlspecialchars($data_cek['tgl_datang'], ENT_QUOTES); ?>"
|
||||
<select name="jekel" id="jekel" class="form-control">
|
||||
<option value="">-- Pilih jekel --</option>
|
||||
<?php
|
||||
//menhecek data yg dipilih sebelumnya
|
||||
if ($data_cek['jekel'] == "LK") echo "<option value='LK' selected>LK</option>";
|
||||
else echo "<option value='LK'>LK</option>";
|
||||
|
||||
if ($data_cek['jekel'] == "PR") echo "<option value='PR' selected>PR</option>";
|
||||
else echo "<option value='PR'>PR</option>";
|
||||
?>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group row">
|
||||
<label class="col-sm-2 col-form-label">Tgl Datang</label>
|
||||
<div class="col-sm-3">
|
||||
<input type="date" class="form-control" id="tgl_datang" name="tgl_datang" value="<?php echo $data_cek['tgl_datang']; ?>"
|
||||
required>
|
||||
</div>
|
||||
</div>
|
||||
@@ -83,14 +72,15 @@
|
||||
<option selected="">- Pilih -</option>
|
||||
<?php
|
||||
// ambil data dari database
|
||||
$query = "select * from tb_pdd where status='Ada'";
|
||||
$query = "select * from tb_pdd";
|
||||
$hasil = mysqli_query($koneksi, $query);
|
||||
while ($row = mysqli_fetch_array($hasil)) {
|
||||
?>
|
||||
<option value="<?php echo $row['id_pend'] ?>" <?=$data_cek['id_pelapor']==$row['id_pend'] ? "selected" : null ?>>
|
||||
<?php echo htmlspecialchars($row['nik'], ENT_QUOTES); ?>
|
||||
<option value="<?php echo $row['id_pend'] ?>" <?=$data_cek[
|
||||
'id_pend']==$row[ 'id_pend'] ? "selected" : null ?>>
|
||||
<?php echo $row['nik'] ?>
|
||||
-
|
||||
<?php echo htmlspecialchars($row['nama'], ENT_QUOTES); ?>
|
||||
<?php echo $row['nama'] ?>
|
||||
</option>
|
||||
<?php
|
||||
}
|
||||
@@ -108,44 +98,31 @@
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<?php
|
||||
|
||||
if (isset ($_POST['Ubah'])){
|
||||
// Sanitize Input to prevent SQL Injection & Syntax Errors
|
||||
$id_datang = (int)$_POST['id_datang'];
|
||||
$nik = mysqli_real_escape_string($koneksi, trim($_POST['nik']));
|
||||
$nama_datang = mysqli_real_escape_string($koneksi, trim($_POST['nama_datang']));
|
||||
$jekel = mysqli_real_escape_string($koneksi, trim($_POST['jekel']));
|
||||
|
||||
$tgl_datang = mysqli_real_escape_string($koneksi, trim($_POST['tgl_datang']));
|
||||
$pelapor = (int)$_POST['pelapor'];
|
||||
|
||||
// Update tb_datang table
|
||||
$sql_ubah = "UPDATE tb_datang SET
|
||||
nik='$nik',
|
||||
nama_datang='$nama_datang',
|
||||
jekel='$jekel',
|
||||
tgl_datang='$tgl_datang',
|
||||
pelapor='$pelapor'
|
||||
WHERE id_datang='$id_datang'";
|
||||
$query_ubah = mysqli_query($koneksi, $sql_ubah);
|
||||
|
||||
|
||||
|
||||
mysqli_close($koneksi);
|
||||
|
||||
if ($query_ubah) {
|
||||
echo "<script>
|
||||
Swal.fire({title: 'Ubah Data Berhasil',text: '',icon: 'success',confirmButtonText: 'OK'
|
||||
}).then((result) => {if (result.value)
|
||||
{window.location = 'index.php?page=data-datang';
|
||||
}
|
||||
})</script>";
|
||||
}else{
|
||||
echo "<script>
|
||||
Swal.fire({title: 'Ubah Data Gagal',text: '',icon: 'error',confirmButtonText: 'OK'
|
||||
}).then((result) => {if (result.value)
|
||||
{window.location = 'index.php?page=data-datang';
|
||||
}
|
||||
})</script>";
|
||||
}}
|
||||
<?php
|
||||
|
||||
if (isset ($_POST['Ubah'])){
|
||||
$sql_ubah = "UPDATE tb_datang SET
|
||||
nik='".$_POST['nik']."',
|
||||
nama_datang='".$_POST['nama_datang']."',
|
||||
jekel='".$_POST['jekel']."',
|
||||
tgl_datang='".$_POST['tgl_datang']."',
|
||||
pelapor='".$_POST['pelapor']."'
|
||||
WHERE id_datang='".$_POST['id_datang']."'";
|
||||
$query_ubah = mysqli_query($koneksi, $sql_ubah);
|
||||
mysqli_close($koneksi);
|
||||
|
||||
if ($query_ubah) {
|
||||
echo "<script>
|
||||
Swal.fire({title: 'Ubah Data Berhasil',text: '',icon: 'success',confirmButtonText: 'OK'
|
||||
}).then((result) => {if (result.value)
|
||||
{window.location = 'index.php?page=data-datang';
|
||||
}
|
||||
})</script>";
|
||||
}else{
|
||||
echo "<script>
|
||||
Swal.fire({title: 'Ubah Data Gagal',text: '',icon: 'error',confirmButtonText: 'OK'
|
||||
}).then((result) => {if (result.value)
|
||||
{window.location = 'index.php?page=data-datang';
|
||||
}
|
||||
})</script>";
|
||||
}}
|
||||
|
||||
198
admin/kartu/add_kartu.php
Executable file → Normal file
198
admin/kartu/add_kartu.php
Executable file → Normal file
@@ -30,9 +30,9 @@
|
||||
</div>
|
||||
|
||||
<div class="form-group row">
|
||||
<label class="col-sm-2 col-form-label">Kepala Keluarga</label>
|
||||
<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="Kepala Keluarga" required>
|
||||
<input type="text" class="form-control" id="kepala" name="kepala" placeholder="Kpl Keluarga" required>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -46,10 +46,10 @@
|
||||
<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" value="000" required>
|
||||
<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" value="000" required>
|
||||
<input type="text" class="form-control" id="rw" name="rw" placeholder="RW" required>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -166,18 +166,7 @@ window.addEventListener('load', function() {
|
||||
<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>
|
||||
<p class="mb-0 text-muted">Gunakan data ini?</p>
|
||||
</div>
|
||||
`,
|
||||
icon: 'question',
|
||||
@@ -190,8 +179,8 @@ window.addEventListener('load', function() {
|
||||
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;
|
||||
document.getElementsByName('rt')[0].value = d.rt || '000';
|
||||
document.getElementsByName('rw')[0].value = d.rw || '000';
|
||||
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;
|
||||
@@ -238,28 +227,27 @@ window.addEventListener('load', function() {
|
||||
}
|
||||
|
||||
//mulai proses simpan data
|
||||
$no_kk_raw = trim($_POST['no_kk']);
|
||||
$no_kk_clean = mysqli_real_escape_string($koneksi, $no_kk_raw);
|
||||
$cek_kk = mysqli_query($koneksi, "SELECT * FROM tb_kk WHERE no_kk='$no_kk_clean'");
|
||||
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 = $no_kk_clean;
|
||||
$kepala = mysqli_real_escape_string($koneksi, trim($_POST['kepala']));
|
||||
$desa = mysqli_real_escape_string($koneksi, trim($_POST['desa']));
|
||||
$rt = mysqli_real_escape_string($koneksi, trim($_POST['rt']));
|
||||
$rw = mysqli_real_escape_string($koneksi, trim($_POST['rw']));
|
||||
$kec = mysqli_real_escape_string($koneksi, trim($_POST['kec']));
|
||||
$kab = mysqli_real_escape_string($koneksi, trim($_POST['kab']));
|
||||
$prov = mysqli_real_escape_string($koneksi, trim($_POST['prov']));
|
||||
$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',
|
||||
@@ -273,70 +261,80 @@ window.addEventListener('load', function() {
|
||||
'$nama_file')";
|
||||
$query_simpan = mysqli_query($koneksi, $sql_simpan);
|
||||
|
||||
// Process Auto-Linking Members
|
||||
$linked_count = 0;
|
||||
$failed_count = 0;
|
||||
$failed_members = []; // Store failed members for detailed feedback
|
||||
|
||||
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']);
|
||||
$nama_mem = isset($mem['nama']) ? mysqli_real_escape_string($koneksi, $mem['nama']) : '';
|
||||
$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++;
|
||||
$failed_members[] = ['nik' => $nik_mem, 'nama' => $nama_mem, 'hubungan' => $hub_mem];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Process Auto-Linking Members
|
||||
if ($query_simpan && !empty($_POST['anggota_json'])) {
|
||||
file_put_contents('debug_log.txt', "----------------------------------------\n", FILE_APPEND);
|
||||
file_put_contents('debug_log.txt', "Saving KK ID: " . mysqli_insert_id($koneksi) . "\n", FILE_APPEND);
|
||||
file_put_contents('debug_log.txt', "Raw JSON: " . $_POST['anggota_json'] . "\n", FILE_APPEND);
|
||||
|
||||
$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']);
|
||||
|
||||
file_put_contents('debug_log.txt', "Processing NIK: $nik_mem\n", FILE_APPEND);
|
||||
|
||||
// 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'];
|
||||
file_put_contents('debug_log.txt', "Found Existing ID: $id_pend_found. Linking...\n", FILE_APPEND);
|
||||
|
||||
// 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')";
|
||||
if (!mysqli_query($koneksi, $sql_add_ang)) {
|
||||
file_put_contents('debug_log.txt', "Link Error: " . mysqli_error($koneksi) . "\n", FILE_APPEND);
|
||||
} else {
|
||||
file_put_contents('debug_log.txt', "Success Link ID $id_pend_found\n", FILE_APPEND);
|
||||
}
|
||||
} else {
|
||||
// Create New Resident if not found
|
||||
file_put_contents('debug_log.txt', "NIK Not Found. Creating New.\n", FILE_APPEND);
|
||||
|
||||
$nama_mem = mysqli_real_escape_string($koneksi, $mem['nama']);
|
||||
$tempat_lh = mysqli_real_escape_string($koneksi, $mem['tempat_lh'] ?? '-');
|
||||
$tgl_lh = mysqli_real_escape_string($koneksi, $mem['tgl_lh'] ?? '0000-00-00');
|
||||
$jekel = mysqli_real_escape_string($koneksi, $mem['jekel'] ?? 'LK');
|
||||
$agama = mysqli_real_escape_string($koneksi, $mem['agama'] ?? 'Islam');
|
||||
$kawin = mysqli_real_escape_string($koneksi, $mem['kawin'] ?? 'Belum Kawin');
|
||||
$pekerjaan = mysqli_real_escape_string($koneksi, $mem['pekerjaan'] ?? 'Pelajar/Mahasiswa');
|
||||
$kewarganegaraan = mysqli_real_escape_string($koneksi, $mem['kewarganegaraan'] ?? 'WNI');
|
||||
|
||||
$sql_new_pend = "INSERT INTO tb_pdd (
|
||||
nik, nama, tempat_lh, tgl_lh, jekel,
|
||||
desa, rt, rw, agama, kawin, pekerjaan, status, kwn
|
||||
) VALUES (
|
||||
'$nik_mem', '$nama_mem', '$tempat_lh', '$tgl_lh', '$jekel',
|
||||
'$desa', '$rt', '$rw', '$agama', '$kawin', '$pekerjaan', 'Ada', '$kewarganegaraan'
|
||||
)";
|
||||
|
||||
if (mysqli_query($koneksi, $sql_new_pend)) {
|
||||
$id_pend_new = mysqli_insert_id($koneksi);
|
||||
file_put_contents('debug_log.txt', "Created New ID: $id_pend_new. Linking...\n", FILE_APPEND);
|
||||
|
||||
// Link to KK
|
||||
$sql_add_ang = "INSERT INTO tb_anggota (id_kk, id_pend, hubungan) VALUES ('$id_kk_baru', '$id_pend_new', '$hub_mem')";
|
||||
mysqli_query($koneksi, $sql_add_ang);
|
||||
} else {
|
||||
file_put_contents('debug_log.txt', "Error Creating Resident: " . mysqli_error($koneksi) . "\n", FILE_APPEND);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
file_put_contents('debug_log.txt', "JSON Decode Failed or Not Array\n", FILE_APPEND);
|
||||
}
|
||||
}
|
||||
|
||||
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>";
|
||||
// Add detailed failed members list if any
|
||||
if (!empty($failed_members)) {
|
||||
$msg_add .= "<br><br><b>Detail Anggota Tidak Ditemukan:</b><br>";
|
||||
$msg_add .= "<div style='max-height: 150px; overflow-y: auto; background: #f8f9fa; border: 1px solid #ddd; padding: 5px; font-size: 0.9rem;'>";
|
||||
foreach ($failed_members as $fm) {
|
||||
$url_params = http_build_query([
|
||||
'nik' => $fm['nik'],
|
||||
'nama' => $fm['nama'],
|
||||
'desa' => $desa,
|
||||
'rt' => $rt,
|
||||
'rw' => $rw,
|
||||
'kecamatan' => $kec,
|
||||
'kabupaten' => $kab,
|
||||
'provinsi' => $prov
|
||||
]);
|
||||
$add_link = "<a href='index.php?page=add-pend&$url_params' class='btn btn-xs btn-outline-primary ml-2'>Tambah</a>";
|
||||
$msg_add .= "• <b>" . htmlspecialchars($fm['nik']) . "</b> - " . htmlspecialchars($fm['nama']) . " (" . htmlspecialchars($fm['hubungan']) . ") $add_link<br>";
|
||||
}
|
||||
$msg_add .= "</div>";
|
||||
$msg_add .= "<small class='text-muted'>Tambahkan data penduduk yang belum terdaftar melalui menu <a href='index.php?page=add-pend'>Tambah Penduduk</a>.</small>";
|
||||
}
|
||||
}
|
||||
|
||||
if ($query_simpan) {
|
||||
echo "<script>
|
||||
Swal.fire({title: 'Tambah Data Berhasil',html: 'Data KK disimpan.$msg_add',icon: 'success',confirmButtonText: 'OK'
|
||||
Swal.fire({title: 'Tambah Data Berhasil',text: '',icon: 'success',confirmButtonText: 'OK'
|
||||
}).then((result) => {if (result.value){
|
||||
window.location = 'index.php?page=data-kartu';
|
||||
}
|
||||
|
||||
43
admin/kartu/anggota.php
Executable file → Normal file
43
admin/kartu/anggota.php
Executable file → Normal file
@@ -97,7 +97,7 @@
|
||||
<tr>
|
||||
<th>NIK</th>
|
||||
<th>Nama</th>
|
||||
<th>Jenis Kelamin</th>
|
||||
<th>Jekel</th>
|
||||
<th>Hub Keluarga</th>
|
||||
<th>Aksi</th>
|
||||
</tr>
|
||||
@@ -119,21 +119,13 @@
|
||||
<?php echo $data['nama']; ?>
|
||||
</td>
|
||||
<td>
|
||||
<?php
|
||||
if ($data['jekel'] == 'LK') {
|
||||
echo 'LAKI-LAKI';
|
||||
} elseif ($data['jekel'] == 'PR') {
|
||||
echo 'PEREMPUAN';
|
||||
} else {
|
||||
echo $data['jekel'];
|
||||
}
|
||||
?>
|
||||
<?php echo $data['jekel']; ?>
|
||||
</td>
|
||||
<td>
|
||||
<?php echo $data['hubungan']; ?>
|
||||
</td>
|
||||
<td>
|
||||
<a href="?page=del-anggota&kode=<?php echo $data['id_anggota']; ?>" onclick="confirmDelete(event)"
|
||||
<a href="?page=del-anggota&kode=<?php echo $data['id_anggota']; ?>" onclick="return confirm('Apakah anda yakin hapus data ini ?')"
|
||||
title="Hapus" class="btn btn-danger btn-sm">
|
||||
<i class="fa fa-trash"></i>
|
||||
</a>
|
||||
@@ -143,30 +135,11 @@
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
</tbody>
|
||||
</tfoot>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
function confirmDelete(event) {
|
||||
event.preventDefault();
|
||||
Swal.fire({
|
||||
title: 'Konfirmasi Hapus',
|
||||
text: 'Apakah Anda yakin ingin menghapus data ini?',
|
||||
icon: 'warning',
|
||||
showCancelButton: true,
|
||||
confirmButtonColor: '#d33',
|
||||
cancelButtonColor: '#3085d6',
|
||||
confirmButtonText: 'Ya, Hapus',
|
||||
cancelButtonText: 'Batal'
|
||||
}).then((result) => {
|
||||
if (result.isConfirmed) {
|
||||
window.location.href = event.currentTarget.href;
|
||||
}
|
||||
});
|
||||
}
|
||||
</script>
|
||||
</tbody>
|
||||
</tfoot>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-footer">
|
||||
<a href="?page=data-kartu" title="Kembali" class="btn btn-warning">Kembali</a>
|
||||
|
||||
12
admin/kartu/anggota_full.php
Executable file → Normal file
12
admin/kartu/anggota_full.php
Executable file → Normal file
@@ -59,7 +59,7 @@
|
||||
<th>No</th>
|
||||
<th>NIK</th>
|
||||
<th>Nama</th>
|
||||
<th>Jenis Kelamin</th>
|
||||
<th>Jekel</th>
|
||||
<th>Hub Keluarga</th>
|
||||
<th>Status</th>
|
||||
</tr>
|
||||
@@ -85,15 +85,7 @@
|
||||
<?php echo $data['nama']; ?>
|
||||
</td>
|
||||
<td>
|
||||
<?php
|
||||
if ($data['jekel'] == 'LK') {
|
||||
echo 'LAKI-LAKI';
|
||||
} elseif ($data['jekel'] == 'PR') {
|
||||
echo 'PEREMPUAN';
|
||||
} else {
|
||||
echo $data['jekel'];
|
||||
}
|
||||
?>
|
||||
<?php echo $data['jekel']; ?>
|
||||
</td>
|
||||
<td>
|
||||
<?php echo $data['hubungan']; ?>
|
||||
|
||||
0
admin/kartu/data_kartu.php
Executable file → Normal file
0
admin/kartu/data_kartu.php
Executable file → Normal file
0
admin/kartu/del_anggota.php
Executable file → Normal file
0
admin/kartu/del_anggota.php
Executable file → Normal file
0
admin/kartu/del_kartu.php
Executable file → Normal file
0
admin/kartu/del_kartu.php
Executable file → Normal file
6
admin/kartu/edit_kartu.php
Executable file → Normal file
6
admin/kartu/edit_kartu.php
Executable file → Normal file
@@ -52,7 +52,7 @@
|
||||
</div>
|
||||
|
||||
<div class="form-group row">
|
||||
<label class="col-sm-2 col-form-label">Kepala Keluarga</label>
|
||||
<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" value="<?php echo $data_cek['kepala']; ?>"
|
||||
required>
|
||||
@@ -208,8 +208,8 @@ window.addEventListener('load', function() {
|
||||
if(d.no_kk) document.getElementsByName('no_kk')[0].value = d.no_kk;
|
||||
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;
|
||||
document.getElementsByName('rt')[0].value = d.rt || '000';
|
||||
document.getElementsByName('rw')[0].value = d.rw || '000';
|
||||
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;
|
||||
|
||||
145
admin/lahir/add_lahir.php
Executable file → Normal file
145
admin/lahir/add_lahir.php
Executable file → Normal file
@@ -27,16 +27,16 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group row">
|
||||
<label class="col-sm-2 col-form-label">Jenis Kelamin</label>
|
||||
<div class="col-sm-3">
|
||||
<select name="jekel" id="jekel" class="form-control">
|
||||
<option>- Pilih -</option>
|
||||
<option>LK</option>
|
||||
<option>PR</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<label class="col-sm-2 col-form-label">Jenis Kelain</label>
|
||||
<div class="col-sm-3">
|
||||
<select name="jekel" id="jekel" class="form-control">
|
||||
<option>- Pilih -</option>
|
||||
<option>LK</option>
|
||||
<option>PR</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group row">
|
||||
<label class="col-sm-2 col-form-label">Keluarga</label>
|
||||
@@ -69,69 +69,62 @@
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<?php
|
||||
|
||||
if (isset ($_POST['Simpan'])){
|
||||
//mulai proses simpan data
|
||||
|
||||
// Sanitize Input to prevent SQL Injection & Syntax Errors
|
||||
$nik = mysqli_real_escape_string($koneksi, trim($_POST['nik']));
|
||||
$nama = mysqli_real_escape_string($koneksi, trim($_POST['nama']));
|
||||
$tgl_lh = mysqli_real_escape_string($koneksi, trim($_POST['tgl_lh']));
|
||||
$jekel = mysqli_real_escape_string($koneksi, trim($_POST['jekel']));
|
||||
$id_kk = (int)$_POST['id_kk']; // Cast to integer for safety
|
||||
|
||||
$sql_simpan = "INSERT INTO tb_lahir (nama, tgl_lh, jekel, id_kk) VALUES (
|
||||
'$nama',
|
||||
'$tgl_lh',
|
||||
'$jekel',
|
||||
'$id_kk')";
|
||||
$query_simpan = mysqli_query($koneksi, $sql_simpan);
|
||||
|
||||
// Otomatis tambah ke Data Penduduk
|
||||
// Ambil data alamat dari KK
|
||||
$sql_kk = "SELECT desa, rt, rw FROM tb_kk WHERE id_kk='$id_kk'";
|
||||
$q_kk = mysqli_query($koneksi, $sql_kk);
|
||||
$d_kk = mysqli_fetch_array($q_kk);
|
||||
$desa = $d_kk['desa'];
|
||||
$rt = $d_kk['rt'];
|
||||
$rw = $d_kk['rw'];
|
||||
|
||||
$sql_pdd = "INSERT INTO tb_pdd (nik, nama, tempat_lh, tgl_lh, jekel, desa, rt, rw, agama, kawin, pekerjaan, status) VALUES (
|
||||
'$nik',
|
||||
'$nama',
|
||||
'-',
|
||||
'$tgl_lh',
|
||||
'$jekel',
|
||||
'$desa', '$rt', '$rw',
|
||||
'-', 'Belum', 'Belum/Tidak Bekerja', 'Ada')";
|
||||
$query_pdd = mysqli_query($koneksi, $sql_pdd);
|
||||
|
||||
// Ambil ID Penduduk yang baru dibuat
|
||||
$id_pend_baru = mysqli_insert_id($koneksi);
|
||||
|
||||
// Masukkan ke Anggota KK
|
||||
$sql_anggota = "INSERT INTO tb_anggota (id_kk, id_pend, hubungan) VALUES (
|
||||
'$id_kk',
|
||||
'$id_pend_baru',
|
||||
'Anak')";
|
||||
$query_anggota = mysqli_query($koneksi, $sql_anggota);
|
||||
|
||||
mysqli_close($koneksi);
|
||||
|
||||
if ($query_simpan && $query_pdd && $query_anggota) {
|
||||
echo "<script>
|
||||
Swal.fire({title: 'Tambah Data Berhasil',text: '',icon: 'success',confirmButtonText: 'OK'
|
||||
}).then((result) => {if (result.value){
|
||||
window.location = 'index.php?page=data-lahir';
|
||||
}
|
||||
})</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-lahir';
|
||||
}
|
||||
})</script>";
|
||||
}}
|
||||
//selesai proses simpan data
|
||||
<?php
|
||||
|
||||
if (isset ($_POST['Simpan'])){
|
||||
//mulai proses simpan data
|
||||
$sql_simpan = "INSERT INTO tb_lahir (nama, tgl_lh, jekel, id_kk) VALUES (
|
||||
'".$_POST['nama']."',
|
||||
'".$_POST['tgl_lh']."',
|
||||
'".$_POST['jekel']."',
|
||||
'".$_POST['id_kk']."')";
|
||||
$query_simpan = mysqli_query($koneksi, $sql_simpan);
|
||||
|
||||
// Otomatis tambah ke Data Penduduk
|
||||
// Ambil data alamat dari KK
|
||||
$id_kk = $_POST['id_kk'];
|
||||
$sql_kk = "SELECT desa, rt, rw FROM tb_kk WHERE id_kk='$id_kk'";
|
||||
$q_kk = mysqli_query($koneksi, $sql_kk);
|
||||
$d_kk = mysqli_fetch_array($q_kk);
|
||||
$desa = $d_kk['desa'];
|
||||
$rt = $d_kk['rt'];
|
||||
$rw = $d_kk['rw'];
|
||||
|
||||
$sql_pdd = "INSERT INTO tb_pdd (nik, nama, tempat_lh, tgl_lh, jekel, desa, rt, rw, agama, kawin, pekerjaan, status) VALUES (
|
||||
'".$_POST['nik']."',
|
||||
'".$_POST['nama']."',
|
||||
'-',
|
||||
'".$_POST['tgl_lh']."',
|
||||
'".$_POST['jekel']."',
|
||||
'$desa', '$rt', '$rw',
|
||||
'-', 'Belum', 'Belum/Tidak Bekerja', 'Ada')";
|
||||
$query_pdd = mysqli_query($koneksi, $sql_pdd);
|
||||
|
||||
// Ambil ID Penduduk yang baru dibuat
|
||||
$id_pend_baru = mysqli_insert_id($koneksi);
|
||||
|
||||
// Masukkan ke Anggota KK
|
||||
$sql_anggota = "INSERT INTO tb_anggota (id_kk, id_pend, hubungan) VALUES (
|
||||
'$id_kk',
|
||||
'$id_pend_baru',
|
||||
'Anak')";
|
||||
$query_anggota = mysqli_query($koneksi, $sql_anggota);
|
||||
|
||||
mysqli_close($koneksi);
|
||||
|
||||
if ($query_simpan && $query_pdd && $query_anggota) {
|
||||
echo "<script>
|
||||
Swal.fire({title: 'Tambah Data Berhasil',text: '',icon: 'success',confirmButtonText: 'OK'
|
||||
}).then((result) => {if (result.value){
|
||||
window.location = 'index.php?page=data-lahir';
|
||||
}
|
||||
})</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-lahir';
|
||||
}
|
||||
})</script>";
|
||||
}}
|
||||
//selesai proses simpan data
|
||||
|
||||
43
admin/lahir/data_lahir.php
Executable file → Normal file
43
admin/lahir/data_lahir.php
Executable file → Normal file
@@ -17,7 +17,7 @@
|
||||
<th>No</th>
|
||||
<th>Nama</th>
|
||||
<th>Tgl Lahir</th>
|
||||
<th>Jenis Kelamin</th>
|
||||
<th>Jekel</th>
|
||||
<th>Keluarga</th>
|
||||
<th>Aksi</th>
|
||||
</tr>
|
||||
@@ -42,15 +42,7 @@
|
||||
<?php echo $data['tgl_lh']; ?>
|
||||
</td>
|
||||
<td>
|
||||
<?php
|
||||
if ($data['jekel'] == 'LK') {
|
||||
echo 'LAKI-LAKI';
|
||||
} elseif ($data['jekel'] == 'PR') {
|
||||
echo 'PEREMPUAN';
|
||||
} else {
|
||||
echo $data['jekel'];
|
||||
}
|
||||
?>
|
||||
<?php echo $data['jekel']; ?>
|
||||
</td>
|
||||
<td>
|
||||
<?php echo $data['no_kk']; ?>-
|
||||
@@ -61,10 +53,10 @@
|
||||
class="btn btn-success btn-sm">
|
||||
<i class="fa fa-edit"></i>
|
||||
</a>
|
||||
<a href="?page=del-lahir&kode=<?php echo $data['id_lahir']; ?>" onclick="confirmDelete(event)"
|
||||
<a href="?page=del-lahir&kode=<?php echo $data['id_lahir']; ?>" onclick="return confirm('Apakah anda yakin hapus data ini ?')"
|
||||
title="Hapus" class="btn btn-danger btn-sm">
|
||||
<i class="fa fa-trash"></i>
|
||||
</a>
|
||||
</>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
@@ -73,26 +65,7 @@
|
||||
?>
|
||||
</tbody>
|
||||
</tfoot>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<!-- /.card-body -->
|
||||
<script>
|
||||
function confirmDelete(event) {
|
||||
event.preventDefault();
|
||||
Swal.fire({
|
||||
title: 'Konfirmasi Hapus',
|
||||
text: 'Apakah Anda yakin ingin menghapus data ini?',
|
||||
icon: 'warning',
|
||||
showCancelButton: true,
|
||||
confirmButtonColor: '#d33',
|
||||
cancelButtonColor: '#3085d6',
|
||||
confirmButtonText: 'Ya, Hapus',
|
||||
cancelButtonText: 'Batal'
|
||||
}).then((result) => {
|
||||
if (result.isConfirmed) {
|
||||
window.location.href = event.currentTarget.href;
|
||||
}
|
||||
});
|
||||
}
|
||||
</script>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<!-- /.card-body -->
|
||||
0
admin/lahir/del_lahir.php
Executable file → Normal file
0
admin/lahir/del_lahir.php
Executable file → Normal file
0
admin/lahir/edit_lahir.php
Executable file → Normal file
0
admin/lahir/edit_lahir.php
Executable file → Normal file
0
admin/laporan/laporan_klasifikasi.php
Executable file → Normal file
0
admin/laporan/laporan_klasifikasi.php
Executable file → Normal file
70
admin/mendu/add_mendu.php
Executable file → Normal file
70
admin/mendu/add_mendu.php
Executable file → Normal file
@@ -52,41 +52,35 @@
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<?php
|
||||
|
||||
if (isset ($_POST['Simpan'])){
|
||||
//mulai proses simpan data
|
||||
|
||||
// Sanitize Input to prevent SQL Injection & Syntax Errors
|
||||
$id_pdd = (int)$_POST['id_pdd']; // Cast to integer for safety
|
||||
$tgl_mendu = mysqli_real_escape_string($koneksi, trim($_POST['tgl_mendu']));
|
||||
$sebab = mysqli_real_escape_string($koneksi, trim($_POST['sebab']));
|
||||
|
||||
$sql_simpan = "INSERT INTO tb_mendu (id_pdd, tgl_mendu, sebab) VALUES (
|
||||
'$id_pdd',
|
||||
'$tgl_mendu',
|
||||
'$sebab')";
|
||||
$query_simpan = mysqli_query($koneksi, $sql_simpan);
|
||||
|
||||
$sql_ubah = "UPDATE tb_pdd SET
|
||||
status='Meninggal'
|
||||
WHERE id_pend='$id_pdd'";
|
||||
$query_ubah = mysqli_query($koneksi, $sql_ubah);
|
||||
mysqli_close($koneksi);
|
||||
|
||||
if ($query_simpan && $query_ubah) {
|
||||
echo "<script>
|
||||
Swal.fire({title: 'Tambah Data Berhasil',text: '',icon: 'success',confirmButtonText: 'OK'
|
||||
}).then((result) => {if (result.value){
|
||||
window.location = 'index.php?page=data-mendu';
|
||||
}
|
||||
})</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-mendu';
|
||||
}
|
||||
})</script>";
|
||||
}}
|
||||
//selesai proses simpan data
|
||||
<?php
|
||||
|
||||
if (isset ($_POST['Simpan'])){
|
||||
//mulai proses simpan data
|
||||
$sql_simpan = "INSERT INTO tb_mendu (id_pdd, tgl_mendu, sebab) VALUES (
|
||||
'".$_POST['id_pdd']."',
|
||||
'".$_POST['tgl_mendu']."',
|
||||
'".$_POST['sebab']."')";
|
||||
$query_simpan = mysqli_query($koneksi, $sql_simpan);
|
||||
|
||||
$sql_ubah = "UPDATE tb_pdd SET
|
||||
status='Meninggal'
|
||||
WHERE id_pend='".$_POST['id_pdd']."'";
|
||||
$query_ubah = mysqli_query($koneksi, $sql_ubah);
|
||||
mysqli_close($koneksi);
|
||||
|
||||
if ($query_simpan && $query_ubah) {
|
||||
echo "<script>
|
||||
Swal.fire({title: 'Tambah Data Berhasil',text: '',icon: 'success',confirmButtonText: 'OK'
|
||||
}).then((result) => {if (result.value){
|
||||
window.location = 'index.php?page=data-mendu';
|
||||
}
|
||||
})</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-mendu';
|
||||
}
|
||||
})</script>";
|
||||
}}
|
||||
//selesai proses simpan data
|
||||
|
||||
59
admin/mendu/data_mendu.php
Executable file → Normal file
59
admin/mendu/data_mendu.php
Executable file → Normal file
@@ -13,21 +13,20 @@
|
||||
<br>
|
||||
<table id="example1" class="table table-bordered table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>No</th>
|
||||
<th>NIK</th>
|
||||
<th>Nama</th>
|
||||
<th>Jenis Kelamin</th>
|
||||
<th>Tanggal</th>
|
||||
<th>Sebab</th>
|
||||
<th>Aksi</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>No</th>
|
||||
<th>NIK</th>
|
||||
<th>Nama</th>
|
||||
<th>Tanggal</th>
|
||||
<th>Sebab</th>
|
||||
<th>Aksi</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
||||
<?php
|
||||
$no = 1;
|
||||
$sql = $koneksi->query("SELECT p.id_pend, p.nik, p.nama, p.jekel, m.tgl_mendu, m.sebab, m.id_mendu from
|
||||
$sql = $koneksi->query("SELECT p.id_pend, p.nik, p.nama, m.tgl_mendu, m.sebab, m.id_mendu from
|
||||
tb_mendu m inner join tb_pdd p on p.id_pend=m.id_pdd");
|
||||
while ($data= $sql->fetch_assoc()) {
|
||||
?>
|
||||
@@ -42,12 +41,9 @@
|
||||
<td>
|
||||
<?php echo $data['nama']; ?>
|
||||
</td>
|
||||
<td>
|
||||
<?php echo $data['jekel'] == 'LK' ? 'LAKI-LAKI' : 'PEREMPUAN'; ?>
|
||||
</td>
|
||||
<td>
|
||||
<?php echo $data['tgl_mendu']; ?>
|
||||
</td>
|
||||
<td>
|
||||
<?php echo $data['tgl_mendu']; ?>
|
||||
</td>
|
||||
<td>
|
||||
<?php echo $data['sebab']; ?>
|
||||
</td>
|
||||
@@ -60,10 +56,10 @@
|
||||
class="btn btn-success btn-sm">
|
||||
<i class="fa fa-edit"></i>
|
||||
</a>
|
||||
<a href="?page=del-mendu&kode=<?php echo $data['id_pend']; ?>" onclick="confirmDelete(event)"
|
||||
<a href="?page=del-mendu&kode=<?php echo $data['id_pend']; ?>" onclick="return confirm('Apakah anda yakin hapus data ini ?')"
|
||||
title="Hapus" class="btn btn-danger btn-sm">
|
||||
<i class="fa fa-trash"></i>
|
||||
</a>
|
||||
</>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
@@ -72,26 +68,7 @@
|
||||
?>
|
||||
</tbody>
|
||||
</tfoot>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<!-- /.card-body -->
|
||||
<script>
|
||||
function confirmDelete(event) {
|
||||
event.preventDefault();
|
||||
Swal.fire({
|
||||
title: 'Konfirmasi Hapus',
|
||||
text: 'Apakah Anda yakin ingin menghapus data ini?',
|
||||
icon: 'warning',
|
||||
showCancelButton: true,
|
||||
confirmButtonColor: '#d33',
|
||||
cancelButtonColor: '#3085d6',
|
||||
confirmButtonText: 'Ya, Hapus',
|
||||
cancelButtonText: 'Batal'
|
||||
}).then((result) => {
|
||||
if (result.isConfirmed) {
|
||||
window.location.href = event.currentTarget.href;
|
||||
}
|
||||
});
|
||||
}
|
||||
</script>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<!-- /.card-body -->
|
||||
0
admin/mendu/del_mendu.php
Executable file → Normal file
0
admin/mendu/del_mendu.php
Executable file → Normal file
0
admin/mendu/edit_mendu.php
Executable file → Normal file
0
admin/mendu/edit_mendu.php
Executable file → Normal file
10
admin/mendu/view_mendu.php
Executable file → Normal file
10
admin/mendu/view_mendu.php
Executable file → Normal file
@@ -90,15 +90,7 @@
|
||||
<b>Jenis Kelamin</b>
|
||||
</td>
|
||||
<td>:
|
||||
<?php
|
||||
if ($data_cek['jekel'] == 'LK') {
|
||||
echo 'LAKI-LAKI';
|
||||
} elseif ($data_cek['jekel'] == 'PR') {
|
||||
echo 'PEREMPUAN';
|
||||
} else {
|
||||
echo $data_cek['jekel'];
|
||||
}
|
||||
?>
|
||||
<?php echo $data_cek['jekel']; ?>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
|
||||
322
admin/pend/add_pend.php
Executable file → Normal file
322
admin/pend/add_pend.php
Executable file → Normal file
@@ -1,6 +1,3 @@
|
||||
<?php
|
||||
$return_to = isset($_GET['return_to']) ? mysqli_real_escape_string($koneksi, trim($_GET['return_to'])) : '';
|
||||
?>
|
||||
<div class="card card-primary">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">
|
||||
@@ -91,10 +88,10 @@ $return_to = isset($_GET['return_to']) ? mysqli_real_escape_string($koneksi, tri
|
||||
<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" value="000" required>
|
||||
<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" value="000" required>
|
||||
<input type="text" class="form-control" id="rw" name="rw" placeholder="RW" required>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -130,16 +127,10 @@ $return_to = isset($_GET['return_to']) ? mysqli_real_escape_string($koneksi, tri
|
||||
<div class="col-sm-6">
|
||||
<input type="text" class="form-control" id="kewarganegaraan" name="kewarganegaraan" placeholder="WNI/WNA" required>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group row">
|
||||
<label class="col-sm-2 col-form-label">No. Telepon</label>
|
||||
<div class="col-sm-6">
|
||||
<input type="text" class="form-control" id="phone" name="phone" placeholder="Nomor Telepon">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
<div class="card-footer">
|
||||
<input type="submit" name="Simpan" value="Simpan" class="btn btn-info">
|
||||
@@ -149,62 +140,11 @@ $return_to = isset($_GET['return_to']) ? mysqli_real_escape_string($koneksi, tri
|
||||
</div>
|
||||
|
||||
<script>
|
||||
window.addEventListener('load', function() {
|
||||
// Pre-fill form from URL parameters
|
||||
var urlParams = new URLSearchParams(window.location.search);
|
||||
if (urlParams.has('nik')) document.getElementsByName('nik')[0].value = urlParams.get('nik');
|
||||
if (urlParams.has('nama')) document.getElementsByName('nama')[0].value = urlParams.get('nama');
|
||||
if (urlParams.has('desa')) document.getElementsByName('desa')[0].value = urlParams.get('desa');
|
||||
if (urlParams.has('rt')) document.getElementsByName('rt')[0].value = urlParams.get('rt');
|
||||
if (urlParams.has('rw')) document.getElementsByName('rw')[0].value = urlParams.get('rw');
|
||||
if (urlParams.has('kecamatan')) document.getElementsByName('kecamatan')[0].value = urlParams.get('kecamatan');
|
||||
if (urlParams.has('kabupaten')) document.getElementsByName('kabupaten')[0].value = urlParams.get('kabupaten');
|
||||
if (urlParams.has('provinsi')) document.getElementsByName('provinsi')[0].value = urlParams.get('provinsi');
|
||||
|
||||
// NIK Validation (16 digits, numeric)
|
||||
var nikInput = document.getElementsByName('nik')[0];
|
||||
function validateNIK(nik) {
|
||||
nik = nik.trim();
|
||||
if (nik.length !== 16) return false;
|
||||
return /^\d+$/.test(nik); // Only digits
|
||||
}
|
||||
function showNIKError(message) {
|
||||
Swal.fire({
|
||||
icon: 'warning',
|
||||
title: 'Format NIK Salah',
|
||||
text: message,
|
||||
confirmButtonText: 'OK'
|
||||
});
|
||||
}
|
||||
// Validate on blur
|
||||
if (nikInput) {
|
||||
nikInput.addEventListener('blur', function() {
|
||||
var nik = this.value.trim();
|
||||
if (nik === '') return;
|
||||
if (!validateNIK(nik)) {
|
||||
showNIKError('NIK harus terdiri dari 16 digit angka.');
|
||||
this.focus();
|
||||
}
|
||||
});
|
||||
}
|
||||
// Validate on form submit
|
||||
var form = document.querySelector('form');
|
||||
if (form) {
|
||||
form.addEventListener('submit', function(e) {
|
||||
var nik = nikInput.value.trim();
|
||||
if (nik !== '' && !validateNIK(nik)) {
|
||||
e.preventDefault();
|
||||
showNIKError('NIK harus terdiri dari 16 digit angka.');
|
||||
nikInput.focus();
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Scanner Logic
|
||||
var inputImage = document.getElementById('foto_ktp');
|
||||
var preview = document.getElementById('preview_ktp');
|
||||
var hiddenInput = document.getElementById('foto_cropped');
|
||||
window.addEventListener('load', function() {
|
||||
// Scanner Logic
|
||||
var inputImage = document.getElementById('foto_ktp');
|
||||
var preview = document.getElementById('preview_ktp');
|
||||
var hiddenInput = document.getElementById('foto_cropped');
|
||||
|
||||
// Defines callback for scanner modal
|
||||
window.handleScannerResult = function(base64) {
|
||||
@@ -391,146 +331,102 @@ window.addEventListener('load', function() {
|
||||
}
|
||||
|
||||
//mulai proses simpan data
|
||||
$nik = mysqli_real_escape_string($koneksi, trim($_POST['nik']));
|
||||
$cek_nik = mysqli_query($koneksi, "SELECT * FROM tb_pdd WHERE nik='$nik'");
|
||||
if(mysqli_num_rows($cek_nik) > 0){
|
||||
echo "<script>
|
||||
Swal.fire({title: 'Gagal',text: 'NIK sudah terdaftar dalam sistem!',icon: 'error',confirmButtonText: 'OK'
|
||||
}).then((result) => {if (result.value){
|
||||
window.location = 'index.php?page=add-pend" . (!empty($return_to) ? '&return_to=' . $return_to : '') . "';
|
||||
}
|
||||
})</script>";
|
||||
return;
|
||||
}
|
||||
|
||||
// Sanitize Input to prevent SQL Injection & Syntax Errors
|
||||
$nama = mysqli_real_escape_string($koneksi, trim($_POST['nama']));
|
||||
$tempat_lh = mysqli_real_escape_string($koneksi, trim($_POST['tempat_lh']));
|
||||
$tgl_lh = mysqli_real_escape_string($koneksi, trim($_POST['tgl_lh']));
|
||||
$jekel = mysqli_real_escape_string($koneksi, trim($_POST['jekel']));
|
||||
$desa = mysqli_real_escape_string($koneksi, trim($_POST['desa']));
|
||||
$rt = mysqli_real_escape_string($koneksi, trim($_POST['rt']));
|
||||
$rw = mysqli_real_escape_string($koneksi, trim($_POST['rw']));
|
||||
$agama = mysqli_real_escape_string($koneksi, trim($_POST['agama']));
|
||||
$kawin = mysqli_real_escape_string($koneksi, trim($_POST['kawin']));
|
||||
$pekerjaan = mysqli_real_escape_string($koneksi, trim($_POST['pekerjaan']));
|
||||
$kecamatan = mysqli_real_escape_string($koneksi, trim($_POST['kecamatan']));
|
||||
$kabupaten = mysqli_real_escape_string($koneksi, trim($_POST['kabupaten']));
|
||||
$provinsi = mysqli_real_escape_string($koneksi, trim($_POST['provinsi']));
|
||||
$kewarganegaraan = mysqli_real_escape_string($koneksi, trim($_POST['kewarganegaraan']));
|
||||
$phone = mysqli_real_escape_string($koneksi, trim($_POST['phone']));
|
||||
|
||||
|
||||
$sql_simpan = "INSERT INTO tb_pdd (nik, nama, tempat_lh, tgl_lh, jekel, desa, rt, rw, agama, kawin, pekerjaan, foto_ktp, status, kecamatan, kabupaten, provinsi, kewarganegaraan, phone) VALUES (
|
||||
'$nik',
|
||||
'$nama',
|
||||
'$tempat_lh',
|
||||
'$tgl_lh',
|
||||
'$jekel',
|
||||
'$desa',
|
||||
'$rt',
|
||||
'$rw',
|
||||
'$agama',
|
||||
'$kawin',
|
||||
'$pekerjaan',
|
||||
'$nama_file',
|
||||
'Ada',
|
||||
'$kecamatan',
|
||||
'$kabupaten',
|
||||
'$provinsi',
|
||||
'$kewarganegaraan', '$phone')";
|
||||
$query_simpan = mysqli_query($koneksi, $sql_simpan);
|
||||
|
||||
if ($query_simpan) {
|
||||
$id_pend_baru = mysqli_insert_id($koneksi);
|
||||
$redirect_url = !empty($return_to) ? "index.php?page=" . $return_to . "&selected_id=" . $id_pend_baru : "index.php?page=data-pend";
|
||||
|
||||
// KTP → KK: Cari KK yang cocok berdasarkan alamat
|
||||
$sql_cari_kk = "SELECT k.id_kk, k.no_kk, k.kepala, k.desa, k.rt, k.rw
|
||||
FROM tb_kk k
|
||||
WHERE k.desa='$desa' AND k.rt='$rt' AND k.rw='$rw'
|
||||
AND k.kec='$kecamatan' AND k.kab='$kabupaten' AND k.prov='$provinsi'";
|
||||
$q_cari_kk = mysqli_query($koneksi, $sql_cari_kk);
|
||||
$kk_cocok = mysqli_fetch_assoc($q_cari_kk);
|
||||
|
||||
if ($kk_cocok) {
|
||||
// Tawarkan untuk menghubungkan dengan KK
|
||||
$no_kk = $kk_cocok['no_kk'];
|
||||
$kepala_kk = $kk_cocok['kepala'];
|
||||
$id_kk = $kk_cocok['id_kk'];
|
||||
|
||||
// Cek apakah sudah terhubung
|
||||
$sql_cek_hubungan = "SELECT * FROM tb_anggota WHERE id_kk='$id_kk' AND id_pend='$id_pend_baru'";
|
||||
$q_cek_hubungan = mysqli_query($koneksi, $sql_cek_hubungan);
|
||||
|
||||
if (mysqli_num_rows($q_cek_hubungan) == 0) {
|
||||
// Simpan sementara data untuk konfirmasi JavaScript
|
||||
$_SESSION['kk_link_data'] = [
|
||||
'id_pend' => $id_pend_baru,
|
||||
'id_kk' => $id_kk,
|
||||
'no_kk' => $no_kk,
|
||||
'kepala_kk' => $kepala_kk,
|
||||
'nama_pend' => $nama
|
||||
];
|
||||
|
||||
echo "<script>
|
||||
Swal.fire({
|
||||
title: 'Data Penduduk Disimpan!',
|
||||
html: '<b>Data berhasil disimpan.</b><br><br>Ditemukan KK dengan alamat yang sama:<br><b>No KK: $no_kk</b><br>Kepala Keluarga: $kepala_kk<br><br>Hubungkan ke KK ini sebagai anggota?',
|
||||
icon: 'success',
|
||||
showCancelButton: true,
|
||||
confirmButtonText: 'Ya, Hubungkan',
|
||||
cancelButtonText: 'Tidak, Simpan Saja'
|
||||
}).then((result) => {
|
||||
if (result.value) {
|
||||
// Kirim permintaan untuk menghubungkan
|
||||
fetch('admin/pend/link_to_kk.php', {
|
||||
method: 'POST',
|
||||
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
|
||||
body: 'id_pend=$id_pend_baru&id_kk=$id_kk&hubungan=ANGGOTA'
|
||||
}).then(resp => resp.json()).then(data => {
|
||||
if(data.success) {
|
||||
Swal.fire('Berhasil!', 'Data telah dihubungkan dengan KK.', 'success').then(() => {
|
||||
window.location = '$redirect_url';
|
||||
});
|
||||
} else {
|
||||
Swal.fire('Gagal', 'Gagal menghubungkan: ' + data.message, 'error').then(() => {
|
||||
window.location = '$redirect_url';
|
||||
});
|
||||
}
|
||||
});
|
||||
} else {
|
||||
window.location = '$redirect_url';
|
||||
}
|
||||
});
|
||||
</script>";
|
||||
} else {
|
||||
// Sudah terhubung
|
||||
echo "<script>
|
||||
Swal.fire({title: 'Tambah Data Berhasil',text: 'Data telah terhubung dengan KK $no_kk',icon: 'success',confirmButtonText: 'OK'
|
||||
}).then((result) => {if (result.value){
|
||||
window.location = '$redirect_url';
|
||||
}
|
||||
})</script>";
|
||||
}
|
||||
} else {
|
||||
// Tidak ada KK yang cocok
|
||||
echo "<script>
|
||||
Swal.fire({title: 'Tambah Data Berhasil',text: '',icon: 'success',confirmButtonText: 'OK'
|
||||
}).then((result) => {if (result.value){
|
||||
window.location = '$redirect_url';
|
||||
}
|
||||
})</script>";
|
||||
}
|
||||
} else {
|
||||
$error_redirect = 'index.php?page=add-pend' . (!empty($return_to) ? '&return_to=' . $return_to : '');
|
||||
echo "<script>
|
||||
Swal.fire({title: 'Tambah Data Gagal',text: '" . mysqli_error($koneksi) . "',icon: 'error',confirmButtonText: 'OK'
|
||||
}).then((result) => {if (result.value){
|
||||
window.location = '$error_redirect';
|
||||
}
|
||||
})</script>";
|
||||
}
|
||||
mysqli_close($koneksi);
|
||||
}
|
||||
$nik = $_POST['nik'];
|
||||
$cek_nik = mysqli_query($koneksi, "SELECT * FROM tb_pdd WHERE nik='$nik'");
|
||||
if(mysqli_num_rows($cek_nik) > 0){
|
||||
// AUTO-LINKING: Instead of blocking, we UPDATE the existing record with Scan Data
|
||||
// Sanitize input first before UPDATE
|
||||
$nama = mysqli_real_escape_string($koneksi, $_POST['nama']);
|
||||
$tempat_lh = mysqli_real_escape_string($koneksi, $_POST['tempat_lh']);
|
||||
$tgl_lh = mysqli_real_escape_string($koneksi, $_POST['tgl_lh']);
|
||||
$jekel = mysqli_real_escape_string($koneksi, $_POST['jekel']);
|
||||
$desa = mysqli_real_escape_string($koneksi, $_POST['desa']);
|
||||
$rt = mysqli_real_escape_string($koneksi, $_POST['rt']);
|
||||
$rw = mysqli_real_escape_string($koneksi, $_POST['rw']);
|
||||
$agama = mysqli_real_escape_string($koneksi, $_POST['agama']);
|
||||
$kawin = mysqli_real_escape_string($koneksi, $_POST['kawin']);
|
||||
$pekerjaan = mysqli_real_escape_string($koneksi, $_POST['pekerjaan']);
|
||||
$kewarganegaraan = mysqli_real_escape_string($koneksi, $_POST['kewarganegaraan']);
|
||||
|
||||
$sql_update = "UPDATE tb_pdd SET
|
||||
nama='$nama',
|
||||
tempat_lh='$tempat_lh',
|
||||
tgl_lh='$tgl_lh',
|
||||
jekel='$jekel',
|
||||
desa='$desa',
|
||||
rt='$rt',
|
||||
rw='$rw',
|
||||
agama='$agama',
|
||||
kawin='$kawin',
|
||||
pekerjaan='$pekerjaan',
|
||||
kewarganegaraan='$kewarganegaraan',
|
||||
foto_ktp='$nama_file'
|
||||
WHERE nik='$nik'";
|
||||
|
||||
$query_update = mysqli_query($koneksi, $sql_update);
|
||||
|
||||
if ($query_update) {
|
||||
echo "<script>
|
||||
Swal.fire({title: 'Data Diperbarui',text: 'NIK sudah ada, data penduduk telah diperbarui dengan hasil scan KTP.',icon: 'success',confirmButtonText: 'OK'
|
||||
}).then((result) => {if (result.value){
|
||||
window.location = 'index.php?page=data-pend';
|
||||
}
|
||||
})</script>";
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Sanitize Input to prevent SQL Injection & Syntax Errors
|
||||
$nik = mysqli_real_escape_string($koneksi, $_POST['nik']);
|
||||
$nama = mysqli_real_escape_string($koneksi, $_POST['nama']);
|
||||
$tempat_lh = mysqli_real_escape_string($koneksi, $_POST['tempat_lh']);
|
||||
$tgl_lh = mysqli_real_escape_string($koneksi, $_POST['tgl_lh']);
|
||||
$jekel = mysqli_real_escape_string($koneksi, $_POST['jekel']);
|
||||
$desa = mysqli_real_escape_string($koneksi, $_POST['desa']);
|
||||
$rt = mysqli_real_escape_string($koneksi, $_POST['rt']);
|
||||
$rw = mysqli_real_escape_string($koneksi, $_POST['rw']);
|
||||
$agama = mysqli_real_escape_string($koneksi, $_POST['agama']);
|
||||
$kawin = mysqli_real_escape_string($koneksi, $_POST['kawin']);
|
||||
$pekerjaan = mysqli_real_escape_string($koneksi, $_POST['pekerjaan']);
|
||||
$kecamatan = mysqli_real_escape_string($koneksi, $_POST['kecamatan']);
|
||||
$kabupaten = mysqli_real_escape_string($koneksi, $_POST['kabupaten']);
|
||||
$provinsi = mysqli_real_escape_string($koneksi, $_POST['provinsi']);
|
||||
$kewarganegaraan = mysqli_real_escape_string($koneksi, $_POST['kewarganegaraan']);
|
||||
|
||||
$sql_simpan = "INSERT INTO tb_pdd (nik, nama, tempat_lh, tgl_lh, jekel, desa, rt, rw, agama, kawin, pekerjaan, foto_ktp, status, kecamatan, kabupaten, provinsi, kewarganegaraan) VALUES (
|
||||
'$nik',
|
||||
'$nama',
|
||||
'$tempat_lh',
|
||||
'$tgl_lh',
|
||||
'$jekel',
|
||||
'$desa',
|
||||
'$rt',
|
||||
'$rw',
|
||||
'$agama',
|
||||
'$kawin',
|
||||
'$pekerjaan',
|
||||
'$nama_file',
|
||||
'Ada',
|
||||
'$kecamatan',
|
||||
'$kabupaten',
|
||||
'$provinsi',
|
||||
'$kewarganegaraan')";
|
||||
$query_simpan = mysqli_query($koneksi, $sql_simpan);
|
||||
mysqli_close($koneksi);
|
||||
|
||||
if ($query_simpan) {
|
||||
echo "<script>
|
||||
Swal.fire({title: 'Tambah Data Berhasil',text: '',icon: 'success',confirmButtonText: 'OK'
|
||||
}).then((result) => {if (result.value){
|
||||
window.location = 'index.php?page=data-pend';
|
||||
}
|
||||
})</script>";
|
||||
}else{
|
||||
echo "<script>
|
||||
Swal.fire({title: 'Tambah Data Gagal',text: '<?php echo mysqli_error($koneksi); ?>',icon: 'error',confirmButtonText: 'OK'
|
||||
}).then((result) => {if (result.value){
|
||||
window.location = 'index.php?page=add-pend';
|
||||
}
|
||||
})</script>";
|
||||
}}
|
||||
//selesai proses simpan data
|
||||
|
||||
12
admin/pend/data_pend.php
Executable file → Normal file
12
admin/pend/data_pend.php
Executable file → Normal file
@@ -17,7 +17,7 @@
|
||||
<th>No</th>
|
||||
<th>NIK</th>
|
||||
<th>Nama</th>
|
||||
<th>Jenis Kelamin</th>
|
||||
<th>JK</th>
|
||||
<th>Alamat</th>
|
||||
<th>No KK</th>
|
||||
<th>Aksi</th>
|
||||
@@ -59,15 +59,7 @@
|
||||
<?php echo $data['nama']; ?>
|
||||
</td>
|
||||
<td>
|
||||
<?php
|
||||
if ($data['jekel'] == 'LK') {
|
||||
echo 'LAKI-LAKI';
|
||||
} elseif ($data['jekel'] == 'PR') {
|
||||
echo 'PEREMPUAN';
|
||||
} else {
|
||||
echo $data['jekel'];
|
||||
}
|
||||
?>
|
||||
<?php echo $data['jekel']; ?>
|
||||
</td>
|
||||
<td>
|
||||
<?php echo $data['desa']; ?>
|
||||
|
||||
0
admin/pend/del_pend.php
Executable file → Normal file
0
admin/pend/del_pend.php
Executable file → Normal file
22
admin/pend/edit_pend.php
Executable file → Normal file
22
admin/pend/edit_pend.php
Executable file → Normal file
@@ -178,16 +178,9 @@
|
||||
<input type="text" class="form-control" id="kewarganegaraan" name="kewarganegaraan" value="<?php echo $data_cek['kewarganegaraan']; ?>"
|
||||
required>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group row">
|
||||
<label class="col-sm-2 col-form-label">No. Telepon</label>
|
||||
<div class="col-sm-6">
|
||||
<input type="text" class="form-control" id="phone" name="phone" value="<?php echo isset($data_cek['phone']) ? $data_cek['phone'] : ''; ?>" placeholder="Nomor Telepon">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
<div class="card-footer">
|
||||
<input type="submit" name="Ubah" value="Simpan" class="btn btn-success">
|
||||
@@ -389,7 +382,6 @@
|
||||
$kabupaten = mysqli_real_escape_string($koneksi, $_POST['kabupaten']);
|
||||
$provinsi = mysqli_real_escape_string($koneksi, $_POST['provinsi']);
|
||||
$kewarganegaraan = mysqli_real_escape_string($koneksi, $_POST['kewarganegaraan']);
|
||||
$phone = mysqli_real_escape_string($koneksi, $_POST['phone']);
|
||||
|
||||
if($has_new_photo){
|
||||
$foto= $data_cek['foto_ktp'];
|
||||
@@ -411,9 +403,8 @@
|
||||
kecamatan='$kecamatan',
|
||||
kabupaten='$kabupaten',
|
||||
provinsi='$provinsi',
|
||||
kewarganegaraan='$kewarganegaraan',
|
||||
phone='$phone',
|
||||
foto_ktp='$nama_file'
|
||||
kewarganegaraan='$kewarganegaraan',
|
||||
foto_ktp='$nama_file'
|
||||
WHERE id_pend='$id_pend'";
|
||||
$query_ubah = mysqli_query($koneksi, $sql_ubah);
|
||||
|
||||
@@ -433,8 +424,7 @@
|
||||
kecamatan='$kecamatan',
|
||||
kabupaten='$kabupaten',
|
||||
provinsi='$provinsi',
|
||||
kewarganegaraan='$kewarganegaraan',
|
||||
phone='$phone'
|
||||
kewarganegaraan='$kewarganegaraan'
|
||||
WHERE id_pend='$id_pend'";
|
||||
$query_ubah = mysqli_query($koneksi, $sql_ubah);
|
||||
}
|
||||
|
||||
@@ -1,62 +0,0 @@
|
||||
<?php
|
||||
session_start();
|
||||
include "../inc/koneksi.php";
|
||||
|
||||
header('Content-Type: application/json');
|
||||
|
||||
if (!isset($_SESSION["ses_username"])) {
|
||||
echo json_encode(['success' => false, 'message' => 'Unauthorized']);
|
||||
exit;
|
||||
}
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
|
||||
echo json_encode(['success' => false, 'message' => 'Invalid request method']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$id_pend = isset($_POST['id_pend']) ? intval($_POST['id_pend']) : 0;
|
||||
$id_kk = isset($_POST['id_kk']) ? intval($_POST['id_kk']) : 0;
|
||||
$hubungan = isset($_POST['hubungan']) ? mysqli_real_escape_string($koneksi, $_POST['hubungan']) : 'ANGGOTA';
|
||||
|
||||
if ($id_pend <= 0 || $id_kk <= 0) {
|
||||
echo json_encode(['success' => false, 'message' => 'Invalid ID']);
|
||||
exit;
|
||||
}
|
||||
|
||||
// Cek apakah sudah terhubung
|
||||
$sql_cek = "SELECT * FROM tb_anggota WHERE id_kk='$id_kk' AND id_pend='$id_pend'";
|
||||
$q_cek = mysqli_query($koneksi, $sql_cek);
|
||||
|
||||
if (mysqli_num_rows($q_cek) > 0) {
|
||||
echo json_encode(['success' => false, 'message' => 'Sudah terhubung']);
|
||||
exit;
|
||||
}
|
||||
|
||||
// Cek apakah penduduk ada
|
||||
$sql_cek_pend = "SELECT * FROM tb_pdd WHERE id_pend='$id_pend'";
|
||||
$q_cek_pend = mysqli_query($koneksi, $sql_cek_pend);
|
||||
if (mysqli_num_rows($q_cek_pend) == 0) {
|
||||
echo json_encode(['success' => false, 'message' => 'Data penduduk tidak ditemukan']);
|
||||
exit;
|
||||
}
|
||||
|
||||
// Cek apakah KK ada
|
||||
$sql_cek_kk = "SELECT * FROM tb_kk WHERE id_kk='$id_kk'";
|
||||
$q_cek_kk = mysqli_query($koneksi, $sql_cek_kk);
|
||||
if (mysqli_num_rows($q_cek_kk) == 0) {
|
||||
echo json_encode(['success' => false, 'message' => 'Data KK tidak ditemukan']);
|
||||
exit;
|
||||
}
|
||||
|
||||
// Hubungkan
|
||||
$sql_link = "INSERT INTO tb_anggota (id_kk, id_pend, hubungan) VALUES ('$id_kk', '$id_pend', '$hubungan')";
|
||||
$q_link = mysqli_query($koneksi, $sql_link);
|
||||
|
||||
if ($q_link) {
|
||||
echo json_encode(['success' => true, 'message' => 'Berhasil dihubungkan']);
|
||||
} else {
|
||||
echo json_encode(['success' => false, 'message' => 'Database error: ' . mysqli_error($koneksi)]);
|
||||
}
|
||||
|
||||
mysqli_close($koneksi);
|
||||
?>
|
||||
14
admin/pend/view_pend.php
Executable file → Normal file
14
admin/pend/view_pend.php
Executable file → Normal file
@@ -134,17 +134,9 @@
|
||||
<td>:
|
||||
<?php echo $data_cek['kewarganegaraan']; ?>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="width: 150px">
|
||||
<b>No. Telepon</b>
|
||||
</td>
|
||||
<td>:
|
||||
<?php echo isset($data_cek['phone']) ? $data_cek['phone'] : ''; ?>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
|
||||
</tr>
|
||||
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="card-footer">
|
||||
|
||||
80
admin/pengguna/add_pengguna.php
Executable file → Normal file
80
admin/pengguna/add_pengguna.php
Executable file → Normal file
@@ -30,11 +30,11 @@
|
||||
<div class="form-group row">
|
||||
<label class="col-sm-2 col-form-label">Level</label>
|
||||
<div class="col-sm-4">
|
||||
<select name="level" id="level" class="form-control">
|
||||
<option value="">- Pilih -</option>
|
||||
<option value="Administrator">Administrator</option>
|
||||
<option value="Kaur Pemerintah">Kaur Pemerintah</option>
|
||||
</select>
|
||||
<select name="level" id="level" class="form-control">
|
||||
<option>- Pilih -</option>
|
||||
<option>Administrator</option>
|
||||
<option>Kaur Pemerintah</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -46,45 +46,31 @@
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<?php
|
||||
|
||||
if (isset ($_POST['Simpan'])){
|
||||
// Map level untuk database (enum: 'admin', 'kaur')
|
||||
$level_map = [
|
||||
'Administrator' => 'admin',
|
||||
'Kaur Pemerintah' => 'kaur'
|
||||
];
|
||||
$level_db = isset($level_map[$_POST['level']]) ? $level_map[$_POST['level']] : $_POST['level'];
|
||||
|
||||
// Sanitize Input to prevent SQL Injection & Syntax Errors
|
||||
$nama_pengguna = mysqli_real_escape_string($koneksi, trim($_POST['nama_pengguna']));
|
||||
$username = mysqli_real_escape_string($koneksi, trim($_POST['username']));
|
||||
$password_raw = trim($_POST['password']);
|
||||
$password_hash = MD5($password_raw);
|
||||
$level_db = mysqli_real_escape_string($koneksi, $level_db);
|
||||
|
||||
//mulai proses simpan data
|
||||
$sql_simpan = "INSERT INTO tb_pengguna (nama_pengguna,username,password,level) VALUES (
|
||||
'$nama_pengguna',
|
||||
'$username',
|
||||
'$password_hash',
|
||||
'$level_db')";
|
||||
$query_simpan = mysqli_query($koneksi, $sql_simpan);
|
||||
mysqli_close($koneksi);
|
||||
|
||||
if ($query_simpan) {
|
||||
echo "<script>
|
||||
Swal.fire({title: 'Tambah Data Berhasil',text: '',icon: 'success',confirmButtonText: 'OK'
|
||||
}).then((result) => {if (result.value){
|
||||
window.location = 'index.php?page=data-pengguna';
|
||||
}
|
||||
})</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-pengguna';
|
||||
}
|
||||
})</script>";
|
||||
}}
|
||||
//selesai proses simpan data
|
||||
<?php
|
||||
|
||||
if (isset ($_POST['Simpan'])){
|
||||
//mulai proses simpan data
|
||||
$sql_simpan = "INSERT INTO tb_pengguna (nama_pengguna,username,password,level) VALUES (
|
||||
'".$_POST['nama_pengguna']."',
|
||||
'".$_POST['username']."',
|
||||
'".$_POST['password']."',
|
||||
'".$_POST['level']."')";
|
||||
$query_simpan = mysqli_query($koneksi, $sql_simpan);
|
||||
mysqli_close($koneksi);
|
||||
|
||||
if ($query_simpan) {
|
||||
echo "<script>
|
||||
Swal.fire({title: 'Tambah Data Berhasil',text: '',icon: 'success',confirmButtonText: 'OK'
|
||||
}).then((result) => {if (result.value){
|
||||
window.location = 'index.php?page=data-pengguna';
|
||||
}
|
||||
})</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-pengguna';
|
||||
}
|
||||
})</script>";
|
||||
}}
|
||||
//selesai proses simpan data
|
||||
|
||||
48
admin/pengguna/data_pengguna.php
Executable file → Normal file
48
admin/pengguna/data_pengguna.php
Executable file → Normal file
@@ -23,16 +23,11 @@
|
||||
</thead>
|
||||
<tbody>
|
||||
|
||||
<?php
|
||||
$no = 1;
|
||||
$level_map = [
|
||||
'admin' => 'Administrator',
|
||||
'kaur' => 'Kaur Pemerintah'
|
||||
];
|
||||
$sql = $koneksi->query("select * from tb_pengguna");
|
||||
while ($data= $sql->fetch_assoc()) {
|
||||
$level_display = isset($level_map[$data['level']]) ? $level_map[$data['level']] : $data['level'];
|
||||
?>
|
||||
<?php
|
||||
$no = 1;
|
||||
$sql = $koneksi->query("select * from tb_pengguna");
|
||||
while ($data= $sql->fetch_assoc()) {
|
||||
?>
|
||||
|
||||
<tr>
|
||||
<td>
|
||||
@@ -45,17 +40,17 @@
|
||||
<?php echo $data['username']; ?>
|
||||
</td>
|
||||
<td>
|
||||
<?php echo $level_display; ?>
|
||||
<?php echo $data['level']; ?>
|
||||
</td>
|
||||
<td>
|
||||
<a href="?page=edit-pengguna&kode=<?php echo $data['id_pengguna']; ?>" title="Ubah"
|
||||
class="btn btn-success btn-sm">
|
||||
<i class="fa fa-edit"></i>
|
||||
</a>
|
||||
<a href="?page=del-pengguna&kode=<?php echo $data['id_pengguna']; ?>" onclick="confirmDelete(event)"
|
||||
<a href="?page=del-pengguna&kode=<?php echo $data['id_pengguna']; ?>" onclick="return confirm('Apakah anda yakin hapus data ini ?')"
|
||||
title="Hapus" class="btn btn-danger btn-sm">
|
||||
<i class="fa fa-trash"></i>
|
||||
</a>
|
||||
</>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
@@ -64,26 +59,7 @@
|
||||
?>
|
||||
</tbody>
|
||||
</tfoot>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<!-- /.card-body -->
|
||||
<script>
|
||||
function confirmDelete(event) {
|
||||
event.preventDefault();
|
||||
Swal.fire({
|
||||
title: 'Konfirmasi Hapus',
|
||||
text: 'Apakah Anda yakin ingin menghapus data ini?',
|
||||
icon: 'warning',
|
||||
showCancelButton: true,
|
||||
confirmButtonColor: '#d33',
|
||||
cancelButtonColor: '#3085d6',
|
||||
confirmButtonText: 'Ya, Hapus',
|
||||
cancelButtonText: 'Batal'
|
||||
}).then((result) => {
|
||||
if (result.isConfirmed) {
|
||||
window.location.href = event.currentTarget.href;
|
||||
}
|
||||
});
|
||||
}
|
||||
</script>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<!-- /.card-body -->
|
||||
0
admin/pengguna/del_pengguna.php
Executable file → Normal file
0
admin/pengguna/del_pengguna.php
Executable file → Normal file
57
admin/pengguna/edit_pengguna.php
Executable file → Normal file
57
admin/pengguna/edit_pengguna.php
Executable file → Normal file
@@ -46,29 +46,17 @@
|
||||
<div class="form-group row">
|
||||
<label class="col-sm-2 col-form-label">Level</label>
|
||||
<div class="col-sm-4">
|
||||
<select name="level" id="level" class="form-control">
|
||||
<option value="">-- Pilih Level --</option>
|
||||
<?php
|
||||
// Mapping level dari database ke tampilan
|
||||
$level_display_map = [
|
||||
'admin' => 'Administrator',
|
||||
'kaur' => 'Kaur Pemerintah',
|
||||
'Administrator' => 'Administrator', // backward compatibility
|
||||
'Kaur Pemerintah' => 'Kaur Pemerintah'
|
||||
];
|
||||
$current_level = $data_cek['level'];
|
||||
$current_display = isset($level_display_map[$current_level]) ? $level_display_map[$current_level] : $current_level;
|
||||
|
||||
// Opsi Administrator
|
||||
if ($current_display == "Administrator") {
|
||||
echo "<option value='Administrator' selected>Administrator</option>";
|
||||
echo "<option value='Kaur Pemerintah'>Kaur Pemerintah</option>";
|
||||
} else {
|
||||
echo "<option value='Administrator'>Administrator</option>";
|
||||
echo "<option value='Kaur Pemerintah' selected>Kaur Pemerintah</option>";
|
||||
}
|
||||
?>
|
||||
</select>
|
||||
<select name="level" id="level" class="form-control">
|
||||
<option value="">-- Pilih Level --</option>
|
||||
<?php
|
||||
//menhecek data yg dipilih sebelumnya
|
||||
if ($data_cek['level'] == "Administrator") echo "<option value='Administrator' selected>Administrator</option>";
|
||||
else echo "<option value='Administrator'>Administrator</option>";
|
||||
|
||||
if ($data_cek['level'] == "Kaur Pemerintah") echo "<option value='Kaur Pemerintah' selected>Kaur Pemerintah</option>";
|
||||
else echo "<option value='Kaur Pemerintah'>Kaur Pemerintah</option>";
|
||||
?>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -84,21 +72,14 @@
|
||||
|
||||
<?php
|
||||
|
||||
if (isset ($_POST['Ubah'])){
|
||||
// Map level untuk database (enum: 'admin', 'kaur')
|
||||
$level_map = [
|
||||
'Administrator' => 'admin',
|
||||
'Kaur Pemerintah' => 'kaur'
|
||||
];
|
||||
$level_db = isset($level_map[$_POST['level']]) ? $level_map[$_POST['level']] : $_POST['level'];
|
||||
|
||||
$sql_ubah = "UPDATE tb_pengguna SET
|
||||
nama_pengguna='".$_POST['nama_pengguna']."',
|
||||
username='".$_POST['username']."',
|
||||
password='".$_POST['password']."',
|
||||
level='".$level_db."'
|
||||
WHERE id_pengguna='".$_POST['id_pengguna']."'";
|
||||
$query_ubah = mysqli_query($koneksi, $sql_ubah);
|
||||
if (isset ($_POST['Ubah'])){
|
||||
$sql_ubah = "UPDATE tb_pengguna SET
|
||||
nama_pengguna='".$_POST['nama_pengguna']."',
|
||||
username='".$_POST['username']."',
|
||||
password='".$_POST['password']."',
|
||||
level='".$_POST['level']."'
|
||||
WHERE id_pengguna='".$_POST['id_pengguna']."'";
|
||||
$query_ubah = mysqli_query($koneksi, $sql_ubah);
|
||||
mysqli_close($koneksi);
|
||||
|
||||
if ($query_ubah) {
|
||||
|
||||
70
admin/pindah/add_pindah.php
Executable file → Normal file
70
admin/pindah/add_pindah.php
Executable file → Normal file
@@ -52,41 +52,35 @@
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<?php
|
||||
|
||||
if (isset ($_POST['Simpan'])){
|
||||
//mulai proses simpan data
|
||||
|
||||
// Sanitize Input to prevent SQL Injection & Syntax Errors
|
||||
$id_pdd = (int)$_POST['id_pdd']; // Cast to integer for safety
|
||||
$tgl_pindah = mysqli_real_escape_string($koneksi, trim($_POST['tgl_pindah']));
|
||||
$alasan = mysqli_real_escape_string($koneksi, trim($_POST['alasan']));
|
||||
|
||||
$sql_simpan = "INSERT INTO tb_pindah (id_pdd, tgl_pindah, alasan) VALUES (
|
||||
'$id_pdd',
|
||||
'$tgl_pindah',
|
||||
'$alasan')";
|
||||
$query_simpan = mysqli_query($koneksi, $sql_simpan);
|
||||
|
||||
$sql_ubah = "UPDATE tb_pdd SET
|
||||
status='Pindah'
|
||||
WHERE id_pend='$id_pdd'";
|
||||
$query_ubah = mysqli_query($koneksi, $sql_ubah);
|
||||
mysqli_close($koneksi);
|
||||
|
||||
if ($query_simpan && $query_ubah) {
|
||||
echo "<script>
|
||||
Swal.fire({title: 'Tambah Data Berhasil',text: '',icon: 'success',confirmButtonText: 'OK'
|
||||
}).then((result) => {if (result.value){
|
||||
window.location = 'index.php?page=data-pindah';
|
||||
}
|
||||
})</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-pindah';
|
||||
}
|
||||
})</script>";
|
||||
}}
|
||||
//selesai proses simpan data
|
||||
<?php
|
||||
|
||||
if (isset ($_POST['Simpan'])){
|
||||
//mulai proses simpan data
|
||||
$sql_simpan = "INSERT INTO tb_pindah (id_pdd, tgl_pindah, alasan) VALUES (
|
||||
'".$_POST['id_pdd']."',
|
||||
'".$_POST['tgl_pindah']."',
|
||||
'".$_POST['alasan']."')";
|
||||
$query_simpan = mysqli_query($koneksi, $sql_simpan);
|
||||
|
||||
$sql_ubah = "UPDATE tb_pdd SET
|
||||
status='Pindah'
|
||||
WHERE id_pend='".$_POST['id_pdd']."'";
|
||||
$query_ubah = mysqli_query($koneksi, $sql_ubah);
|
||||
mysqli_close($koneksi);
|
||||
|
||||
if ($query_simpan && $query_ubah) {
|
||||
echo "<script>
|
||||
Swal.fire({title: 'Tambah Data Berhasil',text: '',icon: 'success',confirmButtonText: 'OK'
|
||||
}).then((result) => {if (result.value){
|
||||
window.location = 'index.php?page=data-pindah';
|
||||
}
|
||||
})</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-pindah';
|
||||
}
|
||||
})</script>";
|
||||
}}
|
||||
//selesai proses simpan data
|
||||
|
||||
59
admin/pindah/data_pindah.php
Executable file → Normal file
59
admin/pindah/data_pindah.php
Executable file → Normal file
@@ -13,21 +13,20 @@
|
||||
<br>
|
||||
<table id="example1" class="table table-bordered table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>No</th>
|
||||
<th>NIK</th>
|
||||
<th>Nama</th>
|
||||
<th>Jenis Kelamin</th>
|
||||
<th>Tanggal</th>
|
||||
<th>Alasan</th>
|
||||
<th>Aksi</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>No</th>
|
||||
<th>NIK</th>
|
||||
<th>Nama</th>
|
||||
<th>Tanggal</th>
|
||||
<th>Alasan</th>
|
||||
<th>Aksi</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
||||
<?php
|
||||
$no = 1;
|
||||
$sql = $koneksi->query("SELECT p.id_pend, p.nik, p.nama, p.jekel, d.tgl_pindah, d.alasan, d.id_pindah from
|
||||
$sql = $koneksi->query("SELECT p.id_pend, p.nik, p.nama, d.tgl_pindah, d.alasan, d.id_pindah from
|
||||
tb_pindah d inner join tb_pdd p on p.id_pend=d.id_pdd");
|
||||
while ($data= $sql->fetch_assoc()) {
|
||||
?>
|
||||
@@ -42,12 +41,9 @@
|
||||
<td>
|
||||
<?php echo $data['nama']; ?>
|
||||
</td>
|
||||
<td>
|
||||
<?php echo $data['jekel'] == 'LK' ? 'LAKI-LAKI' : 'PEREMPUAN'; ?>
|
||||
</td>
|
||||
<td>
|
||||
<?php echo $data['tgl_pindah']; ?>
|
||||
</td>
|
||||
<td>
|
||||
<?php echo $data['tgl_pindah']; ?>
|
||||
</td>
|
||||
<td>
|
||||
<?php echo $data['alasan']; ?>
|
||||
</td>
|
||||
@@ -60,10 +56,10 @@
|
||||
class="btn btn-success btn-sm">
|
||||
<i class="fa fa-edit"></i>
|
||||
</a>
|
||||
<a href="?page=del-pindah&kode=<?php echo $data['id_pend']; ?>" onclick="confirmDelete(event)"
|
||||
<a href="?page=del-pindah&kode=<?php echo $data['id_pend']; ?>" onclick="return confirm('Apakah anda yakin hapus data ini ?')"
|
||||
title="Hapus" class="btn btn-danger btn-sm">
|
||||
<i class="fa fa-trash"></i>
|
||||
</a>
|
||||
</>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
@@ -72,26 +68,7 @@
|
||||
?>
|
||||
</tbody>
|
||||
</tfoot>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<!-- /.card-body -->
|
||||
<script>
|
||||
function confirmDelete(event) {
|
||||
event.preventDefault();
|
||||
Swal.fire({
|
||||
title: 'Konfirmasi Hapus',
|
||||
text: 'Apakah Anda yakin ingin menghapus data ini?',
|
||||
icon: 'warning',
|
||||
showCancelButton: true,
|
||||
confirmButtonColor: '#d33',
|
||||
cancelButtonColor: '#3085d6',
|
||||
confirmButtonText: 'Ya, Hapus',
|
||||
cancelButtonText: 'Batal'
|
||||
}).then((result) => {
|
||||
if (result.isConfirmed) {
|
||||
window.location.href = event.currentTarget.href;
|
||||
}
|
||||
});
|
||||
}
|
||||
</script>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<!-- /.card-body -->
|
||||
0
admin/pindah/del_pindah.php
Executable file → Normal file
0
admin/pindah/del_pindah.php
Executable file → Normal file
0
admin/pindah/edit_pindah.php
Executable file → Normal file
0
admin/pindah/edit_pindah.php
Executable file → Normal file
10
admin/pindah/view_pindah.php
Executable file → Normal file
10
admin/pindah/view_pindah.php
Executable file → Normal file
@@ -90,15 +90,7 @@
|
||||
<b>Jenis Kelamin</b>
|
||||
</td>
|
||||
<td>:
|
||||
<?php
|
||||
if ($data_cek['jekel'] == 'LK') {
|
||||
echo 'LAKI-LAKI';
|
||||
} elseif ($data_cek['jekel'] == 'PR') {
|
||||
echo 'PEREMPUAN';
|
||||
} else {
|
||||
echo $data_cek['jekel'];
|
||||
}
|
||||
?>
|
||||
<?php echo $data_cek['jekel']; ?>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
|
||||
0
admin/profil/data_profil.php
Executable file → Normal file
0
admin/profil/data_profil.php
Executable file → Normal file
888
admin/scanner_modal.php
Executable file → Normal file
888
admin/scanner_modal.php
Executable file → Normal file
@@ -3,33 +3,29 @@
|
||||
<div class="modal fade" id="modalScanner" tabindex="-1" role="dialog" aria-labelledby="modalScannerLabel" aria-hidden="true" data-backdrop="static">
|
||||
<div class="modal-dialog modal-xl" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="modalScannerLabel"><i class="fas fa-expand"></i> Smart Scanner</h5>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body text-center bg-dark p-0" style="position: relative; overflow: hidden; height: 80vh;">
|
||||
<div id="scanner-container" style="position: relative; margin: auto; display: inline-block;">
|
||||
<canvas id="canvas-image" style="position: absolute; left: 0; top: 0; z-index: 1;"></canvas>
|
||||
<canvas id="canvas-overlay" style="position: absolute; left: 0; top: 0; z-index: 2; cursor: crosshair;"></canvas>
|
||||
</div>
|
||||
|
||||
<div id="scanner-loading" style="position: absolute; top: 50%; left: 50%; transform: translate(-50%,-50%); color: white; display: none;">
|
||||
<i class="fas fa-spinner fa-spin fa-3x"></i><br>Detecting Document...
|
||||
</div>
|
||||
|
||||
<!-- Mobile Help Tips -->
|
||||
<div id="mobile-help" class="d-none d-md-none d-lg-none" style="position: absolute; bottom: 10px; left: 0; right: 0; text-align: center; color: white; background: rgba(0,0,0,0.7); padding: 5px; font-size: 12px;">
|
||||
<span>📍 Sentuh & geser titik biru untuk atur sudut dokumen</span>
|
||||
</div>
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="modalScannerLabel"><i class="fas fa-expand"></i> Smart Scanner</h5>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body text-center bg-dark p-0" style="position: relative; overflow: hidden; height: 80vh;">
|
||||
<!-- Container for Canvases -->
|
||||
<!-- Container for Canvases -->
|
||||
<div id="scanner-container" style="position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); box-shadow: 0 0 10px rgba(0,0,0,0.5);">
|
||||
<canvas id="canvas-image" style="position: absolute; left: 0; top: 0; z-index: 10;"></canvas>
|
||||
<canvas id="canvas-overlay" style="position: absolute; left: 0; top: 0; z-index: 20; cursor: crosshair;"></canvas>
|
||||
</div>
|
||||
<div id="scanner-loading" style="position: absolute; top: 50%; left: 50%; transform: translate(-50%,-50%); color: white; display: none; z-index: 50; text-align: center;">
|
||||
<i class="fas fa-spinner fa-spin fa-3x"></i><br><span style="margin-top: 10px; display: block;">Sedang menganalisa...</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer justify-content-between">
|
||||
<div>
|
||||
<button type="button" class="btn btn-secondary" id="btnScanRotateLeft" title="Putar Kiri (-90°)"><i class="fas fa-undo"></i></button>
|
||||
<button type="button" class="btn btn-secondary" id="btnScanRotateRight" title="Putar Kanan (+90°)"><i class="fas fa-redo"></i></button>
|
||||
<button type="button" class="btn btn-warning" id="btnScanReset"><i class="fas fa-sync"></i> Reset Sudut</button>
|
||||
</div>
|
||||
<div>
|
||||
<button type="button" class="btn btn-secondary" id="btnScanRotateLeft" title="Putar Kiri (-90°)"><i class="fas fa-undo"></i></button>
|
||||
<button type="button" class="btn btn-secondary" id="btnScanRotateRight" title="Putar Kanan (+90°)"><i class="fas fa-redo"></i></button>
|
||||
<button type="button" class="btn btn-warning" id="btnScanReset"><i class="fas fa-sync"></i> Reset Sudut</button>
|
||||
</div>
|
||||
<div>
|
||||
<button type="button" class="btn btn-secondary" data-dismiss="modal">Batal</button>
|
||||
<button type="button" class="btn btn-primary" id="btnScanSave"><i class="fas fa-check"></i> Simpan Hasil Scan</button>
|
||||
@@ -39,341 +35,31 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
/* Disable all transitions and hover effects for scanner modal */
|
||||
#modalScanner .card,
|
||||
#modalScanner .modal-content,
|
||||
#modalScanner .modal-body,
|
||||
#modalScanner .modal-header,
|
||||
#modalScanner .modal-footer,
|
||||
#modalScanner .modal-dialog,
|
||||
#modalScanner #scanner-container,
|
||||
#modalScanner #scanner-container * {
|
||||
transition: none !important;
|
||||
}
|
||||
#modalScanner .card:hover,
|
||||
#modalScanner .modal-content:hover,
|
||||
#modalScanner .modal-body:hover,
|
||||
#modalScanner .modal-header:hover,
|
||||
#modalScanner .modal-footer:hover,
|
||||
#modalScanner .modal-dialog:hover,
|
||||
#modalScanner #scanner-container:hover,
|
||||
#modalScanner #scanner-container *:hover {
|
||||
transform: none !important;
|
||||
}
|
||||
/* Ensure canvas is fully visible */
|
||||
#canvas-image {
|
||||
opacity: 1 !important;
|
||||
filter: none !important;
|
||||
background-color: white !important;
|
||||
}
|
||||
#canvas-overlay {
|
||||
opacity: 1 !important;
|
||||
filter: none !important;
|
||||
}
|
||||
/* Prevent canvas from moving on hover */
|
||||
#canvas-image:hover,
|
||||
#canvas-overlay:hover {
|
||||
transform: none !important;
|
||||
}
|
||||
|
||||
/* Prevent modal dragging and improve touch handling on mobile */
|
||||
#modalScanner .modal-dialog,
|
||||
#modalScanner .modal-content,
|
||||
#modalScanner .modal-header,
|
||||
#modalScanner .modal-footer {
|
||||
touch-action: none !important; /* Prevent browser touch gestures (pan, zoom, swipe) */
|
||||
user-select: none !important; /* Prevent text selection during drag */
|
||||
-webkit-user-select: none !important;
|
||||
-webkit-touch-callout: none !important;
|
||||
}
|
||||
|
||||
/* Allow touch interaction only on canvas and buttons */
|
||||
#modalScanner .modal-body,
|
||||
#canvas-image,
|
||||
#canvas-overlay {
|
||||
touch-action: manipulation !important; /* Allow pinch-zoom and pan on canvas only */
|
||||
}
|
||||
|
||||
/* Prevent modal backdrop from responding to touch */
|
||||
.modal-backdrop {
|
||||
touch-action: none !important;
|
||||
}
|
||||
|
||||
/* Lock modal position on mobile */
|
||||
@media (max-width: 768px) {
|
||||
#modalScanner {
|
||||
padding-right: 0 !important; /* Prevent shift from scrollbar */
|
||||
}
|
||||
#modalScanner .modal-dialog {
|
||||
margin: 0 !important;
|
||||
max-height: 100vh !important;
|
||||
height: 100vh !important;
|
||||
width: 100vw !important;
|
||||
max-width: 100vw !important;
|
||||
position: fixed !important;
|
||||
top: 0 !important;
|
||||
left: 0 !important;
|
||||
right: 0 !important;
|
||||
bottom: 0 !important;
|
||||
transform: none !important;
|
||||
transition: none !important;
|
||||
}
|
||||
#modalScanner .modal-content {
|
||||
border-radius: 0 !important;
|
||||
height: 100vh !important;
|
||||
max-height: 100vh !important;
|
||||
width: 100vw !important;
|
||||
max-width: 100vw !important;
|
||||
overflow: hidden !important;
|
||||
position: fixed !important;
|
||||
top: 0 !important;
|
||||
left: 0 !important;
|
||||
transform: none !important;
|
||||
transition: none !important;
|
||||
}
|
||||
#modalScanner .modal-body {
|
||||
height: calc(100vh - 120px) !important; /* Account for header and footer */
|
||||
overflow: hidden !important;
|
||||
}
|
||||
/* Prevent any modal movement */
|
||||
.modal-open #modalScanner {
|
||||
overflow: hidden !important;
|
||||
}
|
||||
/* Larger touch target for close button on mobile */
|
||||
#modalScanner .modal-header .close {
|
||||
padding: 20px !important;
|
||||
font-size: 2rem !important;
|
||||
line-height: 1 !important;
|
||||
margin: -10px -10px -10px auto !important;
|
||||
}
|
||||
|
||||
/* Larger touch targets for all buttons */
|
||||
#modalScanner .modal-footer .btn {
|
||||
min-height: 44px !important;
|
||||
min-width: 44px !important;
|
||||
padding: 10px 15px !important;
|
||||
font-size: 16px !important; /* Prevent zoom on iOS */
|
||||
}
|
||||
|
||||
/* Larger corner points for touch */
|
||||
#canvas-overlay {
|
||||
touch-action: manipulation;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Help text */
|
||||
#mobile-help {
|
||||
font-size: 14px !important;
|
||||
padding: 10px !important;
|
||||
}
|
||||
}
|
||||
|
||||
/* Larger hit area for corner points for touch devices */
|
||||
#canvas-overlay {
|
||||
touch-action: pinch-zoom;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
window.addEventListener('load', function() {
|
||||
// Function to load scanner libraries dynamically
|
||||
function loadScannerLibs() {
|
||||
return new Promise(function(resolve, reject) {
|
||||
// Check if both libraries are already loaded AND OpenCV runtime is ready
|
||||
if (typeof cv !== 'undefined' && cv.Mat && typeof jscanify !== 'undefined') {
|
||||
resolve();
|
||||
return;
|
||||
}
|
||||
|
||||
// Load OpenCV first (jscanify depends on it)
|
||||
function loadOpenCV() {
|
||||
return new Promise(function(resolveOpenCV, rejectOpenCV) {
|
||||
if (typeof cv !== 'undefined') {
|
||||
// OpenCV already loaded, check if runtime ready
|
||||
if (cv.Mat) {
|
||||
resolveOpenCV();
|
||||
} else if (cv.onRuntimeInitialized) {
|
||||
// Wait for runtime initialization
|
||||
var existingCallback = cv.onRuntimeInitialized;
|
||||
cv.onRuntimeInitialized = function() {
|
||||
if (typeof existingCallback === 'function') {
|
||||
existingCallback();
|
||||
}
|
||||
resolveOpenCV();
|
||||
};
|
||||
} else {
|
||||
// OpenCV loaded but no runtime callback mechanism
|
||||
// Poll for cv.Mat
|
||||
var checkInterval = setInterval(function() {
|
||||
if (cv.Mat) {
|
||||
clearInterval(checkInterval);
|
||||
resolveOpenCV();
|
||||
}
|
||||
}, 100);
|
||||
// Timeout after 10 seconds
|
||||
setTimeout(function() {
|
||||
clearInterval(checkInterval);
|
||||
rejectOpenCV(new Error('OpenCV runtime initialization timeout'));
|
||||
}, 10000);
|
||||
}
|
||||
} else {
|
||||
// Load OpenCV script
|
||||
var opencvScript = document.createElement('script');
|
||||
opencvScript.src = '../../plugins/vendor/opencv/opencv.js';
|
||||
opencvScript.onload = function() {
|
||||
console.log('OpenCV.js loaded dynamically');
|
||||
// Wait for runtime initialization
|
||||
if (cv.onRuntimeInitialized) {
|
||||
var existingCallback = cv.onRuntimeInitialized;
|
||||
cv.onRuntimeInitialized = function() {
|
||||
if (typeof existingCallback === 'function') {
|
||||
existingCallback();
|
||||
}
|
||||
resolveOpenCV();
|
||||
};
|
||||
} else {
|
||||
// Fallback: wait a bit then resolve
|
||||
setTimeout(resolveOpenCV, 5000);
|
||||
}
|
||||
};
|
||||
opencvScript.onerror = function() {
|
||||
console.error('Failed to load OpenCV.js');
|
||||
rejectOpenCV(new Error('Failed to load OpenCV.js'));
|
||||
};
|
||||
document.head.appendChild(opencvScript);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Load jscanify after OpenCV is ready
|
||||
function loadJscanify() {
|
||||
return new Promise(function(resolveJscanify, rejectJscanify) {
|
||||
if (typeof jscanify !== 'undefined') {
|
||||
resolveJscanify();
|
||||
return;
|
||||
}
|
||||
|
||||
var jscanifyScript = document.createElement('script');
|
||||
jscanifyScript.src = '../../plugins/vendor/jscanify/jscanify.min.js';
|
||||
jscanifyScript.onload = function() {
|
||||
console.log('jscanify loaded dynamically');
|
||||
resolveJscanify();
|
||||
};
|
||||
jscanifyScript.onerror = function() {
|
||||
console.error('Failed to load jscanify');
|
||||
rejectJscanify(new Error('Failed to load jscanify'));
|
||||
};
|
||||
document.head.appendChild(jscanifyScript);
|
||||
});
|
||||
}
|
||||
|
||||
// Load all libraries in sequence
|
||||
loadOpenCV()
|
||||
.then(function() {
|
||||
console.log('OpenCV ready, loading jscanify...');
|
||||
return loadJscanify();
|
||||
})
|
||||
.then(function() {
|
||||
console.log('All scanner libraries loaded');
|
||||
resolve();
|
||||
})
|
||||
.catch(function(error) {
|
||||
console.error('Failed to load scanner libraries:', error);
|
||||
reject(error);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Load libraries and then initialize scanner
|
||||
loadScannerLibs().then(function() {
|
||||
// Give OpenCV a moment to initialize runtime
|
||||
setTimeout(function() {
|
||||
// Scanner Variables
|
||||
var scannerModal = $('#modalScanner');
|
||||
var canvasImage = document.getElementById('canvas-image');
|
||||
var canvasOverlay = document.getElementById('canvas-overlay');
|
||||
var ctxImg = canvasImage.getContext('2d');
|
||||
var ctxOver = canvasOverlay.getContext('2d');
|
||||
const IS_TOUCH_DEVICE = 'ontouchstart' in window || navigator.maxTouchPoints > 0;
|
||||
|
||||
var scanner = null;
|
||||
|
||||
function initScanner() {
|
||||
// Check if OpenCV is loaded
|
||||
if (typeof cv === 'undefined') {
|
||||
console.warn('OpenCV not loaded yet');
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if OpenCV runtime is already initialized
|
||||
if (cv.Mat) {
|
||||
try {
|
||||
scanner = new jscanify();
|
||||
console.log('Scanner initialized successfully (runtime ready)');
|
||||
return true;
|
||||
} catch (e) {
|
||||
console.error('Failed to initialize jscanify:', e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Runtime not initialized yet, set up callback
|
||||
if (cv.onRuntimeInitialized) {
|
||||
// Save any existing callback
|
||||
var existingCallback = cv.onRuntimeInitialized;
|
||||
cv.onRuntimeInitialized = function() {
|
||||
// Call existing callback first if it's a function
|
||||
if (typeof existingCallback === 'function') {
|
||||
existingCallback();
|
||||
}
|
||||
// Now initialize scanner
|
||||
try {
|
||||
scanner = new jscanify();
|
||||
console.log('Scanner initialized after runtime ready (callback)');
|
||||
} catch (e) {
|
||||
console.error('Failed to initialize jscanify after runtime:', e);
|
||||
}
|
||||
};
|
||||
console.log('Waiting for OpenCV runtime initialization...');
|
||||
return false;
|
||||
}
|
||||
|
||||
// Should not reach here
|
||||
console.warn('OpenCV loaded but no runtime initialization mechanism');
|
||||
return false;
|
||||
}
|
||||
|
||||
// Try to initialize scanner immediately
|
||||
initScanner();
|
||||
var originalImg = new Image();
|
||||
|
||||
// Mode is always smart scan now
|
||||
var currentMode = 'smart';
|
||||
var scanner = new jscanify();
|
||||
var originalImg = new Image();
|
||||
|
||||
// Corner Points (tl, tr, bl, br)
|
||||
var corners = [];
|
||||
var activePoint = null;
|
||||
var isDragging = false;
|
||||
var touchStartPos = null;
|
||||
var isTouchInteraction = false;
|
||||
var touchOffset = null;
|
||||
// Corner Points (tl, tr, bl, br)
|
||||
var corners = [];
|
||||
var activePoint = null;
|
||||
var isDragging = false;
|
||||
|
||||
// Config - Extra large circles for easy mobile touch, thin lines
|
||||
const POINT_RADIUS = 50; // Extra large circle radius for easy mobile touch
|
||||
const POINT_COLOR = 'rgba(0, 123, 255, 0.15)'; // Transparent blue (15% opacity)
|
||||
const POINT_OUTLINE_COLOR = '#007bff'; // Blue outline
|
||||
const POINT_OUTLINE_WIDTH = 2; // Thin outline
|
||||
const LINE_COLOR = 'rgba(0, 255, 0, 0.8)'; // Semi-transparent green lines
|
||||
const LINE_WIDTH = 1.5; // Very thin lines
|
||||
const TOUCH_RADIUS_MULTIPLIER = 3.5; // Extra large hit area for touch devices
|
||||
const TOUCH_SLOP = 5; // pixels threshold before dragging starts
|
||||
// Config
|
||||
const POINT_RADIUS = 15;
|
||||
const POINT_COLOR = '#007bff';
|
||||
const LINE_COLOR = '#00ff00';
|
||||
const LINE_WIDTH = 3;
|
||||
|
||||
// Mode is always smart scan (no toggle needed)
|
||||
|
||||
// --- Public Function to Open Scanner ---
|
||||
window.openScanner = function(file) {
|
||||
// --- Public Function to Open Scanner ---
|
||||
window.openScanner = function(file) {
|
||||
if (!file) return;
|
||||
|
||||
// Reset State
|
||||
@@ -390,7 +76,10 @@ window.addEventListener('load', function() {
|
||||
|
||||
function checkReady() {
|
||||
if (imgLoaded && modalShown) {
|
||||
setupScannerCanvas();
|
||||
// Defer execution to allow UI (spinner) to render first
|
||||
setTimeout(function() {
|
||||
initScanner();
|
||||
}, 100);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -405,151 +94,77 @@ window.addEventListener('load', function() {
|
||||
};
|
||||
reader.readAsDataURL(file);
|
||||
|
||||
// 2. Show Modal & Listen
|
||||
scannerModal.off('shown.bs.modal'); // Remove old listeners
|
||||
scannerModal.on('shown.bs.modal', function() {
|
||||
modalShown = true;
|
||||
checkReady();
|
||||
|
||||
// Prevent body scrolling on mobile
|
||||
document.body.style.overflow = 'hidden';
|
||||
document.body.style.position = 'fixed';
|
||||
document.body.style.width = '100%';
|
||||
|
||||
// Prevent modal dragging on mobile
|
||||
var modalDialog = document.querySelector('#modalScanner .modal-dialog');
|
||||
var modalContent = document.querySelector('#modalScanner .modal-content');
|
||||
var modalHeader = document.querySelector('#modalScanner .modal-header');
|
||||
var modalFooter = document.querySelector('#modalScanner .modal-footer');
|
||||
|
||||
var preventTouch = function(e) {
|
||||
// Allow touch on canvas elements and buttons
|
||||
var target = e.target;
|
||||
var isCanvas = target.id === 'canvas-overlay' || target.id === 'canvas-image' ||
|
||||
target.closest('#scanner-container');
|
||||
var isButton = target.tagName === 'BUTTON' || target.closest('button');
|
||||
|
||||
if (!isCanvas && !isButton) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
}
|
||||
};
|
||||
|
||||
if (modalDialog) {
|
||||
modalDialog.addEventListener('touchstart', preventTouch, { passive: false });
|
||||
modalDialog.addEventListener('touchmove', preventTouch, { passive: false });
|
||||
}
|
||||
if (modalContent) {
|
||||
modalContent.addEventListener('touchstart', preventTouch, { passive: false });
|
||||
modalContent.addEventListener('touchmove', preventTouch, { passive: false });
|
||||
}
|
||||
if (modalHeader) {
|
||||
modalHeader.addEventListener('touchstart', preventTouch, { passive: false });
|
||||
modalHeader.addEventListener('touchmove', preventTouch, { passive: false });
|
||||
}
|
||||
if (modalFooter) {
|
||||
modalFooter.addEventListener('touchstart', preventTouch, { passive: false });
|
||||
modalFooter.addEventListener('touchmove', preventTouch, { passive: false });
|
||||
}
|
||||
});
|
||||
|
||||
// Restore scrolling when modal is hidden
|
||||
scannerModal.on('hidden.bs.modal', function() {
|
||||
document.body.style.overflow = '';
|
||||
document.body.style.position = '';
|
||||
document.body.style.width = '';
|
||||
|
||||
});
|
||||
// 2. Show Modal & Listen
|
||||
scannerModal.off('shown.bs.modal'); // Remove old listeners
|
||||
scannerModal.on('shown.bs.modal', function() {
|
||||
modalShown = true;
|
||||
checkReady();
|
||||
});
|
||||
|
||||
scannerModal.modal('show');
|
||||
};
|
||||
|
||||
function detectDocument(scale, w, h, showAlert = false) {
|
||||
// Detect Contour using jscanify
|
||||
try {
|
||||
// jscanify expects an image element, we can pass originalImg but we need to map coordinates
|
||||
// Wait, jscanify uses OpenCV which might not be ready.
|
||||
if (typeof cv !== 'undefined' && cv.Mat) {
|
||||
// We need to work on the original image for detection, then scale points
|
||||
var contour = scanner ? scanner.findPaper(originalImg) : null;
|
||||
// contour returns { topLeftCorner, topRightCorner, bottomLeftCorner, bottomRightCorner } each {x, y}
|
||||
|
||||
if (contour) {
|
||||
// Order: TL, TR, BR, BL (clockwise)
|
||||
corners = [
|
||||
{ x: contour.topLeftCorner.x * scale, y: contour.topLeftCorner.y * scale },
|
||||
{ x: contour.topRightCorner.x * scale, y: contour.topRightCorner.y * scale },
|
||||
{ x: contour.bottomRightCorner.x * scale, y: contour.bottomRightCorner.y * scale },
|
||||
{ x: contour.bottomLeftCorner.x * scale, y: contour.bottomLeftCorner.y * scale }
|
||||
];
|
||||
function initScanner() {
|
||||
// Resize Canvas to fit screen but keep aspect ratio
|
||||
var maxWidth = $('#modalScanner .modal-body').width() - 20;
|
||||
var maxHeight = $('#modalScanner .modal-body').height() - 20;
|
||||
|
||||
var scale = Math.min(maxWidth / originalImg.width, maxHeight / originalImg.height);
|
||||
var w = originalImg.width * scale;
|
||||
var h = originalImg.height * scale;
|
||||
|
||||
canvasImage.width = w;
|
||||
canvasImage.height = h;
|
||||
canvasOverlay.width = w;
|
||||
canvasOverlay.height = h;
|
||||
|
||||
// Resize container
|
||||
$('#scanner-container').css({ width: w, height: h });
|
||||
|
||||
// Draw Image
|
||||
ctxImg.drawImage(originalImg, 0, 0, w, h);
|
||||
|
||||
// Detect Contour using jscanify
|
||||
try {
|
||||
// jscanify expects an image element, we can pass originalImg but we need to map coordinates
|
||||
// Wait, jscanify uses OpenCV which might not be ready.
|
||||
if (typeof cv !== 'undefined' && cv.Mat) {
|
||||
// We need to work on the original image for detection, then scale points
|
||||
var contour = scanner.findPaper(originalImg);
|
||||
// contour returns { topLeftCorner, topRightCorner, bottomLeftCorner, bottomRightCorner } each {x, y}
|
||||
|
||||
if (contour) {
|
||||
corners = [
|
||||
{ x: contour.topLeftCorner.x * scale, y: contour.topLeftCorner.y * scale },
|
||||
{ x: contour.topRightCorner.x * scale, y: contour.topRightCorner.y * scale },
|
||||
{ x: contour.bottomRightCorner.x * scale, y: contour.bottomRightCorner.y * scale }, // Order: tr -> br -> bl ?? No, usually tl, tr, br, bl order for polygon drawing
|
||||
{ x: contour.bottomLeftCorner.x * scale, y: contour.bottomLeftCorner.y * scale }
|
||||
];
|
||||
// Reorder primarily for logic: TL, TR, BR, BL
|
||||
corners = [
|
||||
{ x: contour.topLeftCorner.x * scale, y: contour.topLeftCorner.y * scale },
|
||||
{ x: contour.topRightCorner.x * scale, y: contour.topRightCorner.y * scale },
|
||||
{ x: contour.bottomRightCorner.x * scale, y: contour.bottomRightCorner.y * scale },
|
||||
{ x: contour.bottomLeftCorner.x * scale, y: contour.bottomLeftCorner.y * scale }
|
||||
];
|
||||
|
||||
} else {
|
||||
defaultCorners(w, h);
|
||||
if (showAlert) {
|
||||
Swal.fire({
|
||||
icon: 'warning',
|
||||
title: 'Deteksi Gagal',
|
||||
text: 'Dokumen tidak terdeteksi. Silakan atur sudut secara manual.',
|
||||
confirmButtonText: 'OK'
|
||||
});
|
||||
}
|
||||
}
|
||||
} else {
|
||||
console.warn("OpenCV not ready yet");
|
||||
defaultCorners(w, h);
|
||||
if (showAlert) {
|
||||
Swal.fire({
|
||||
icon: 'warning',
|
||||
title: 'Scanner Tidak Siap',
|
||||
text: 'OpenCV belum siap. Silakan atur sudut secara manual.',
|
||||
confirmButtonText: 'OK'
|
||||
});
|
||||
}
|
||||
}
|
||||
} catch(e) {
|
||||
console.error("Scanner Error:", e);
|
||||
defaultCorners(w, h); // Fallback
|
||||
if (showAlert) {
|
||||
Swal.fire({
|
||||
icon: 'error',
|
||||
title: 'Error Scanner',
|
||||
text: 'Terjadi kesalahan saat mendeteksi dokumen: ' + e.message,
|
||||
confirmButtonText: 'OK'
|
||||
});
|
||||
}
|
||||
}
|
||||
drawOverlay();
|
||||
}
|
||||
} else {
|
||||
defaultCorners(w, h);
|
||||
}
|
||||
} else {
|
||||
console.warn("OpenCV not ready yet");
|
||||
defaultCorners(w, h);
|
||||
}
|
||||
} catch(e) {
|
||||
console.error("Scanner Error:", e);
|
||||
defaultCorners(w, h); // Fallback
|
||||
}
|
||||
|
||||
$('#scanner-loading').hide();
|
||||
drawOverlay();
|
||||
}
|
||||
|
||||
function setupScannerCanvas() {
|
||||
// Resize Canvas to fit screen but keep aspect ratio
|
||||
var maxWidth = $('#modalScanner .modal-body').width() - 20;
|
||||
var maxHeight = $('#modalScanner .modal-body').height() - 20;
|
||||
|
||||
var scale = Math.min(maxWidth / originalImg.width, maxHeight / originalImg.height);
|
||||
var w = originalImg.width * scale;
|
||||
var h = originalImg.height * scale;
|
||||
|
||||
canvasImage.width = w;
|
||||
canvasImage.height = h;
|
||||
canvasOverlay.width = w;
|
||||
canvasOverlay.height = h;
|
||||
|
||||
// Resize container
|
||||
$('#scanner-container').css({ width: w, height: h, marginTop: '10px' });
|
||||
|
||||
// Draw Image
|
||||
ctxImg.drawImage(originalImg, 0, 0, w, h);
|
||||
|
||||
detectDocument(scale, w, h, false);
|
||||
$('#scanner-loading').hide();
|
||||
|
||||
// No cropper needed - smart scan only
|
||||
}
|
||||
|
||||
|
||||
|
||||
function defaultCorners(w, h) {
|
||||
function defaultCorners(w, h) {
|
||||
// Default 20% margin
|
||||
var mX = w * 0.1;
|
||||
var mY = h * 0.1;
|
||||
@@ -566,7 +181,7 @@ window.addEventListener('load', function() {
|
||||
|
||||
if (corners.length < 4) return;
|
||||
|
||||
// Draw thin cropping lines
|
||||
// Draw Lines
|
||||
ctxOver.beginPath();
|
||||
ctxOver.lineWidth = LINE_WIDTH;
|
||||
ctxOver.strokeStyle = LINE_COLOR;
|
||||
@@ -577,19 +192,14 @@ window.addEventListener('load', function() {
|
||||
ctxOver.closePath();
|
||||
ctxOver.stroke();
|
||||
|
||||
// Draw transparent circles with thin outline
|
||||
// Draw Points
|
||||
ctxOver.fillStyle = POINT_COLOR;
|
||||
corners.forEach(p => {
|
||||
// Draw transparent inner circle
|
||||
ctxOver.beginPath();
|
||||
ctxOver.arc(p.x, p.y, POINT_RADIUS, 0, Math.PI * 2);
|
||||
ctxOver.fillStyle = POINT_COLOR;
|
||||
ctxOver.fill();
|
||||
|
||||
// Draw thin blue outline
|
||||
ctxOver.beginPath();
|
||||
ctxOver.arc(p.x, p.y, POINT_RADIUS, 0, Math.PI * 2);
|
||||
ctxOver.lineWidth = POINT_OUTLINE_WIDTH;
|
||||
ctxOver.strokeStyle = POINT_OUTLINE_COLOR;
|
||||
ctxOver.strokeStyle = 'white';
|
||||
ctxOver.lineWidth = 2;
|
||||
ctxOver.stroke();
|
||||
});
|
||||
}
|
||||
@@ -604,192 +214,106 @@ window.addEventListener('load', function() {
|
||||
};
|
||||
}
|
||||
|
||||
function isInside(pos, point) {
|
||||
var dx = pos.x - point.x;
|
||||
var dy = pos.y - point.y;
|
||||
return dx * dx + dy * dy <= POINT_RADIUS * POINT_RADIUS * 2; // Bigger hit area
|
||||
}
|
||||
|
||||
function getClosestCorner(pos, isTouch) {
|
||||
var closestIdx = -1;
|
||||
var closestDist = Infinity;
|
||||
var radius = POINT_RADIUS * (isTouch ? TOUCH_RADIUS_MULTIPLIER : 1.5); // Larger radius for touch
|
||||
var radiusSq = radius * radius;
|
||||
|
||||
corners.forEach((p, i) => {
|
||||
var dx = pos.x - p.x;
|
||||
var dy = pos.y - p.y;
|
||||
var distSq = dx * dx + dy * dy;
|
||||
if (distSq < radiusSq && distSq < closestDist) {
|
||||
closestDist = distSq;
|
||||
closestIdx = i;
|
||||
}
|
||||
});
|
||||
return closestIdx;
|
||||
}
|
||||
function isInside(pos, point) {
|
||||
var dx = pos.x - point.x;
|
||||
var dy = pos.y - point.y;
|
||||
return dx * dx + dy * dy <= POINT_RADIUS * POINT_RADIUS * 2; // Bigger hit area
|
||||
}
|
||||
|
||||
canvasOverlay.addEventListener('mousedown', function(e) {
|
||||
handleStart(getMousePos(e), false);
|
||||
e.stopPropagation();
|
||||
});
|
||||
canvasOverlay.addEventListener('touchstart', function(e) {
|
||||
var pos = getMousePos(e);
|
||||
handleStart(pos, true);
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
}, {passive: false});
|
||||
canvasOverlay.addEventListener('mousedown', function(e) { handleStart(getMousePos(e)); });
|
||||
canvasOverlay.addEventListener('touchstart', function(e) { handleStart(getMousePos(e)); e.preventDefault(); }, {passive: false});
|
||||
|
||||
window.addEventListener('mousemove', function(e) { if(isDragging) handleMove(getMousePos(e)); }); // Window to catch drag out
|
||||
canvasOverlay.addEventListener('touchmove', function(e) {
|
||||
if(isDragging) {
|
||||
handleMove(getMousePos(e));
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
}
|
||||
}, {passive: false});
|
||||
window.addEventListener('mousemove', function(e) { if(isDragging) handleMove(getMousePos(e)); }); // Window to catch drag out
|
||||
canvasOverlay.addEventListener('touchmove', function(e) { if(isDragging) handleMove(getMousePos(e)); e.preventDefault(); }, {passive: false});
|
||||
|
||||
window.addEventListener('mouseup', function() { handleEnd(); });
|
||||
window.addEventListener('touchend', function() { handleEnd(); });
|
||||
|
||||
function handleStart(pos, isTouch = false) {
|
||||
activePoint = getClosestCorner(pos, isTouch);
|
||||
if (activePoint !== -1) {
|
||||
isTouchInteraction = isTouch;
|
||||
touchOffset = { x: pos.x - corners[activePoint].x, y: pos.y - corners[activePoint].y };
|
||||
if (isTouch) {
|
||||
touchStartPos = pos;
|
||||
// Start dragging immediately but handle slop in handleMove
|
||||
isDragging = true;
|
||||
} else {
|
||||
isDragging = true;
|
||||
touchStartPos = null;
|
||||
}
|
||||
} else {
|
||||
activePoint = null;
|
||||
isDragging = false;
|
||||
isTouchInteraction = false;
|
||||
touchStartPos = null;
|
||||
touchOffset = null;
|
||||
}
|
||||
}
|
||||
function handleStart(pos) {
|
||||
activePoint = null;
|
||||
corners.forEach((p, i) => {
|
||||
if (isInside(pos, p)) {
|
||||
activePoint = i;
|
||||
isDragging = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function handleMove(pos) {
|
||||
if (activePoint !== null) {
|
||||
// Touch slop detection
|
||||
if (isTouchInteraction && touchStartPos) {
|
||||
var dx = pos.x - touchStartPos.x;
|
||||
var dy = pos.y - touchStartPos.y;
|
||||
var distSq = dx * dx + dy * dy;
|
||||
if (distSq < TOUCH_SLOP * TOUCH_SLOP) {
|
||||
return; // Ignore small movements until slop exceeded
|
||||
}
|
||||
// Slop exceeded, clear touchStartPos so we don't check again
|
||||
touchStartPos = null;
|
||||
}
|
||||
function handleMove(pos) {
|
||||
if (activePoint !== null) {
|
||||
// Constrain to canvas?? Optional but good
|
||||
corners[activePoint].x = pos.x;
|
||||
corners[activePoint].y = pos.y;
|
||||
drawOverlay();
|
||||
}
|
||||
}
|
||||
|
||||
function handleEnd() {
|
||||
isDragging = false;
|
||||
activePoint = null;
|
||||
}
|
||||
|
||||
// --- Rotate Functions ---
|
||||
function rotateImage(degree) {
|
||||
var offCanvas = document.createElement('canvas');
|
||||
var offCtx = offCanvas.getContext('2d');
|
||||
|
||||
// Swap Width/Height for 90 degree rotation
|
||||
offCanvas.width = originalImg.height;
|
||||
offCanvas.height = originalImg.width;
|
||||
|
||||
offCtx.translate(offCanvas.width / 2, offCanvas.height / 2);
|
||||
offCtx.rotate(degree * Math.PI / 180);
|
||||
offCtx.drawImage(originalImg, -originalImg.width / 2, -originalImg.height / 2);
|
||||
|
||||
// Update originalImg
|
||||
var rotatedUrl = offCanvas.toDataURL();
|
||||
originalImg.onload = function() {
|
||||
initScanner(); // Re-init with new image
|
||||
}
|
||||
originalImg.src = rotatedUrl;
|
||||
}
|
||||
|
||||
$('#btnScanRotateLeft').click(function() { rotateImage(-90); });
|
||||
$('#btnScanRotateRight').click(function() { rotateImage(90); });
|
||||
|
||||
// --- Reset Button ---
|
||||
$('#btnScanReset').click(function() {
|
||||
initScanner();
|
||||
});
|
||||
|
||||
// --- Save / Extract Button ---
|
||||
$('#btnScanSave').click(function() {
|
||||
// Warp Image
|
||||
try {
|
||||
// 1. Get raw points relative to Original Image
|
||||
var scaleX = originalImg.width / canvasImage.width;
|
||||
var scaleY = originalImg.height / canvasImage.height;
|
||||
|
||||
// Apply offset to maintain relative position
|
||||
if (touchOffset) {
|
||||
corners[activePoint].x = pos.x - touchOffset.x;
|
||||
corners[activePoint].y = pos.y - touchOffset.y;
|
||||
} else {
|
||||
corners[activePoint].x = pos.x;
|
||||
corners[activePoint].y = pos.y;
|
||||
}
|
||||
var tl = { x: corners[0].x * scaleX, y: corners[0].y * scaleY };
|
||||
var tr = { x: corners[1].x * scaleX, y: corners[1].y * scaleY };
|
||||
var br = { x: corners[2].x * scaleX, y: corners[2].y * scaleY };
|
||||
var bl = { x: corners[3].x * scaleX, y: corners[3].y * scaleY };
|
||||
|
||||
// Optional: constrain to canvas bounds
|
||||
var w = canvasOverlay.width;
|
||||
var h = canvasOverlay.height;
|
||||
corners[activePoint].x = Math.max(0, Math.min(w, corners[activePoint].x));
|
||||
corners[activePoint].y = Math.max(0, Math.min(h, corners[activePoint].y));
|
||||
// 2. Calculate dimensions of the crop area
|
||||
var widthTop = Math.hypot(tr.x - tl.x, tr.y - tl.y);
|
||||
var widthBottom = Math.hypot(br.x - bl.x, br.y - bl.y);
|
||||
var outputWidth = Math.max(widthTop, widthBottom);
|
||||
|
||||
drawOverlay();
|
||||
}
|
||||
}
|
||||
var heightLeft = Math.hypot(bl.x - tl.x, bl.y - tl.y);
|
||||
var heightRight = Math.hypot(br.x - tr.x, br.y - tr.y);
|
||||
var outputHeight = Math.max(heightLeft, heightRight);
|
||||
|
||||
function handleEnd() {
|
||||
isDragging = false;
|
||||
activePoint = null;
|
||||
isTouchInteraction = false;
|
||||
touchStartPos = null;
|
||||
touchOffset = null;
|
||||
}
|
||||
|
||||
// --- Rotate Functions ---
|
||||
function rotateImage(degree) {
|
||||
var offCanvas = document.createElement('canvas');
|
||||
var offCtx = offCanvas.getContext('2d');
|
||||
|
||||
// Swap Width/Height for 90 degree rotation
|
||||
offCanvas.width = originalImg.height;
|
||||
offCanvas.height = originalImg.width;
|
||||
|
||||
offCtx.translate(offCanvas.width / 2, offCanvas.height / 2);
|
||||
offCtx.rotate(degree * Math.PI / 180);
|
||||
offCtx.drawImage(originalImg, -originalImg.width / 2, -originalImg.height / 2);
|
||||
|
||||
// Update originalImg
|
||||
var rotatedUrl = offCanvas.toDataURL();
|
||||
originalImg.onload = function() {
|
||||
// Re-init scanner
|
||||
setupScannerCanvas();
|
||||
}
|
||||
originalImg.src = rotatedUrl;
|
||||
}
|
||||
|
||||
$('#btnScanRotateLeft').click(function() { rotateImage(-90); });
|
||||
$('#btnScanRotateRight').click(function() { rotateImage(90); });
|
||||
|
||||
// --- Reset Button ---
|
||||
$('#btnScanReset').click(function() {
|
||||
setupScannerCanvas();
|
||||
});
|
||||
|
||||
|
||||
|
||||
// --- Save / Extract Button ---
|
||||
$('#btnScanSave').click(function() {
|
||||
try {
|
||||
var base64;
|
||||
var extractPoints = {
|
||||
topLeftCorner: tl,
|
||||
topRightCorner: tr,
|
||||
bottomRightCorner: br,
|
||||
bottomLeftCorner: bl
|
||||
};
|
||||
|
||||
// Smart Scan Mode - Use jscanify
|
||||
// 1. Get raw points relative to Original Image
|
||||
var scaleX = originalImg.width / canvasImage.width;
|
||||
var scaleY = originalImg.height / canvasImage.height;
|
||||
|
||||
var tl = { x: corners[0].x * scaleX, y: corners[0].y * scaleY };
|
||||
var tr = { x: corners[1].x * scaleX, y: corners[1].y * scaleY };
|
||||
var br = { x: corners[2].x * scaleX, y: corners[2].y * scaleY };
|
||||
var bl = { x: corners[3].x * scaleX, y: corners[3].y * scaleY };
|
||||
|
||||
// 2. Calculate dimensions of the crop area
|
||||
var widthTop = Math.hypot(tr.x - tl.x, tr.y - tl.y);
|
||||
var widthBottom = Math.hypot(br.x - bl.x, br.y - bl.y);
|
||||
var outputWidth = Math.max(widthTop, widthBottom);
|
||||
|
||||
var heightLeft = Math.hypot(bl.x - tl.x, bl.y - tl.y);
|
||||
var heightRight = Math.hypot(br.x - tr.x, br.y - tr.y);
|
||||
var outputHeight = Math.max(heightLeft, heightRight);
|
||||
|
||||
var extractPoints = {
|
||||
topLeftCorner: tl,
|
||||
topRightCorner: tr,
|
||||
bottomRightCorner: br,
|
||||
bottomLeftCorner: bl
|
||||
};
|
||||
|
||||
// 3. Extract with dynamic dimensions
|
||||
var resultCanvas = null;
|
||||
if (!scanner || !scanner.extractPaper) {
|
||||
// Try to initialize scanner if not ready
|
||||
initScanner();
|
||||
}
|
||||
if (scanner && scanner.extractPaper) {
|
||||
resultCanvas = scanner.extractPaper(originalImg, outputWidth, outputHeight, extractPoints);
|
||||
} else {
|
||||
alert("Scanner library not loaded. Please refresh the page.");
|
||||
return;
|
||||
}
|
||||
base64 = resultCanvas.toDataURL('image/jpeg');
|
||||
// 3. Extract with dynamic dimensions
|
||||
var resultCanvas = scanner.extractPaper(originalImg, outputWidth, outputHeight, extractPoints);
|
||||
var base64 = resultCanvas.toDataURL('image/jpeg');
|
||||
|
||||
if (window.handleScannerResult) {
|
||||
window.handleScannerResult(base64);
|
||||
@@ -797,18 +321,10 @@ window.addEventListener('load', function() {
|
||||
|
||||
scannerModal.modal('hide');
|
||||
|
||||
} catch (e) {
|
||||
alert("Gagal memproses gambar: " + e.message);
|
||||
console.error(e);
|
||||
}
|
||||
});
|
||||
|
||||
// Show mobile help if touch device
|
||||
if (IS_TOUCH_DEVICE) {
|
||||
$('#mobile-help').removeClass('d-none');
|
||||
}
|
||||
|
||||
// Mode is always smart scan now
|
||||
}, 500); }); });
|
||||
} catch (e) {
|
||||
alert("Gagal memproses gambar: " + e.message);
|
||||
}
|
||||
});
|
||||
|
||||
</script>
|
||||
});
|
||||
</script>
|
||||
|
||||
0
unused/build/config/postcss.config.js → build/config/postcss.config.js
Executable file → Normal file
0
unused/build/config/postcss.config.js → build/config/postcss.config.js
Executable file → Normal file
0
unused/build/config/rollup.config.js → build/config/rollup.config.js
Executable file → Normal file
0
unused/build/config/rollup.config.js → build/config/rollup.config.js
Executable file → Normal file
0
unused/build/js/.jscsrc → build/js/.jscsrc
Executable file → Normal file
0
unused/build/js/.jscsrc → build/js/.jscsrc
Executable file → Normal file
0
unused/build/js/AdminLTE.js → build/js/AdminLTE.js
Executable file → Normal file
0
unused/build/js/AdminLTE.js → build/js/AdminLTE.js
Executable file → Normal file
0
unused/build/js/CardRefresh.js → build/js/CardRefresh.js
Executable file → Normal file
0
unused/build/js/CardRefresh.js → build/js/CardRefresh.js
Executable file → Normal file
0
unused/build/js/CardWidget.js → build/js/CardWidget.js
Executable file → Normal file
0
unused/build/js/CardWidget.js → build/js/CardWidget.js
Executable file → Normal file
0
unused/build/js/ControlSidebar.js → build/js/ControlSidebar.js
Executable file → Normal file
0
unused/build/js/ControlSidebar.js → build/js/ControlSidebar.js
Executable file → Normal file
0
unused/build/js/DirectChat.js → build/js/DirectChat.js
Executable file → Normal file
0
unused/build/js/DirectChat.js → build/js/DirectChat.js
Executable file → Normal file
0
unused/build/js/Dropdown.js → build/js/Dropdown.js
Executable file → Normal file
0
unused/build/js/Dropdown.js → build/js/Dropdown.js
Executable file → Normal file
0
unused/build/js/Layout.js → build/js/Layout.js
Executable file → Normal file
0
unused/build/js/Layout.js → build/js/Layout.js
Executable file → Normal file
0
unused/build/js/PushMenu.js → build/js/PushMenu.js
Executable file → Normal file
0
unused/build/js/PushMenu.js → build/js/PushMenu.js
Executable file → Normal file
0
unused/build/js/SiteSearch.js → build/js/SiteSearch.js
Executable file → Normal file
0
unused/build/js/SiteSearch.js → build/js/SiteSearch.js
Executable file → Normal file
0
unused/build/js/Toasts.js → build/js/Toasts.js
Executable file → Normal file
0
unused/build/js/Toasts.js → build/js/Toasts.js
Executable file → Normal file
0
unused/build/js/TodoList.js → build/js/TodoList.js
Executable file → Normal file
0
unused/build/js/TodoList.js → build/js/TodoList.js
Executable file → Normal file
0
unused/build/js/Treeview.js → build/js/Treeview.js
Executable file → Normal file
0
unused/build/js/Treeview.js → build/js/Treeview.js
Executable file → Normal file
0
unused/build/npm/DocsPlugins.js → build/npm/DocsPlugins.js
Executable file → Normal file
0
unused/build/npm/DocsPlugins.js → build/npm/DocsPlugins.js
Executable file → Normal file
0
unused/build/npm/DocsPublish.js → build/npm/DocsPublish.js
Executable file → Normal file
0
unused/build/npm/DocsPublish.js → build/npm/DocsPublish.js
Executable file → Normal file
0
unused/build/npm/Plugins.js → build/npm/Plugins.js
Executable file → Normal file
0
unused/build/npm/Plugins.js → build/npm/Plugins.js
Executable file → Normal file
0
unused/build/npm/Publish.js → build/npm/Publish.js
Executable file → Normal file
0
unused/build/npm/Publish.js → build/npm/Publish.js
Executable file → Normal file
0
unused/build/scss/.csslintrc → build/scss/.csslintrc
Executable file → Normal file
0
unused/build/scss/.csslintrc → build/scss/.csslintrc
Executable file → Normal file
0
unused/build/scss/AdminLTE-components.scss → build/scss/AdminLTE-components.scss
Executable file → Normal file
0
unused/build/scss/AdminLTE-components.scss → build/scss/AdminLTE-components.scss
Executable file → Normal file
0
unused/build/scss/AdminLTE-core.scss → build/scss/AdminLTE-core.scss
Executable file → Normal file
0
unused/build/scss/AdminLTE-core.scss → build/scss/AdminLTE-core.scss
Executable file → Normal file
0
unused/build/scss/AdminLTE-extra-components.scss → build/scss/AdminLTE-extra-components.scss
Executable file → Normal file
0
unused/build/scss/AdminLTE-extra-components.scss → build/scss/AdminLTE-extra-components.scss
Executable file → Normal file
0
unused/build/scss/AdminLTE-pages.scss → build/scss/AdminLTE-pages.scss
Executable file → Normal file
0
unused/build/scss/AdminLTE-pages.scss → build/scss/AdminLTE-pages.scss
Executable file → Normal file
0
unused/build/scss/AdminLTE-plugins.scss → build/scss/AdminLTE-plugins.scss
Executable file → Normal file
0
unused/build/scss/AdminLTE-plugins.scss → build/scss/AdminLTE-plugins.scss
Executable file → Normal file
0
unused/build/scss/AdminLTE-raw.scss → build/scss/AdminLTE-raw.scss
Executable file → Normal file
0
unused/build/scss/AdminLTE-raw.scss → build/scss/AdminLTE-raw.scss
Executable file → Normal file
0
unused/build/scss/AdminLTE.scss → build/scss/AdminLTE.scss
Executable file → Normal file
0
unused/build/scss/AdminLTE.scss → build/scss/AdminLTE.scss
Executable file → Normal file
0
unused/build/scss/_alerts.scss → build/scss/_alerts.scss
Executable file → Normal file
0
unused/build/scss/_alerts.scss → build/scss/_alerts.scss
Executable file → Normal file
0
unused/build/scss/_bootstrap-variables.scss → build/scss/_bootstrap-variables.scss
Executable file → Normal file
0
unused/build/scss/_bootstrap-variables.scss → build/scss/_bootstrap-variables.scss
Executable file → Normal file
0
unused/build/scss/_brand.scss → build/scss/_brand.scss
Executable file → Normal file
0
unused/build/scss/_brand.scss → build/scss/_brand.scss
Executable file → Normal file
0
unused/build/scss/_buttons.scss → build/scss/_buttons.scss
Executable file → Normal file
0
unused/build/scss/_buttons.scss → build/scss/_buttons.scss
Executable file → Normal file
0
unused/build/scss/_callout.scss → build/scss/_callout.scss
Executable file → Normal file
0
unused/build/scss/_callout.scss → build/scss/_callout.scss
Executable file → Normal file
0
unused/build/scss/_cards.scss → build/scss/_cards.scss
Executable file → Normal file
0
unused/build/scss/_cards.scss → build/scss/_cards.scss
Executable file → Normal file
0
unused/build/scss/_carousel.scss → build/scss/_carousel.scss
Executable file → Normal file
0
unused/build/scss/_carousel.scss → build/scss/_carousel.scss
Executable file → Normal file
0
unused/build/scss/_colors.scss → build/scss/_colors.scss
Executable file → Normal file
0
unused/build/scss/_colors.scss → build/scss/_colors.scss
Executable file → Normal file
0
unused/build/scss/_control-sidebar.scss → build/scss/_control-sidebar.scss
Executable file → Normal file
0
unused/build/scss/_control-sidebar.scss → build/scss/_control-sidebar.scss
Executable file → Normal file
0
unused/build/scss/_direct-chat.scss → build/scss/_direct-chat.scss
Executable file → Normal file
0
unused/build/scss/_direct-chat.scss → build/scss/_direct-chat.scss
Executable file → Normal file
0
unused/build/scss/_dropdown.scss → build/scss/_dropdown.scss
Executable file → Normal file
0
unused/build/scss/_dropdown.scss → build/scss/_dropdown.scss
Executable file → Normal file
0
unused/build/scss/_elevation.scss → build/scss/_elevation.scss
Executable file → Normal file
0
unused/build/scss/_elevation.scss → build/scss/_elevation.scss
Executable file → Normal file
0
unused/build/scss/_forms.scss → build/scss/_forms.scss
Executable file → Normal file
0
unused/build/scss/_forms.scss → build/scss/_forms.scss
Executable file → Normal file
0
unused/build/scss/_info-box.scss → build/scss/_info-box.scss
Executable file → Normal file
0
unused/build/scss/_info-box.scss → build/scss/_info-box.scss
Executable file → Normal file
0
unused/build/scss/_layout.scss → build/scss/_layout.scss
Executable file → Normal file
0
unused/build/scss/_layout.scss → build/scss/_layout.scss
Executable file → Normal file
0
unused/build/scss/_main-header.scss → build/scss/_main-header.scss
Executable file → Normal file
0
unused/build/scss/_main-header.scss → build/scss/_main-header.scss
Executable file → Normal file
0
unused/build/scss/_main-sidebar.scss → build/scss/_main-sidebar.scss
Executable file → Normal file
0
unused/build/scss/_main-sidebar.scss → build/scss/_main-sidebar.scss
Executable file → Normal file
0
unused/build/scss/_miscellaneous.scss → build/scss/_miscellaneous.scss
Executable file → Normal file
0
unused/build/scss/_miscellaneous.scss → build/scss/_miscellaneous.scss
Executable file → Normal file
0
unused/build/scss/_mixins.scss → build/scss/_mixins.scss
Executable file → Normal file
0
unused/build/scss/_mixins.scss → build/scss/_mixins.scss
Executable file → Normal file
0
unused/build/scss/_modals.scss → build/scss/_modals.scss
Executable file → Normal file
0
unused/build/scss/_modals.scss → build/scss/_modals.scss
Executable file → Normal file
0
unused/build/scss/_navs.scss → build/scss/_navs.scss
Executable file → Normal file
0
unused/build/scss/_navs.scss → build/scss/_navs.scss
Executable file → Normal file
0
unused/build/scss/_print.scss → build/scss/_print.scss
Executable file → Normal file
0
unused/build/scss/_print.scss → build/scss/_print.scss
Executable file → Normal file
0
unused/build/scss/_products.scss → build/scss/_products.scss
Executable file → Normal file
0
unused/build/scss/_products.scss → build/scss/_products.scss
Executable file → Normal file
0
unused/build/scss/_progress-bars.scss → build/scss/_progress-bars.scss
Executable file → Normal file
0
unused/build/scss/_progress-bars.scss → build/scss/_progress-bars.scss
Executable file → Normal file
0
unused/build/scss/_sidebar-mini.scss → build/scss/_sidebar-mini.scss
Executable file → Normal file
0
unused/build/scss/_sidebar-mini.scss → build/scss/_sidebar-mini.scss
Executable file → Normal file
0
unused/build/scss/_small-box.scss → build/scss/_small-box.scss
Executable file → Normal file
0
unused/build/scss/_small-box.scss → build/scss/_small-box.scss
Executable file → Normal file
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user