Initial commit of unified WebGIS projects

This commit is contained in:
ilham_gmail
2026-06-11 17:42:40 +07:00
commit a0c61f2bc2
64 changed files with 7924 additions and 0 deletions
+76
View File
@@ -0,0 +1,76 @@
# ERD Summary - WebGIS
Dokumen ini merangkum skema database yang dipakai aplikasi pada `sql/migrations/001_init_schema.sql` dan `webgis.sql`.
## Tabel Utama
### `users`
Menyimpan akun pengguna aplikasi.
Kolom penting:
- `email`
- `password_hash`
- `name`
- `organization`
- `org_address`
- `org_phone`
- `org_proof_path`
- `role` dengan nilai `manager` atau `admin`
- `status` dengan nilai `pending`, `active`, `rejected`, atau `pending_verification`
- `email_verified`
- field verifikasi email seperti `email_verification_token_hash`, `email_verification_expires`, dan timestamp terkait
- `approved_by` dan `approved_at`
### `lokasi`
Menyimpan seluruh marker yang tampil di peta.
Kolom penting:
- `nama`
- `no_telp`
- `latitude` dan `longitude`
- `alamat`
- `jenis`
- field khusus rumah seperti `nama_kk`, `rumah_status`, `members`, `monthly_income`
- field bantuan seperti `assisted`, `last_assisted_at`, `assistance_notes`, `sumber_bantuan`, `bentuk_bantuan`
- `photo_path`
- `created_by`
### `bantuan_detail`
Menyimpan detail histori bantuan per lokasi.
Kolom penting:
- `lokasi_id`
- `tanggal_bantuan`
- `pemberi_bantuan`
- `catatan`
- `pemberi_lokasi_id`
- `jumlah`
### `migrations`
Menyimpan catatan migration yang sudah dijalankan.
## Relasi
- `users.approved_by` mengarah ke `users.id`
- `lokasi.created_by` mengarah ke `users.id`
- `lokasi.sumber_bantuan` mengarah ke `lokasi.id`
- `bantuan_detail.lokasi_id` mengarah ke `lokasi.id`
- `bantuan_detail.pemberi_lokasi_id` mengarah ke `lokasi.id`
## Alur Data
1. Guest melihat data publik di peta dan tabel.
2. Pengelola mendaftar, menerima kode verifikasi email, lalu akun dibuat dalam status menunggu persetujuan admin.
3. Admin menyetujui akun pengelola.
4. Pengelola yang disetujui dapat menambah dan mengubah data miliknya.
5. Admin bisa mengelola seluruh data.
## Catatan Implementasi
- Database yang dipakai adalah MySQL/MariaDB.
- Semua relasi foreign key dibuat agar data tetap konsisten.
- Kolom bantuan dan verifikasi email disimpan langsung di tabel utama supaya alurnya sederhana untuk pengembangan berikutnya.
+156
View File
@@ -0,0 +1,156 @@
window.webgisOpenApiSpec = {
openapi: '3.0.3',
info: {
title: 'WebGIS API',
version: '1.0.0',
description: 'API for public map data, manager registrations, and admin approvals.'
},
servers: [{ url: '.' }],
components: {
securitySchemes: {
bearerAuth: {
type: 'http',
scheme: 'bearer',
bearerFormat: 'JWT'
}
}
},
paths: {
'/src/api/auth/register.php': {
post: {
summary: 'Register manager account',
description: 'Public registration endpoint for manager accounts.',
requestBody: {
required: true,
content: {
'application/json': {
schema: {
type: 'object',
required: ['email', 'password'],
properties: {
email: { type: 'string', format: 'email' },
password: { type: 'string' },
name: { type: 'string' },
organization: { type: 'string' }
}
}
}
}
},
responses: { '200': { description: 'Registration successful, pending approval' } }
}
},
'/src/api/auth/login.php': {
post: {
summary: 'Login',
requestBody: {
required: true,
content: {
'application/json': {
schema: {
type: 'object',
required: ['email', 'password'],
properties: {
email: { type: 'string', format: 'email' },
password: { type: 'string' }
}
}
}
}
},
responses: { '200': { description: 'Login successful' } }
}
},
'/src/api/auth/logout.php': {
post: {
summary: 'Logout',
security: [{ bearerAuth: [] }],
responses: { '200': { description: 'Logout successful' } }
}
},
'/src/api/auth/me.php': {
get: {
summary: 'Current user session',
security: [{ bearerAuth: [] }],
responses: { '200': { description: 'Current auth state' } }
}
},
'/src/api/get_lokasi.php': {
get: {
summary: 'List locations',
description: 'Public read-only endpoint.',
responses: { '200': { description: 'Location list' } }
}
},
'/src/api/tambah_lokasi.php': {
post: {
summary: 'Create location',
description: 'Bearer JWT required. Managers can create records; admins can create all.',
security: [{ bearerAuth: [] }],
requestBody: {
required: true,
content: {
'application/json': {
schema: {
type: 'object',
properties: {
nama: { type: 'string' },
jenis: { type: 'string' },
alamat: { type: 'string' },
latitude: { type: 'number' },
longitude: { type: 'number' }
}
}
}
}
},
responses: { '200': { description: 'Created' } }
}
},
'/src/api/update_lokasi.php': {
post: {
summary: 'Update location',
description: 'Bearer JWT required. Managers can edit only their own lokasi; admins can edit all.',
security: [{ bearerAuth: [] }],
responses: { '200': { description: 'Updated' } }
}
},
'/src/api/hapus_lokasi.php': {
post: {
summary: 'Delete location',
description: 'Bearer JWT required. Managers can delete only their own lokasi; admins can delete all.',
security: [{ bearerAuth: [] }],
responses: { '200': { description: 'Deleted' } }
}
},
'/src/api/upload_photo.php': {
post: {
summary: 'Upload location photo',
description: 'Bearer JWT required. Managers can upload only for their own lokasi.',
security: [{ bearerAuth: [] }],
responses: { '200': { description: 'Uploaded' } }
}
},
'/src/api/admin/list_pending_managers.php': {
get: {
summary: 'List pending manager registrations',
security: [{ bearerAuth: [] }],
responses: { '200': { description: 'Pending list' } }
}
},
'/src/api/admin/approve_user.php': {
post: {
summary: 'Approve pending user',
security: [{ bearerAuth: [] }],
responses: { '200': { description: 'Approved' } }
}
},
'/src/api/admin/reject_user.php': {
post: {
summary: 'Reject pending user',
security: [{ bearerAuth: [] }],
responses: { '200': { description: 'Rejected' } }
}
}
}
};
+208
View File
@@ -0,0 +1,208 @@
openapi: 3.0.3
info:
title: WebGIS API
version: 1.0.0
description: API untuk autentikasi pengelola, data lokasi, unggah foto, dan persetujuan admin.
servers:
- url: .
components:
securitySchemes:
bearerAuth:
type: http
scheme: bearer
bearerFormat: JWT
basicAuth:
type: http
scheme: basic
schemas:
RegisterRequest:
type: object
required:
- email
- password
- name
- organization
- org_address
- org_phone
- verify_code
properties:
email:
type: string
format: email
password:
type: string
name:
type: string
organization:
type: string
org_address:
type: string
org_phone:
type: string
verify_code:
type: string
pattern: '^[0-9]{6}$'
LoginRequest:
type: object
required:
- email
- password
properties:
email:
type: string
format: email
password:
type: string
LocationRequest:
type: object
properties:
nama:
type: string
jenis:
type: string
no_telp:
type: string
alamat:
type: string
latitude:
type: number
longitude:
type: number
assisted:
type: integer
enum: [0, 1]
paths:
/src/api/auth/register.php:
post:
summary: Daftar pengelola baru
requestBody:
required: true
content:
multipart/form-data:
schema:
$ref: '#/components/schemas/RegisterRequest'
application/json:
schema:
$ref: '#/components/schemas/RegisterRequest'
responses:
'200':
description: Pendaftaran berhasil dan akun menunggu persetujuan admin
/src/api/auth/send_verification_code.php:
post:
summary: Kirim kode verifikasi email
requestBody:
required: true
content:
application/json:
schema:
type: object
required: [email]
properties:
email:
type: string
format: email
responses:
'200':
description: Kode verifikasi terkirim
/src/api/auth/login.php:
post:
summary: Login pengguna
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/LoginRequest'
responses:
'200':
description: Login berhasil
/src/api/auth/logout.php:
post:
summary: Logout pengguna
security:
- bearerAuth: []
responses:
'200':
description: Logout berhasil
/src/api/auth/me.php:
get:
summary: Ambil sesi pengguna aktif
security:
- bearerAuth: []
responses:
'200':
description: Status autentikasi saat ini
/src/api/get_client_config.php:
get:
summary: Konfigurasi klien yang aman untuk frontend
responses:
'200':
description: Data konfigurasi klien
/src/api/get_lokasi.php:
get:
summary: Ambil daftar lokasi
responses:
'200':
description: Daftar lokasi
/src/api/tambah_lokasi.php:
post:
summary: Tambah lokasi baru
security:
- bearerAuth: []
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/LocationRequest'
responses:
'200':
description: Data berhasil dibuat
/src/api/update_lokasi.php:
post:
summary: Perbarui lokasi
security:
- bearerAuth: []
responses:
'200':
description: Data berhasil diperbarui
/src/api/hapus_lokasi.php:
post:
summary: Hapus lokasi
security:
- bearerAuth: []
responses:
'200':
description: Data berhasil dihapus
/src/api/upload_photo.php:
post:
summary: Unggah foto lokasi
security:
- bearerAuth: []
responses:
'200':
description: Foto berhasil diunggah
/src/api/admin/list_pending_managers.php:
get:
summary: Daftar pengelola menunggu persetujuan
security:
- bearerAuth: []
responses:
'200':
description: Daftar akun pending
/src/api/admin/approve_user.php:
post:
summary: Setujui akun pengelola
security:
- bearerAuth: []
responses:
'200':
description: Akun disetujui
/src/api/admin/reject_user.php:
post:
summary: Tolak akun pengelola
security:
- bearerAuth: []
responses:
'200':
description: Akun ditolak
+37
View File
@@ -0,0 +1,37 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>WebGIS API Docs</title>
<link rel="stylesheet" href="https://unpkg.com/swagger-ui-dist@5/swagger-ui.css">
<style>
body{margin:0;background:#0f172a;font-family:system-ui,-apple-system,Segoe UI,Roboto,Arial,sans-serif}
.topbar{padding:18px 20px;background:linear-gradient(135deg,#0f172a,#1e293b);color:#fff;border-bottom:1px solid rgba(255,255,255,0.08)}
.topbar h1{margin:0;font-size:20px}
.topbar p{margin:6px 0 0;color:#cbd5e1;font-size:13px}
#swagger-ui{background:#fff}
</style>
</head>
<body>
<div class="topbar">
<h1>WebGIS API Docs</h1>
<p>OpenAPI documentation for auth, public map data, manager, and admin endpoints.</p>
</div>
<div id="swagger-ui"></div>
<script src="https://unpkg.com/swagger-ui-dist@5/swagger-ui-bundle.js"></script>
<script src="openapi.js"></script>
<script>
window.onload = function() {
SwaggerUIBundle({
spec: window.webgisOpenApiSpec,
dom_id: '#swagger-ui',
deepLinking: true,
displayRequestDuration: true,
presets: [SwaggerUIBundle.presets.apis],
layout: 'BaseLayout'
});
};
</script>
</body>
</html>