Initial commit: Aplikasi WebGIS PHP Native
This commit is contained in:
@@ -0,0 +1,232 @@
|
||||
<?php
|
||||
session_start();
|
||||
header("Content-Type: application/json");
|
||||
|
||||
// ── KONFIGURASI DATABASE ──────────────────────────────────────
|
||||
$host = '127.0.0.1';
|
||||
$db = 'webgis_poverty';
|
||||
$user = 'root'; // Sesuaikan jika ada password
|
||||
$pass = '';
|
||||
|
||||
try {
|
||||
$pdo = new PDO("mysql:host=$host;dbname=$db;charset=utf8mb4", $user, $pass, [
|
||||
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
|
||||
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC
|
||||
]);
|
||||
} catch (PDOException $e) {
|
||||
http_response_code(500);
|
||||
echo json_encode(['error' => 'Koneksi DB Gagal: ' . $e->getMessage()]);
|
||||
exit;
|
||||
}
|
||||
|
||||
// ── ROUTER ────────────────────────────────────────────────────
|
||||
$route = $_GET['route'] ?? '';
|
||||
$method = $_SERVER['REQUEST_METHOD'];
|
||||
$data = json_decode(file_get_contents('php://input'), true) ?: [];
|
||||
|
||||
// Helper Authentication
|
||||
function checkAuth() {
|
||||
if (!isset($_SESSION['user'])) {
|
||||
http_response_code(401);
|
||||
echo json_encode(['error' => 'Login diperlukan']);
|
||||
exit;
|
||||
}
|
||||
return $_SESSION['user'];
|
||||
}
|
||||
|
||||
// ══════════════════════════════════════════════════
|
||||
// AUTH ENDPOINTS
|
||||
// ══════════════════════════════════════════════════
|
||||
if ($route === '/login' && $method === 'POST') {
|
||||
$stmt = $pdo->prepare("SELECT * FROM users WHERE email = ? AND password_hash = ?");
|
||||
// Menggunakan SHA256 sesuai format di schema.sql Anda
|
||||
$stmt->execute([$data['email'] ?? '', hash('sha256', $data['password'] ?? '')]);
|
||||
$user = $stmt->fetch();
|
||||
|
||||
if ($user && $user['is_active']) {
|
||||
$_SESSION['user'] = $user;
|
||||
echo json_encode($user);
|
||||
} else {
|
||||
http_response_code(401);
|
||||
echo json_encode(['error' => 'Email, password salah, atau akun nonaktif']);
|
||||
}
|
||||
exit;
|
||||
}
|
||||
|
||||
if ($route === '/register' && $method === 'POST') {
|
||||
$stmt = $pdo->prepare("SELECT id FROM users WHERE email = ?");
|
||||
$stmt->execute([$data['email']]);
|
||||
if ($stmt->fetch()) {
|
||||
http_response_code(409); echo json_encode(['error' => 'Email sudah terdaftar']); exit;
|
||||
}
|
||||
|
||||
$stmt = $pdo->prepare("INSERT INTO users (nama, email, password_hash, role, wilayah) VALUES (?, ?, ?, 'masyarakat', ?)");
|
||||
$stmt->execute([$data['nama'], $data['email'], hash('sha256', $data['password']), $data['wilayah']]);
|
||||
|
||||
$user = ['id' => $pdo->lastInsertId(), 'nama' => $data['nama'], 'role' => 'masyarakat', 'wilayah' => $data['wilayah']];
|
||||
$_SESSION['user'] = $user;
|
||||
echo json_encode($user);
|
||||
exit;
|
||||
}
|
||||
|
||||
if ($route === '/logout' && $method === 'POST') {
|
||||
session_destroy();
|
||||
echo json_encode(['message' => 'Logout berhasil']);
|
||||
exit;
|
||||
}
|
||||
|
||||
if ($route === '/me' && $method === 'GET') {
|
||||
checkAuth();
|
||||
echo json_encode($_SESSION['user']);
|
||||
exit;
|
||||
}
|
||||
|
||||
// ══════════════════════════════════════════════════
|
||||
// DATA ENDPOINTS (Memerlukan Login)
|
||||
// ══════════════════════════════════════════════════
|
||||
$user = checkAuth();
|
||||
|
||||
if ($route === '/stats' && $method === 'GET') {
|
||||
$total = $pdo->query("SELECT COUNT(*) FROM rumah_tangga")->fetchColumn();
|
||||
$verified = $pdo->query("SELECT COUNT(*) FROM rumah_tangga WHERE status='verified'")->fetchColumn();
|
||||
$ri_count = $pdo->query("SELECT COUNT(*) FROM rumah_ibadah")->fetchColumn();
|
||||
$covered = $pdo->query("SELECT COUNT(*) FROM rumah_tangga WHERE assigned_ri IS NOT NULL")->fetchColumn();
|
||||
|
||||
$kelurahan = $pdo->query("SELECT kelurahan, COUNT(*) as n FROM rumah_tangga GROUP BY kelurahan")->fetchAll();
|
||||
$status = $pdo->query("SELECT status, COUNT(*) as n FROM rumah_tangga GROUP BY status")->fetchAll();
|
||||
|
||||
echo json_encode([
|
||||
'total' => $total, 'verified' => $verified, 'ri_count' => $ri_count,
|
||||
'pct_covered' => $total ? round(($covered/$total)*100) : 0,
|
||||
'by_kelurahan' => $kelurahan, 'by_status' => $status
|
||||
]);
|
||||
exit;
|
||||
}
|
||||
|
||||
if ($route === '/rumah-tangga' && $method === 'GET') {
|
||||
$rows = $pdo->query("SELECT rt.*, ri.nama as ri_nama FROM rumah_tangga rt LEFT JOIN rumah_ibadah ri ON rt.assigned_ri=ri.id ORDER BY rt.created_at DESC")->fetchAll();
|
||||
echo json_encode($rows);
|
||||
exit;
|
||||
}
|
||||
|
||||
if ($route === '/rumah-tangga' && $method === 'POST') {
|
||||
$stmt = $pdo->prepare("INSERT INTO rumah_tangga (nama_kk, alamat, kelurahan, kecamatan, lat, lng, anggota, penghasilan, kondisi, kebutuhan, catatan, dilaporkan_oleh) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
|
||||
$stmt->execute([
|
||||
$data['nama_kk'], $data['alamat']??'', $data['kelurahan']??'', $data['kecamatan']??'',
|
||||
$data['lat'], $data['lng'], $data['anggota']??1, $data['penghasilan']??'',
|
||||
$data['kondisi']??'', $data['kebutuhan']??'', $data['catatan']??'', $user['id']
|
||||
]);
|
||||
|
||||
$rt_id = $pdo->lastInsertId();
|
||||
|
||||
if (!empty($data['tanggungan'])) {
|
||||
$tStmt = $pdo->prepare("INSERT INTO tanggungan (rumah_tangga_id, nama, tanggal_lahir, jenis_kelamin, hubungan, pendidikan, pekerjaan) VALUES (?, ?, ?, ?, ?, ?, ?)");
|
||||
foreach ($data['tanggungan'] as $t) {
|
||||
$tStmt->execute([$rt_id, $t['nama'], $t['tanggal_lahir'], $t['jenis_kelamin']??'L', $t['hubungan']??'', $t['pendidikan']??'', $t['pekerjaan']??'']);
|
||||
}
|
||||
}
|
||||
echo json_encode(['id' => $rt_id, 'message' => 'Laporan tersimpan']);
|
||||
exit;
|
||||
}
|
||||
|
||||
if (preg_match('#^/rumah-tangga/(\d+)$#', $route, $matches) && $method === 'GET') {
|
||||
$id = $matches[1];
|
||||
$rt = $pdo->prepare("SELECT rt.*, ri.nama as ri_nama, ri.tipe as ri_tipe FROM rumah_tangga rt LEFT JOIN rumah_ibadah ri ON rt.assigned_ri=ri.id WHERE rt.id = ?");
|
||||
$rt->execute([$id]);
|
||||
$rtData = $rt->fetch();
|
||||
|
||||
if($rtData) {
|
||||
$tang = $pdo->prepare("SELECT * FROM tanggungan WHERE rumah_tangga_id = ?");
|
||||
$tang->execute([$id]);
|
||||
$rtData['tanggungan'] = $tang->fetchAll();
|
||||
}
|
||||
echo json_encode($rtData);
|
||||
exit;
|
||||
}
|
||||
|
||||
if (preg_match('#^/rumah-tangga/(\d+)/verifikasi$#', $route, $matches) && $method === 'POST') {
|
||||
$id = $matches[1];
|
||||
$aksi = $data['aksi'];
|
||||
|
||||
$rtStmt = $pdo->prepare("SELECT * FROM rumah_tangga WHERE id = ?");
|
||||
$rtStmt->execute([$id]);
|
||||
$rt = $rtStmt->fetch();
|
||||
|
||||
if ($aksi === 'confirm') {
|
||||
$pdo->prepare("UPDATE rumah_tangga SET confirmations = confirmations + 1 WHERE id = ?")->execute([$id]);
|
||||
} elseif ($aksi === 'reject') {
|
||||
$pdo->prepare("UPDATE rumah_tangga SET status = 'rejected' WHERE id = ?")->execute([$id]);
|
||||
} elseif ($aksi === 'admin_approve') {
|
||||
$pdo->prepare("UPDATE rumah_tangga SET status = 'verified' WHERE id = ?")->execute([$id]);
|
||||
|
||||
// Logika sederhana: Assign RI terdekat
|
||||
$ris = $pdo->query("SELECT id, lat, lng, radius FROM rumah_ibadah")->fetchAll();
|
||||
$bestId = null; $bestDist = 99999999;
|
||||
foreach($ris as $ri) {
|
||||
// Kalkulasi Haversine sederhana di PHP
|
||||
$theta = $rt['lng'] - $ri['lng'];
|
||||
$dist = sin(deg2rad($rt['lat'])) * sin(deg2rad($ri['lat'])) + cos(deg2rad($rt['lat'])) * cos(deg2rad($ri['lat'])) * cos(deg2rad($theta));
|
||||
$dist = acos($dist); $dist = rad2deg($dist); $meters = $dist * 60 * 1.1515 * 1609.344;
|
||||
if ($meters <= $ri['radius'] && $meters < $bestDist) { $bestDist = $meters; $bestId = $ri['id']; }
|
||||
}
|
||||
if($bestId) $pdo->prepare("UPDATE rumah_tangga SET assigned_ri = ? WHERE id = ?")->execute([$bestId, $id]);
|
||||
}
|
||||
echo json_encode(['message' => 'Verifikasi berhasil diperbarui']);
|
||||
exit;
|
||||
}
|
||||
|
||||
if ($route === '/rumah-ibadah' && $method === 'GET') {
|
||||
$rows = $pdo->query("SELECT ri.*, (SELECT COUNT(*) FROM rumah_tangga WHERE assigned_ri=ri.id) as assigned_count FROM rumah_ibadah ri ORDER BY ri.nama")->fetchAll();
|
||||
echo json_encode($rows);
|
||||
exit;
|
||||
}
|
||||
|
||||
if ($route === '/rumah-ibadah' && $method === 'POST') {
|
||||
$stmt = $pdo->prepare("INSERT INTO rumah_ibadah (nama, tipe, kelurahan, lat, lng, radius) VALUES (?, ?, ?, ?, ?, ?)");
|
||||
$stmt->execute([$data['nama'], $data['tipe'], $data['kelurahan']??'', $data['lat'], $data['lng'], $data['radius']??500]);
|
||||
echo json_encode(['id' => $pdo->lastInsertId()]);
|
||||
exit;
|
||||
}
|
||||
|
||||
if ($route === '/program' && $method === 'GET') {
|
||||
$rows = $pdo->query("SELECT pb.*, ri.nama as ri_nama FROM program_bantuan pb LEFT JOIN rumah_ibadah ri ON pb.ri_id=ri.id")->fetchAll();
|
||||
echo json_encode($rows);
|
||||
exit;
|
||||
}
|
||||
|
||||
if ($route === '/program' && $method === 'POST') {
|
||||
$stmt = $pdo->prepare("INSERT INTO program_bantuan (nama, tipe, ri_id, target, tanggal) VALUES (?, ?, ?, ?, CURDATE())");
|
||||
$stmt->execute([$data['nama'], $data['tipe'], $data['ri_id'], $data['target']??10]);
|
||||
echo json_encode(['id' => $pdo->lastInsertId()]);
|
||||
exit;
|
||||
}
|
||||
|
||||
if ($route === '/donasi' && $method === 'GET') {
|
||||
$rows = $pdo->query("SELECT d.*, u.nama as nama_donatur, ri.nama as nama_ri FROM donasi d LEFT JOIN users u ON d.donatur_id=u.id LEFT JOIN rumah_ibadah ri ON d.ri_id=ri.id")->fetchAll();
|
||||
echo json_encode($rows);
|
||||
exit;
|
||||
}
|
||||
|
||||
if ($route === '/donasi' && $method === 'POST') {
|
||||
$stmt = $pdo->prepare("INSERT INTO donasi (donatur_id, ri_id, jumlah, keterangan) VALUES (?, ?, ?, ?)");
|
||||
$stmt->execute([$user['id'], $data['ri_id'], $data['jumlah'], $data['keterangan']??'']);
|
||||
echo json_encode(['id' => $pdo->lastInsertId()]);
|
||||
exit;
|
||||
}
|
||||
|
||||
if ($route === '/users' && $method === 'GET') {
|
||||
$rows = $pdo->query("SELECT id, nama, email, role, wilayah, is_active FROM users ORDER BY role")->fetchAll();
|
||||
echo json_encode($rows);
|
||||
exit;
|
||||
}
|
||||
|
||||
if (preg_match('#^/users/(\d+)/toggle$#', $route, $matches) && $method === 'POST') {
|
||||
$id = $matches[1];
|
||||
$pdo->prepare("UPDATE users SET is_active = NOT is_active WHERE id = ?")->execute([$id]);
|
||||
echo json_encode(['ok' => true]);
|
||||
exit;
|
||||
}
|
||||
|
||||
// ── 404 FALLBACK ────────────────────────────────────────────────
|
||||
http_response_code(404);
|
||||
echo json_encode(['error' => 'Endpoint tidak ditemukan']);
|
||||
+2238
File diff suppressed because it is too large
Load Diff
Generated
+204
@@ -0,0 +1,204 @@
|
||||
{
|
||||
"name": "poverty",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"dependencies": {
|
||||
"docx": "^9.6.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "25.8.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-25.8.0.tgz",
|
||||
"integrity": "sha512-TCFSk8IZh+iLX1xtksoBVtdmgL+1IX0fC9BeU4QqFSuNdN/K+HUlhqOzEmSYYpZUVsLYcPqc9KX+60iDuninSQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"undici-types": ">=7.24.0 <7.24.7"
|
||||
}
|
||||
},
|
||||
"node_modules/core-util-is": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz",
|
||||
"integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/docx": {
|
||||
"version": "9.6.1",
|
||||
"resolved": "https://registry.npmjs.org/docx/-/docx-9.6.1.tgz",
|
||||
"integrity": "sha512-ZJja9/KBUuFC109sCMzovoq2GR2wCG/AuxivjA+OHj/q0TEgJIm3S7yrlUxIy3B+bV8YDj/BiHfWyrRFmyWpDQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/node": "^25.2.3",
|
||||
"hash.js": "^1.1.7",
|
||||
"jszip": "^3.10.1",
|
||||
"nanoid": "^5.1.3",
|
||||
"xml": "^1.0.1",
|
||||
"xml-js": "^1.6.8"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/hash.js": {
|
||||
"version": "1.1.7",
|
||||
"resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz",
|
||||
"integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"inherits": "^2.0.3",
|
||||
"minimalistic-assert": "^1.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/immediate": {
|
||||
"version": "3.0.6",
|
||||
"resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz",
|
||||
"integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/inherits": {
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
|
||||
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/isarray": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
|
||||
"integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/jszip": {
|
||||
"version": "3.10.1",
|
||||
"resolved": "https://registry.npmjs.org/jszip/-/jszip-3.10.1.tgz",
|
||||
"integrity": "sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==",
|
||||
"license": "(MIT OR GPL-3.0-or-later)",
|
||||
"dependencies": {
|
||||
"lie": "~3.3.0",
|
||||
"pako": "~1.0.2",
|
||||
"readable-stream": "~2.3.6",
|
||||
"setimmediate": "^1.0.5"
|
||||
}
|
||||
},
|
||||
"node_modules/lie": {
|
||||
"version": "3.3.0",
|
||||
"resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz",
|
||||
"integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"immediate": "~3.0.5"
|
||||
}
|
||||
},
|
||||
"node_modules/minimalistic-assert": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz",
|
||||
"integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==",
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/nanoid": {
|
||||
"version": "5.1.11",
|
||||
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-5.1.11.tgz",
|
||||
"integrity": "sha512-v+KEsUv2ps74PaSKv0gHTxTCgMXOIfBEbaqa6w6ISIGC7ZsvHN4N9oJ8d4cmf0n5oTzQz2SLmThbQWhjd/8eKg==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/ai"
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"nanoid": "bin/nanoid.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^18 || >=20"
|
||||
}
|
||||
},
|
||||
"node_modules/pako": {
|
||||
"version": "1.0.11",
|
||||
"resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz",
|
||||
"integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==",
|
||||
"license": "(MIT AND Zlib)"
|
||||
},
|
||||
"node_modules/process-nextick-args": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
|
||||
"integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/readable-stream": {
|
||||
"version": "2.3.8",
|
||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz",
|
||||
"integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"core-util-is": "~1.0.0",
|
||||
"inherits": "~2.0.3",
|
||||
"isarray": "~1.0.0",
|
||||
"process-nextick-args": "~2.0.0",
|
||||
"safe-buffer": "~5.1.1",
|
||||
"string_decoder": "~1.1.1",
|
||||
"util-deprecate": "~1.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/safe-buffer": {
|
||||
"version": "5.1.2",
|
||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
|
||||
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/sax": {
|
||||
"version": "1.6.0",
|
||||
"resolved": "https://registry.npmjs.org/sax/-/sax-1.6.0.tgz",
|
||||
"integrity": "sha512-6R3J5M4AcbtLUdZmRv2SygeVaM7IhrLXu9BmnOGmmACak8fiUtOsYNWUS4uK7upbmHIBbLBeFeI//477BKLBzA==",
|
||||
"license": "BlueOak-1.0.0",
|
||||
"engines": {
|
||||
"node": ">=11.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/setimmediate": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz",
|
||||
"integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/string_decoder": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
|
||||
"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"safe-buffer": "~5.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/undici-types": {
|
||||
"version": "7.24.6",
|
||||
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.24.6.tgz",
|
||||
"integrity": "sha512-WRNW+sJgj5OBN4/0JpHFqtqzhpbnV0GuB+OozA9gCL7a993SmU+1JBZCzLNxYsbMfIeDL+lTsphD5jN5N+n0zg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/util-deprecate": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
||||
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/xml": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/xml/-/xml-1.0.1.tgz",
|
||||
"integrity": "sha512-huCv9IH9Tcf95zuYCsQraZtWnJvBtLVE0QHMOs8bWyZAFZNDcYjsPq1nEx8jKA9y+Beo9v+7OBPRisQTjinQMw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/xml-js": {
|
||||
"version": "1.6.11",
|
||||
"resolved": "https://registry.npmjs.org/xml-js/-/xml-js-1.6.11.tgz",
|
||||
"integrity": "sha512-7rVi2KMfwfWFl+GpPg6m80IVMWXLRjO+PxTq7V2CDhoGak0wzYzFgUY2m4XJ47OGdXd8eLE8EmwfAmdjw7lC1g==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"sax": "^1.2.4"
|
||||
},
|
||||
"bin": {
|
||||
"xml-js": "bin/cli.js"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"dependencies": {
|
||||
"docx": "^9.6.1"
|
||||
}
|
||||
}
|
||||
+122
@@ -0,0 +1,122 @@
|
||||
-- Create Database
|
||||
CREATE DATABASE IF NOT EXISTS `webgis_poverty` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||
USE `webgis_poverty`;
|
||||
|
||||
-- Table: users
|
||||
CREATE TABLE IF NOT EXISTS `users` (
|
||||
`id` INT AUTO_INCREMENT PRIMARY KEY,
|
||||
`nama` VARCHAR(255) NOT NULL,
|
||||
`email` VARCHAR(255) NOT NULL UNIQUE,
|
||||
`password_hash` VARCHAR(255) NOT NULL,
|
||||
`role` ENUM('super_admin', 'admin_daerah', 'pengurus_ri', 'donatur', 'masyarakat') NOT NULL DEFAULT 'masyarakat',
|
||||
`wilayah` VARCHAR(255) DEFAULT NULL,
|
||||
`is_active` TINYINT(1) NOT NULL DEFAULT 1,
|
||||
`created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
-- Table: rumah_ibadah
|
||||
CREATE TABLE IF NOT EXISTS `rumah_ibadah` (
|
||||
`id` INT AUTO_INCREMENT PRIMARY KEY,
|
||||
`nama` VARCHAR(255) NOT NULL,
|
||||
`tipe` VARCHAR(100) NOT NULL,
|
||||
`agama` VARCHAR(100) DEFAULT NULL,
|
||||
`alamat` TEXT,
|
||||
`kelurahan` VARCHAR(100) DEFAULT NULL,
|
||||
`kecamatan` VARCHAR(100) DEFAULT NULL,
|
||||
`lat` DOUBLE NOT NULL,
|
||||
`lng` DOUBLE NOT NULL,
|
||||
`radius` DOUBLE DEFAULT 500,
|
||||
`kapasitas` INT DEFAULT 10,
|
||||
`pengurus_id` INT DEFAULT NULL,
|
||||
`created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (`pengurus_id`) REFERENCES `users`(`id`) ON DELETE SET NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
-- Table: rumah_tangga
|
||||
CREATE TABLE IF NOT EXISTS `rumah_tangga` (
|
||||
`id` INT AUTO_INCREMENT PRIMARY KEY,
|
||||
`nama_kk` VARCHAR(255) NOT NULL,
|
||||
`alamat` TEXT,
|
||||
`kelurahan` VARCHAR(100) DEFAULT NULL,
|
||||
`kecamatan` VARCHAR(100) DEFAULT NULL,
|
||||
`lat` DOUBLE NOT NULL,
|
||||
`lng` DOUBLE NOT NULL,
|
||||
`anggota` INT DEFAULT 1,
|
||||
`penghasilan` VARCHAR(255) DEFAULT NULL,
|
||||
`kondisi` VARCHAR(255) DEFAULT NULL,
|
||||
`kebutuhan` TEXT,
|
||||
`catatan` TEXT,
|
||||
`dilaporkan_oleh` INT DEFAULT NULL,
|
||||
`status` ENUM('pending', 'verified', 'rejected') DEFAULT 'pending',
|
||||
`confirmations` INT DEFAULT 0,
|
||||
`assigned_ri` INT DEFAULT NULL,
|
||||
`created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (`dilaporkan_oleh`) REFERENCES `users`(`id`) ON DELETE SET NULL,
|
||||
FOREIGN KEY (`assigned_ri`) REFERENCES `rumah_ibadah`(`id`) ON DELETE SET NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
-- Table: tanggungan
|
||||
CREATE TABLE IF NOT EXISTS `tanggungan` (
|
||||
`id` INT AUTO_INCREMENT PRIMARY KEY,
|
||||
`rumah_tangga_id` INT NOT NULL,
|
||||
`nama` VARCHAR(255) NOT NULL,
|
||||
`tanggal_lahir` DATE NOT NULL,
|
||||
`jenis_kelamin` ENUM('L', 'P') DEFAULT 'L',
|
||||
`hubungan` VARCHAR(100) DEFAULT NULL,
|
||||
`pendidikan` VARCHAR(100) DEFAULT NULL,
|
||||
`pekerjaan` VARCHAR(100) DEFAULT NULL,
|
||||
FOREIGN KEY (`rumah_tangga_id`) REFERENCES `rumah_tangga`(`id`) ON DELETE CASCADE
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
-- Table: verifikasi
|
||||
CREATE TABLE IF NOT EXISTS `verifikasi` (
|
||||
`id` INT AUTO_INCREMENT PRIMARY KEY,
|
||||
`rumah_tangga_id` INT NOT NULL,
|
||||
`user_id` INT NOT NULL,
|
||||
`aksi` ENUM('confirm', 'reject', 'admin_approve') NOT NULL,
|
||||
`alasan` TEXT,
|
||||
`created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (`rumah_tangga_id`) REFERENCES `rumah_tangga`(`id`) ON DELETE CASCADE,
|
||||
FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON DELETE CASCADE
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
-- Table: program_bantuan
|
||||
CREATE TABLE IF NOT EXISTS `program_bantuan` (
|
||||
`id` INT AUTO_INCREMENT PRIMARY KEY,
|
||||
`ri_id` INT NOT NULL,
|
||||
`nama` VARCHAR(255) NOT NULL,
|
||||
`tipe` VARCHAR(100) DEFAULT 'Pangan',
|
||||
`deskripsi` TEXT,
|
||||
`target` INT DEFAULT 10,
|
||||
`tanggal` DATE NOT NULL,
|
||||
`status` VARCHAR(50) DEFAULT 'Aktif',
|
||||
`created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (`ri_id`) REFERENCES `rumah_ibadah`(`id`) ON DELETE CASCADE
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
-- Table: donasi
|
||||
CREATE TABLE IF NOT EXISTS `donasi` (
|
||||
`id` INT AUTO_INCREMENT PRIMARY KEY,
|
||||
`donatur_id` INT NOT NULL,
|
||||
`ri_id` INT NOT NULL,
|
||||
`jumlah` DECIMAL(15, 2) NOT NULL DEFAULT 0.00,
|
||||
`keterangan` TEXT,
|
||||
`created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (`donatur_id`) REFERENCES `users`(`id`) ON DELETE CASCADE,
|
||||
FOREIGN KEY (`ri_id`) REFERENCES `rumah_ibadah`(`id`) ON DELETE CASCADE
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
-- Table: notifikasi
|
||||
CREATE TABLE IF NOT EXISTS `notifikasi` (
|
||||
`id` INT AUTO_INCREMENT PRIMARY KEY,
|
||||
`pesan` TEXT NOT NULL,
|
||||
`tipe` VARCHAR(50) DEFAULT 'info',
|
||||
`sudah_baca` TINYINT(1) DEFAULT 0,
|
||||
`created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
-- Insert default Super Admin (Password: admin123 -> SHA256)
|
||||
-- Hash for 'admin123' is 8c6976e5b5410415bde908bd4dee15dfb167a9c873fc4bb8a81f6f2ab448a918
|
||||
INSERT INTO `users` (`nama`, `email`, `password_hash`, `role`, `wilayah`, `is_active`)
|
||||
VALUES ('Super Admin', 'admin@webgis.com', '8c6976e5b5410415bde908bd4dee15dfb167a9c873fc4bb8a81f6f2ab448a918', 'super_admin', 'Semua', 1)
|
||||
ON DUPLICATE KEY UPDATE `id`=`id`;
|
||||
Reference in New Issue
Block a user