diff --git a/poverty-mapping/index.html b/poverty-mapping/index.html
index fd39a83..686932e 100644
--- a/poverty-mapping/index.html
+++ b/poverty-mapping/index.html
@@ -589,11 +589,19 @@ function openAuthModal(mode){
if(form) form.onsubmit = async function(ev){
ev.preventDefault();
- let endpoint = 'src/api/auth/login.php';
- if(mode === 'register') endpoint = 'src/api/auth/register.php';
- if(mode === 'forgot_password') endpoint = 'src/api/auth/reset_password.php';
+ const submitBtn = form.querySelector('button[type="submit"]') || document.getElementById('auth-modal-submit');
+ const originalText = submitBtn ? submitBtn.textContent : 'Kirim';
- try{
+ if(submitBtn) {
+ submitBtn.disabled = true;
+ submitBtn.textContent = 'Memproses...';
+ }
+
+ try {
+ let endpoint = 'src/api/auth/login.php';
+ if(mode === 'register') endpoint = 'src/api/auth/register.php';
+ if(mode === 'forgot_password') endpoint = 'src/api/auth/reset_password.php';
+
let resp, jr;
if(mode === 'register' || mode === 'forgot_password'){
// Validate password length and match
@@ -604,24 +612,42 @@ function openAuthModal(mode){
if(password.length < 8){
showToast('Password minimal harus 8 karakter', 'error', 5000);
+ if(submitBtn) { submitBtn.disabled = false; submitBtn.textContent = originalText; }
return;
}
if(password !== passwordConfirm){
showToast('Konfirmasi password tidak cocok', 'error', 5000);
+ if(submitBtn) { submitBtn.disabled = false; submitBtn.textContent = originalText; }
return;
}
if(mode === 'register'){
// client-side validation for org_proof: size <=5MB and allowed extensions
const fileInput = form.querySelector('input[name="org_proof"]') || document.getElementById('org_proof_input');
- if(!fileInput){ showToast('Input bukti organisasi tidak ditemukan', 'error', 4000); return; }
- if(!(fileInput.files && fileInput.files.length > 0)){ showToast('Mohon unggah bukti organisasi (foto/pdf).', 'error', 5000); return; }
+ if(!fileInput){
+ showToast('Input bukti organisasi tidak ditemukan', 'error', 4000);
+ if(submitBtn) { submitBtn.disabled = false; submitBtn.textContent = originalText; }
+ return;
+ }
+ if(!(fileInput.files && fileInput.files.length > 0)){
+ showToast('Mohon unggah bukti organisasi (foto/pdf).', 'error', 5000);
+ if(submitBtn) { submitBtn.disabled = false; submitBtn.textContent = originalText; }
+ return;
+ }
const f = fileInput.files[0];
const maxSize = 5 * 1024 * 1024;
const allowed = ['jpg','jpeg','png','svg','pdf'];
const ext = (f.name || '').split('.').pop().toLowerCase();
- if(f.size > maxSize){ showToast('Ukuran file bukti organisasi maksimal 5MB', 'error', 5000); return; }
- if(!allowed.includes(ext)){ showToast('Jenis file tidak diperbolehkan. Hanya .png, .jpg, .jpeg, .svg, atau .pdf.', 'error', 5000); return; }
+ if(f.size > maxSize){
+ showToast('Ukuran file bukti organisasi maksimal 5MB', 'error', 5000);
+ if(submitBtn) { submitBtn.disabled = false; submitBtn.textContent = originalText; }
+ return;
+ }
+ if(!allowed.includes(ext)){
+ showToast('Jenis file tidak diperbolehkan. Hanya .png, .jpg, .jpeg, .svg, atau .pdf.', 'error', 5000);
+ if(submitBtn) { submitBtn.disabled = false; submitBtn.textContent = originalText; }
+ return;
+ }
}
// Check verify code
@@ -629,6 +655,7 @@ function openAuthModal(mode){
const code = codeInput ? codeInput.value.trim() : '';
if(!code || code.length !== 6 || !/^\d{6}$/.test(code)){
showToast('Masukkan kode verifikasi 6 digit yang valid', 'error', 4000);
+ if(submitBtn) { submitBtn.disabled = false; submitBtn.textContent = originalText; }
return;
}
@@ -652,6 +679,7 @@ function openAuthModal(mode){
}
if(!resp.ok || !jr || jr.success === false){
showToast((jr && (jr.error || jr.status || jr.message)) ? (jr.error || jr.status || jr.message) : 'Gagal memproses respons dari server', 'error', 5000);
+ if(submitBtn) { submitBtn.disabled = false; submitBtn.textContent = originalText; }
return;
}
if(mode === 'register'){
@@ -670,7 +698,11 @@ function openAuthModal(mode){
showToast('Berhasil masuk', 'success', 3000);
loadData();
}
- }catch(e){ console.error(e); showToast('Gagal memproses autentikasi', 'error', 5000); }
+ }catch(e){
+ console.error(e);
+ showToast('Gagal memproses autentikasi', 'error', 5000);
+ if(submitBtn) { submitBtn.disabled = false; submitBtn.textContent = originalText; }
+ }
};
// Setup event listeners for registration and forgot password "Send Verification Code" buttons
diff --git a/poverty-mapping/src/api/auth/mail_helper.php b/poverty-mapping/src/api/auth/mail_helper.php
index 57c5beb..d13a089 100644
--- a/poverty-mapping/src/api/auth/mail_helper.php
+++ b/poverty-mapping/src/api/auth/mail_helper.php
@@ -9,7 +9,7 @@ require_once __DIR__ . '/../../../vendor/autoload.php';
$dotenvPath = __DIR__ . '/../../../';
if(file_exists($dotenvPath . '.env')){
try{
- $dotenv = Dotenv\Dotenv::createImmutable($dotenvPath);
+ $dotenv = Dotenv\Dotenv::createUnsafeMutable($dotenvPath);
$dotenv->safeLoad();
}catch(Exception $e){}
}
diff --git a/poverty-mapping/src/config/koneksi.php b/poverty-mapping/src/config/koneksi.php
index 2423fa1..170de4e 100644
--- a/poverty-mapping/src/config/koneksi.php
+++ b/poverty-mapping/src/config/koneksi.php
@@ -1,4 +1,6 @@