1008 lines
31 KiB
PHP
1008 lines
31 KiB
PHP
<!DOCTYPE html>
|
|
<html lang="id">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<title>Pengaturan Akun - Sistem TBC</title>
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
|
|
<link href="https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;600;700&display=swap" rel="stylesheet">
|
|
|
|
<script src="https://unpkg.com/lucide@latest"></script>
|
|
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
|
|
|
|
<style>
|
|
|
|
*{
|
|
margin:0;
|
|
padding:0;
|
|
box-sizing:border-box;
|
|
font-family:'Poppins',sans-serif;
|
|
}
|
|
|
|
body{
|
|
display:flex;
|
|
background:#f5f6fa;
|
|
min-height:100vh;
|
|
}
|
|
|
|
.sidebar{
|
|
width:250px;
|
|
height:100vh;
|
|
background:#c40000;
|
|
position:fixed;
|
|
padding-top:30px;
|
|
z-index:10;
|
|
}
|
|
|
|
.sidebar h2{
|
|
color:white;
|
|
text-align:center;
|
|
margin-bottom:40px;
|
|
font-size:22px;
|
|
font-weight:700;
|
|
}
|
|
|
|
.menu{
|
|
list-style:none;
|
|
}
|
|
|
|
.menu a{
|
|
display:flex;
|
|
align-items:center;
|
|
gap:15px;
|
|
padding:15px 25px;
|
|
text-decoration:none;
|
|
color:white;
|
|
transition:0.3s;
|
|
}
|
|
|
|
.menu li.active a,
|
|
.menu li:hover a{
|
|
background:white;
|
|
color:#c40000;
|
|
border-radius:30px 0 0 30px;
|
|
margin-left:10px;
|
|
}
|
|
|
|
.main-content{
|
|
margin-left:250px;
|
|
width:calc(100% - 250px);
|
|
padding:40px;
|
|
}
|
|
|
|
.header-wrapper{
|
|
border-bottom:2px solid #eee;
|
|
margin-bottom:30px;
|
|
padding-bottom:15px;
|
|
}
|
|
|
|
.page-title{
|
|
font-size:28px;
|
|
font-weight:700;
|
|
color:#c40000;
|
|
}
|
|
|
|
.card{
|
|
background:white;
|
|
border-radius:22px;
|
|
padding:24px;
|
|
width:100%;
|
|
box-shadow:0 10px 30px rgba(0,0,0,0.03);
|
|
}
|
|
|
|
.profile-header{
|
|
display:flex;
|
|
align-items:center;
|
|
gap:18px;
|
|
margin-bottom:28px;
|
|
}
|
|
|
|
.profile-icon{
|
|
width:70px;
|
|
height:70px;
|
|
border-radius:18px;
|
|
background:#fee2e2;
|
|
color:#c40000;
|
|
display:flex;
|
|
align-items:center;
|
|
justify-content:center;
|
|
}
|
|
|
|
.profile-info h3{
|
|
font-size:20px;
|
|
color:#222;
|
|
font-weight:600;
|
|
}
|
|
|
|
.profile-info p{
|
|
color:#888;
|
|
font-size:13px;
|
|
margin-top:3px;
|
|
}
|
|
|
|
.info-group{
|
|
margin-bottom:16px;
|
|
}
|
|
|
|
.info-label{
|
|
font-size:12px;
|
|
font-weight:600;
|
|
color:#666;
|
|
margin-bottom:6px;
|
|
}
|
|
|
|
.info-value{
|
|
background:#fafafa;
|
|
border:1px solid #ececec;
|
|
border-radius:10px;
|
|
padding:12px 14px;
|
|
font-size:13px;
|
|
color:#222;
|
|
}
|
|
|
|
.action-buttons{
|
|
display:flex;
|
|
justify-content:flex-end;
|
|
align-items:center;
|
|
gap:10px;
|
|
margin-top:24px;
|
|
padding-top:20px;
|
|
border-top:1px solid #f0f0f0;
|
|
}
|
|
|
|
.btn-action{
|
|
border:none;
|
|
padding:10px 16px;
|
|
border-radius:10px;
|
|
cursor:pointer;
|
|
font-weight:600;
|
|
font-size:12px;
|
|
display:flex;
|
|
align-items:center;
|
|
gap:7px;
|
|
transition:0.3s;
|
|
}
|
|
|
|
.btn-update{
|
|
background:#c40000;
|
|
color:white;
|
|
}
|
|
|
|
.btn-update:hover{
|
|
background:#a80000;
|
|
}
|
|
|
|
.btn-reset{
|
|
background:#fff5f5;
|
|
color:#c40000;
|
|
border:1px solid #ffd7d7;
|
|
}
|
|
|
|
.btn-reset:hover{
|
|
background:#ffeaea;
|
|
}
|
|
|
|
.btn-logout-alt{
|
|
background:transparent;
|
|
color:#666;
|
|
border:1px solid #ddd;
|
|
}
|
|
|
|
.btn-logout-alt:hover{
|
|
background:#fff1f1;
|
|
color:#c40000;
|
|
border-color:#fee2e2;
|
|
}
|
|
|
|
/* ===================================================== */
|
|
/* PERBAIKAN FINAL POPUP SWEET ALERT */
|
|
/* ===================================================== */
|
|
|
|
.swal-modern-popup{
|
|
width:430px !important;
|
|
border-radius:24px !important;
|
|
padding:0 !important;
|
|
overflow:hidden !important;
|
|
background:#ffffff !important;
|
|
box-shadow:0 20px 60px rgba(0,0,0,0.14) !important;
|
|
}
|
|
|
|
.swal2-html-container{
|
|
margin:0 !important;
|
|
padding:0 !important;
|
|
}
|
|
|
|
.swal-modern-header{
|
|
padding:24px 24px 18px;
|
|
background:linear-gradient(135deg,#c40000,#930000);
|
|
text-align:left;
|
|
}
|
|
|
|
.swal-modern-top{
|
|
display:flex;
|
|
align-items:center;
|
|
gap:14px;
|
|
}
|
|
|
|
.swal-modern-icon{
|
|
width:56px;
|
|
height:56px;
|
|
border-radius:16px;
|
|
background:rgba(255,255,255,0.14);
|
|
display:flex;
|
|
align-items:center;
|
|
justify-content:center;
|
|
flex-shrink:0;
|
|
}
|
|
|
|
.swal-modern-icon i{
|
|
width:26px;
|
|
height:26px;
|
|
color:white;
|
|
}
|
|
|
|
.swal-modern-title{
|
|
font-size:22px !important;
|
|
font-weight:700 !important;
|
|
color:white !important;
|
|
margin:0 !important;
|
|
padding:0 !important;
|
|
text-align:left !important;
|
|
}
|
|
|
|
.swal-modern-subtitle{
|
|
margin-top:4px;
|
|
font-size:13px;
|
|
line-height:1.5;
|
|
color:rgba(255,255,255,0.86);
|
|
text-align:left;
|
|
}
|
|
|
|
.swal-modern-body{
|
|
padding:22px 24px 10px;
|
|
}
|
|
|
|
.swal-label{
|
|
display:block;
|
|
text-align:left;
|
|
font-size:13px;
|
|
font-weight:600;
|
|
color:#374151;
|
|
margin-bottom:8px;
|
|
margin-top:14px;
|
|
}
|
|
|
|
.swal-label:first-child{
|
|
margin-top:0;
|
|
}
|
|
|
|
.swal2-input{
|
|
width:100% !important;
|
|
height:50px !important;
|
|
margin:0 !important;
|
|
border-radius:14px !important;
|
|
border:1px solid #e5e7eb !important;
|
|
background:#fafafa !important;
|
|
padding:0 16px !important;
|
|
font-size:14px !important;
|
|
color:#111827 !important;
|
|
transition:0.25s !important;
|
|
box-shadow:none !important;
|
|
}
|
|
|
|
.swal2-input:focus{
|
|
background:#ffffff !important;
|
|
border-color:#c40000 !important;
|
|
box-shadow:0 0 0 4px rgba(196,0,0,0.08) !important;
|
|
}
|
|
|
|
.swal2-input::placeholder{
|
|
color:#9ca3af !important;
|
|
}
|
|
|
|
.swal2-actions{
|
|
margin:0 !important;
|
|
padding:20px 24px 24px !important;
|
|
justify-content:flex-end !important;
|
|
gap:10px !important;
|
|
}
|
|
|
|
button.swal-btn-confirm{
|
|
background:#c40000 !important;
|
|
color:white !important;
|
|
border:none !important;
|
|
border-radius:14px !important;
|
|
height:46px !important;
|
|
padding:0 22px !important;
|
|
font-size:13px !important;
|
|
font-weight:600 !important;
|
|
box-shadow:none !important;
|
|
}
|
|
|
|
button.swal-btn-confirm:hover{
|
|
background:#a70000 !important;
|
|
}
|
|
|
|
button.swal-btn-cancel{
|
|
background:#f3f4f6 !important;
|
|
color:#374151 !important;
|
|
border:none !important;
|
|
border-radius:14px !important;
|
|
height:46px !important;
|
|
padding:0 22px !important;
|
|
font-size:13px !important;
|
|
font-weight:600 !important;
|
|
box-shadow:none !important;
|
|
}
|
|
|
|
.swal2-styled:focus{
|
|
box-shadow:none !important;
|
|
}
|
|
|
|
/* ===================================================== */
|
|
/* OTP */
|
|
/* ===================================================== */
|
|
|
|
.otp-wrapper{
|
|
display:flex;
|
|
justify-content:center;
|
|
gap:10px;
|
|
margin-top:6px;
|
|
}
|
|
|
|
.otp-input{
|
|
width:48px !important;
|
|
height:54px !important;
|
|
border-radius:14px !important;
|
|
border:1px solid #e5e7eb !important;
|
|
background:#fafafa !important;
|
|
text-align:center;
|
|
font-size:22px !important;
|
|
font-weight:700 !important;
|
|
color:#111827 !important;
|
|
transition:0.25s !important;
|
|
}
|
|
|
|
.otp-input:focus{
|
|
border-color:#c40000 !important;
|
|
background:#ffffff !important;
|
|
box-shadow:0 0 0 4px rgba(196,0,0,0.08) !important;
|
|
}
|
|
|
|
/* ===================================================== */
|
|
/* PASSWORD WARNING MODERN */
|
|
/* ===================================================== */
|
|
|
|
.password-alert{
|
|
margin-top:14px;
|
|
background:#fff7f7;
|
|
border:1px solid #ffe0e0;
|
|
border-radius:16px;
|
|
padding:12px 14px;
|
|
display:flex;
|
|
align-items:flex-start;
|
|
gap:12px;
|
|
}
|
|
|
|
.password-alert-icon{
|
|
width:34px;
|
|
height:34px;
|
|
border-radius:10px;
|
|
background:#ffeaea;
|
|
display:flex;
|
|
align-items:center;
|
|
justify-content:center;
|
|
flex-shrink:0;
|
|
}
|
|
|
|
.password-alert-icon i{
|
|
width:16px;
|
|
height:16px;
|
|
color:#c40000;
|
|
}
|
|
|
|
.password-alert-text{
|
|
text-align:left;
|
|
flex:1;
|
|
}
|
|
|
|
.password-alert-text h4{
|
|
font-size:12px;
|
|
font-weight:700;
|
|
color:#991b1b;
|
|
margin-bottom:2px;
|
|
line-height:1.3;
|
|
}
|
|
|
|
.password-alert-text p{
|
|
font-size:11px;
|
|
line-height:1.5;
|
|
color:#7f1d1d;
|
|
margin:0;
|
|
}
|
|
|
|
/* ============================= */
|
|
/* RESPONSIVE */
|
|
/* ============================= */
|
|
|
|
@media(max-width:600px){
|
|
.swal-modern-popup{
|
|
width:92% !important;
|
|
}
|
|
.swal-modern-header{
|
|
padding:24px 20px 18px;
|
|
}
|
|
.swal-modern-body{
|
|
padding:22px 20px 24px;
|
|
}
|
|
.swal2-actions{
|
|
padding:0 20px 22px !important;
|
|
}
|
|
.otp-input{
|
|
width:45px !important;
|
|
height:52px !important;
|
|
font-size:20px !important;
|
|
}
|
|
}
|
|
|
|
.alert-success{
|
|
background:#dcfce7;
|
|
color:#166534;
|
|
padding:14px;
|
|
border-radius:12px;
|
|
margin-bottom:22px;
|
|
font-size:13px;
|
|
display:flex;
|
|
align-items:center;
|
|
gap:10px;
|
|
}
|
|
|
|
</style>
|
|
</head>
|
|
<body>
|
|
|
|
<div class="sidebar">
|
|
<h2>Sistem TBC</h2>
|
|
<ul class="menu">
|
|
<li>
|
|
@if(session('role') !== 'super_admin')<li><a href="{{ url('/data-pasien') }}"><i data-lucide="users"></i> Data Pasien</a></li>@endif
|
|
<li>
|
|
<a href="{{ url('/data-pasien') }}">
|
|
<i data-lucide="users"></i>
|
|
Data Pasien
|
|
</a>
|
|
</li>
|
|
<li>
|
|
<a href="{{ url('/skrining') }}">
|
|
<i data-lucide="stethoscope"></i>
|
|
Skrining
|
|
</a>
|
|
</li>
|
|
@if(session('role') == 'super_admin')
|
|
<li>
|
|
<a href="{{ url('/kelola-admin') }}">
|
|
<i data-lucide="shield"></i>
|
|
Kelola Admin
|
|
</a>
|
|
</li>
|
|
<li>
|
|
<a href="{{ url('/riwayat-aktivitas') }}">
|
|
<i data-lucide="activity"></i>
|
|
Riwayat Aktivitas
|
|
</a>
|
|
</li>
|
|
@endif
|
|
<li class="active">
|
|
<a href="{{ url('/pengaturan-akun') }}">
|
|
<i data-lucide="user"></i>
|
|
Akun
|
|
</a>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
|
|
<div class="main-content">
|
|
<div class="header-wrapper">
|
|
<h1 class="page-title">Pengaturan Akun</h1>
|
|
</div>
|
|
|
|
<div class="card">
|
|
@if(session('success'))
|
|
<div class="alert-success">
|
|
<i data-lucide="check-circle" size="18"></i>
|
|
{{ session('success') }}
|
|
</div>
|
|
@endif
|
|
|
|
<div class="profile-header">
|
|
<div class="profile-icon">
|
|
<i data-lucide="user" size="35"></i>
|
|
</div>
|
|
<div class="profile-info">
|
|
<h3>{{ $petugas->nama_petugas ?? '-' }}</h3>
|
|
<p>
|
|
{{ session('role') == 'super_admin' ? 'Super Admin' : 'Admin' }}
|
|
Sistem TBC
|
|
</p>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="info-group">
|
|
<div class="info-label">ID Petugas</div>
|
|
<div class="info-value">{{ $petugas->id_petugas }}</div>
|
|
</div>
|
|
<div class="info-group">
|
|
<div class="info-label">Nama Lengkap</div>
|
|
<div class="info-value">{{ $petugas->nama_petugas ?? '-' }}</div>
|
|
</div>
|
|
<div class="info-group">
|
|
<div class="info-label">Email</div>
|
|
<div class="info-value">{{ $petugas->email ?? '-' }}</div>
|
|
</div>
|
|
<div class="info-group">
|
|
<div class="info-label">Role</div>
|
|
<div class="info-value">
|
|
{{ session('role') == 'super_admin' ? 'Super Admin' : 'Admin' }}
|
|
</div>
|
|
</div>
|
|
|
|
<div class="action-buttons">
|
|
<button type="button" class="btn-action btn-update" onclick="updateData()">
|
|
<i data-lucide="pencil"></i>
|
|
Update
|
|
</button>
|
|
<button type="button" class="btn-action btn-reset" onclick="resetPassword()">
|
|
<i data-lucide="lock"></i>
|
|
Reset Password
|
|
</button>
|
|
<button type="button" class="btn-action btn-logout-alt" onclick="logout()">
|
|
<i data-lucide="log-out"></i>
|
|
Logout
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<form id="update-form" action="{{ url('/pengaturan-akun/update') }}" method="POST" style="display:none;">
|
|
@csrf
|
|
<input type="hidden" name="nama_petugas" id="update_nama">
|
|
<input type="hidden" name="email" id="update_email">
|
|
<input type="hidden" name="password" id="update_password">
|
|
</form>
|
|
|
|
<form id="logout-form" action="{{ route('logout') }}" method="POST" style="display:none;">
|
|
@csrf
|
|
</form>
|
|
|
|
<script>
|
|
lucide.createIcons();
|
|
|
|
async function updateData(){
|
|
const { value: formValues } = await Swal.fire({
|
|
html:`
|
|
<div class="swal-modern-header">
|
|
<div class="swal-modern-top">
|
|
<div class="swal-modern-icon">
|
|
<i data-lucide="user-cog"></i>
|
|
</div>
|
|
<div>
|
|
<div class="swal-modern-title">Update Data</div>
|
|
<div class="swal-modern-subtitle">Perbarui informasi akun Anda</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="swal-modern-body">
|
|
<label class="swal-label">Nama Lengkap</label>
|
|
<input id="swal-nama" class="swal2-input" placeholder="Masukkan nama lengkap" value="{{ $petugas->nama_petugas }}">
|
|
<label class="swal-label">Email</label>
|
|
<input id="swal-email" class="swal2-input" placeholder="Masukkan email" value="{{ $petugas->email }}">
|
|
<div class="password-alert">
|
|
<div class="password-alert-icon">
|
|
<i data-lucide="info"></i>
|
|
</div>
|
|
<div class="password-alert-text">
|
|
<h4>Informasi Akun</h4>
|
|
<p>Gunakan email aktif untuk menerima notifikasi dan pemulihan akun.</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
`,
|
|
showCancelButton:true,
|
|
confirmButtonText:'Simpan',
|
|
cancelButtonText:'Batal',
|
|
reverseButtons:true,
|
|
customClass:{
|
|
popup:'swal-modern-popup',
|
|
confirmButton:'swal-btn-confirm',
|
|
cancelButton:'swal-btn-cancel'
|
|
},
|
|
buttonsStyling:false,
|
|
didOpen:() => { lucide.createIcons(); },
|
|
preConfirm:() => {
|
|
const nama = document.getElementById('swal-nama').value;
|
|
const email = document.getElementById('swal-email').value;
|
|
if(!nama || !email){
|
|
Swal.showValidationMessage('Nama dan Email wajib diisi');
|
|
return false;
|
|
}
|
|
return { nama:nama, email:email }
|
|
}
|
|
});
|
|
|
|
if(formValues){
|
|
document.getElementById('update_nama').value = formValues.nama;
|
|
document.getElementById('update_email').value = formValues.email;
|
|
document.getElementById('update_password').value = '';
|
|
document.getElementById('update-form').submit();
|
|
}
|
|
}
|
|
|
|
// FUNGSI GANTI PASSWORD (DENGAN VERIFIKASI PASSWORD SAAT INI)
|
|
async function resetPassword(){
|
|
const { value: step1, isConfirmed: confirmedStep1 } = await Swal.fire({
|
|
html:`
|
|
<div class="swal-modern-header">
|
|
<div class="swal-modern-top">
|
|
<div class="swal-modern-icon"><i data-lucide="lock-keyhole"></i></div>
|
|
<div>
|
|
<div class="swal-modern-title">Ganti Password</div>
|
|
<div class="swal-modern-subtitle">Masukkan password lama dan baru</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="swal-modern-body">
|
|
<label class="swal-label">Password Saat Ini</label>
|
|
<input id="current-password" type="password" class="swal2-input" placeholder="Wajib diisi">
|
|
|
|
<div style="text-align: right; margin-top: 8px; margin-bottom: 15px;">
|
|
<a href="javascript:void(0)" onclick="handleLupaPassword()" style="color: #c40000; font-size: 12px; font-weight: 600; text-decoration: none;">Lupa Password?</a>
|
|
</div>
|
|
|
|
<label class="swal-label">Password Baru</label>
|
|
<input id="new-password-direct" type="password" class="swal2-input" placeholder="Minimal 8 karakter">
|
|
|
|
<label class="swal-label">Konfirmasi Password Baru</label>
|
|
<input id="confirm-password-direct" type="password" class="swal2-input" placeholder="Ulangi password baru">
|
|
</div>
|
|
`,
|
|
showCancelButton:true,
|
|
confirmButtonText:'Simpan Perubahan',
|
|
cancelButtonText:'Batal',
|
|
reverseButtons:true,
|
|
customClass:{
|
|
popup:'swal-modern-popup',
|
|
confirmButton:'swal-btn-confirm',
|
|
cancelButton:'swal-btn-cancel'
|
|
},
|
|
buttonsStyling:false,
|
|
didOpen:() => { lucide.createIcons(); },
|
|
preConfirm:() => {
|
|
const current = document.getElementById('current-password').value;
|
|
const pass = document.getElementById('new-password-direct').value;
|
|
const confirm = document.getElementById('confirm-password-direct').value;
|
|
|
|
if(!current){
|
|
Swal.showValidationMessage('Password saat ini wajib diisi');
|
|
return false;
|
|
}
|
|
if(pass.length < 8){
|
|
Swal.showValidationMessage('Password baru minimal 8 karakter');
|
|
return false;
|
|
}
|
|
if(pass !== confirm){
|
|
Swal.showValidationMessage('Konfirmasi password tidak cocok');
|
|
return false;
|
|
}
|
|
return { current: current, pass: pass };
|
|
}
|
|
});
|
|
|
|
if(!confirmedStep1) return;
|
|
|
|
Swal.fire({
|
|
title:'Memproses...',
|
|
allowOutsideClick:false,
|
|
showConfirmButton:false,
|
|
customClass:{ popup:'swal-modern-popup' },
|
|
didOpen:() => { Swal.showLoading(); }
|
|
});
|
|
|
|
try {
|
|
const response = await fetch('/pengaturan-akun/update-password-langsung', {
|
|
method:'POST',
|
|
headers:{
|
|
'Content-Type':'application/json',
|
|
'X-CSRF-TOKEN':'{{ csrf_token() }}',
|
|
'Accept': 'application/json'
|
|
},
|
|
body:JSON.stringify({
|
|
current_password: step1.current,
|
|
password: step1.pass
|
|
})
|
|
});
|
|
|
|
const result = await response.json();
|
|
await showFinalResult(result);
|
|
|
|
} catch (error) {
|
|
await showFinalResult({
|
|
success: false,
|
|
message: 'Gagal memproses permintaan ke server.'
|
|
});
|
|
}
|
|
}
|
|
|
|
// FUNGSI LUPA PASSWORD (ALUR OTP)
|
|
async function handleLupaPassword() {
|
|
Swal.close();
|
|
const { value: akun } = await Swal.fire({
|
|
html:`
|
|
<div class="swal-modern-header">
|
|
<div class="swal-modern-top">
|
|
<div class="swal-modern-icon"><i data-lucide="shield-check"></i></div>
|
|
<div>
|
|
<div class="swal-modern-title">Reset Password</div>
|
|
<div class="swal-modern-subtitle">Verifikasi akun melalui email</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="swal-modern-body">
|
|
<label class="swal-label">ID Petugas</label>
|
|
<input id="reset-id" class="swal2-input" placeholder="Masukkan ID Petugas">
|
|
<label class="swal-label">Email</label>
|
|
<input id="reset-email" class="swal2-input" placeholder="Masukkan Email">
|
|
</div>
|
|
`,
|
|
showCancelButton:true,
|
|
confirmButtonText:'Kirim OTP',
|
|
cancelButtonText:'Batal',
|
|
reverseButtons:true,
|
|
customClass:{
|
|
popup:'swal-modern-popup',
|
|
confirmButton:'swal-btn-confirm',
|
|
cancelButton:'swal-btn-cancel'
|
|
},
|
|
buttonsStyling:false,
|
|
didOpen:() => { lucide.createIcons(); },
|
|
preConfirm:() => {
|
|
const idPetugas = document.getElementById('reset-id').value;
|
|
const email = document.getElementById('reset-email').value;
|
|
if(!idPetugas || !email){
|
|
Swal.showValidationMessage('ID dan Email wajib diisi');
|
|
return false;
|
|
}
|
|
return { id_petugas:idPetugas, email:email };
|
|
}
|
|
});
|
|
|
|
if(!akun) return;
|
|
|
|
Swal.fire({
|
|
title:'Mengirim OTP...',
|
|
allowOutsideClick:false,
|
|
showConfirmButton:false,
|
|
customClass:{ popup:'swal-modern-popup' },
|
|
didOpen:() => { Swal.showLoading(); }
|
|
});
|
|
|
|
try {
|
|
const kirimOtp = await fetch('/pengaturan-akun/kirim-otp', {
|
|
method:'POST',
|
|
headers:{
|
|
'Content-Type':'application/json',
|
|
'X-CSRF-TOKEN':'{{ csrf_token() }}'
|
|
},
|
|
body:JSON.stringify({ id_petugas:akun.id_petugas, email:akun.email })
|
|
});
|
|
|
|
const otpResult = await kirimOtp.json();
|
|
if(!otpResult.success){
|
|
await showFinalResult(otpResult);
|
|
return;
|
|
}
|
|
|
|
let otpValid = false;
|
|
let finalOtp = '';
|
|
while(!otpValid){
|
|
const otpInput = await Swal.fire({
|
|
html:`
|
|
<div class="swal-modern-header">
|
|
<div class="swal-modern-top">
|
|
<div class="swal-modern-icon"><i data-lucide="mail-check"></i></div>
|
|
<div>
|
|
<div class="swal-modern-title">Verifikasi OTP</div>
|
|
<div class="swal-modern-subtitle">Masukkan 6 digit kode OTP</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="swal-modern-body">
|
|
<div class="otp-wrapper">
|
|
<input type="text" maxlength="1" class="otp-input" id="otp1">
|
|
<input type="text" maxlength="1" class="otp-input" id="otp2">
|
|
<input type="text" maxlength="1" class="otp-input" id="otp3">
|
|
<input type="text" maxlength="1" class="otp-input" id="otp4">
|
|
<input type="text" maxlength="1" class="otp-input" id="otp5">
|
|
<input type="text" maxlength="1" class="otp-input" id="otp6">
|
|
</div>
|
|
</div>
|
|
`,
|
|
showCancelButton:true,
|
|
confirmButtonText:'Verifikasi',
|
|
cancelButtonText:'Batal',
|
|
reverseButtons:true,
|
|
customClass:{
|
|
popup:'swal-modern-popup',
|
|
confirmButton:'swal-btn-confirm',
|
|
cancelButton:'swal-btn-cancel'
|
|
},
|
|
buttonsStyling:false,
|
|
didOpen:() => {
|
|
lucide.createIcons();
|
|
const inputs = document.querySelectorAll('.otp-input');
|
|
inputs[0].focus();
|
|
inputs.forEach((input, index) => {
|
|
input.addEventListener('input', (e) => {
|
|
e.target.value = e.target.value.replace(/[^0-9]/g,'');
|
|
if(e.target.value.length === 1 && inputs[index + 1]) inputs[index + 1].focus();
|
|
});
|
|
input.addEventListener('keydown', (e) => {
|
|
if(e.key === 'Backspace' && !input.value && inputs[index - 1]) inputs[index - 1].focus();
|
|
});
|
|
});
|
|
},
|
|
preConfirm:() => {
|
|
const kodeOtp = Array.from({length: 6}, (_, i) => document.getElementById(`otp${i+1}`).value).join('');
|
|
if(kodeOtp.length < 6) { Swal.showValidationMessage('OTP tidak lengkap'); return false; }
|
|
return kodeOtp;
|
|
}
|
|
});
|
|
|
|
if(!otpInput.isConfirmed) return;
|
|
const cekOtp = await fetch('/pengaturan-akun/verifikasi-otp', {
|
|
method:'POST',
|
|
headers:{
|
|
'Content-Type':'application/json',
|
|
'X-CSRF-TOKEN':'{{ csrf_token() }}'
|
|
},
|
|
body:JSON.stringify({
|
|
id_petugas:akun.id_petugas,
|
|
email:akun.email,
|
|
otp:otpInput.value,
|
|
cek_otp:true
|
|
})
|
|
});
|
|
const otpCheck = await cekOtp.json();
|
|
|
|
if(otpCheck.success){
|
|
otpValid = true;
|
|
finalOtp = otpInput.value;
|
|
} else {
|
|
await Swal.fire({
|
|
icon:'error', title:'OTP Salah', text: otpCheck.message,
|
|
confirmButtonText:'Coba Lagi',
|
|
customClass:{ popup:'swal-modern-popup', confirmButton:'swal-btn-confirm' },
|
|
buttonsStyling:false
|
|
});
|
|
}
|
|
}
|
|
|
|
const { value: passwordBaru } = await Swal.fire({
|
|
html:`
|
|
<div class="swal-modern-header">
|
|
<div class="swal-modern-top">
|
|
<div class="swal-modern-icon"><i data-lucide="lock-keyhole"></i></div>
|
|
<div>
|
|
<div class="swal-modern-title">Password Baru</div>
|
|
<div class="swal-modern-subtitle">Buat password baru yang aman</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="swal-modern-body">
|
|
<label class="swal-label">Password Baru</label>
|
|
<input id="new-password" type="password" class="swal2-input" placeholder="Masukkan Password Baru">
|
|
<label class="swal-label">Konfirmasi Password</label>
|
|
<input id="confirm-password" type="password" class="swal2-input" placeholder="Konfirmasi Password">
|
|
</div>
|
|
`,
|
|
showCancelButton:true,
|
|
confirmButtonText:'Simpan',
|
|
cancelButtonText:'Batal',
|
|
reverseButtons:true,
|
|
customClass:{
|
|
popup:'swal-modern-popup',
|
|
confirmButton:'swal-btn-confirm',
|
|
cancelButton:'swal-btn-cancel'
|
|
},
|
|
buttonsStyling:false,
|
|
didOpen:() => { lucide.createIcons(); },
|
|
preConfirm:() => {
|
|
const pass = document.getElementById('new-password').value;
|
|
const confirm = document.getElementById('confirm-password').value;
|
|
if(pass.length < 8) { Swal.showValidationMessage('Minimal 8 karakter'); return false; }
|
|
if(pass !== confirm) { Swal.showValidationMessage('Konfirmasi tidak cocok'); return false; }
|
|
return { password:pass };
|
|
}
|
|
});
|
|
|
|
if(!passwordBaru) return;
|
|
|
|
const simpanPassword = await fetch('/pengaturan-akun/verifikasi-otp', {
|
|
method:'POST',
|
|
headers:{
|
|
'Content-Type':'application/json',
|
|
'X-CSRF-TOKEN':'{{ csrf_token() }}'
|
|
},
|
|
body:JSON.stringify({
|
|
id_petugas:akun.id_petugas,
|
|
email:akun.email,
|
|
otp:finalOtp,
|
|
password:passwordBaru.password
|
|
})
|
|
});
|
|
const resultPassword = await simpanPassword.json();
|
|
await showFinalResult(resultPassword);
|
|
|
|
} catch (error) {
|
|
Swal.fire('Error', 'Terjadi kesalahan sistem', 'error');
|
|
}
|
|
}
|
|
|
|
// FUNGSI HASIL AKHIR (SUCCESS/WARNING)
|
|
async function showFinalResult(result) {
|
|
return Swal.fire({
|
|
html: `
|
|
<div style="padding:28px 24px 10px; text-align:center;">
|
|
<div style="width:68px; height:68px; margin:0 auto 18px; border-radius:20px; display:flex; align-items:center; justify-content:center; background:${result.success ? '#ecfdf3' : '#fff1f2'};">
|
|
<i data-lucide="${result.success ? 'check-check' : 'shield-alert'}" style="width:30px; height:30px; color:${result.success ? '#16a34a' : '#dc2626'};"></i>
|
|
</div>
|
|
<h2 style="font-size:20px; font-weight:700; color:#111827; margin-bottom:8px;">
|
|
${result.success ? 'Berhasil' : 'Peringatan'}
|
|
</h2>
|
|
<p style="font-size:13px; line-height:1.7; color:#6b7280; margin:0;">
|
|
${result.message}
|
|
</p>
|
|
</div>
|
|
`,
|
|
confirmButtonText: result.success ? 'Selesai' : 'Coba Lagi',
|
|
customClass:{ popup:'swal-modern-popup', confirmButton:'swal-btn-confirm' },
|
|
buttonsStyling:false,
|
|
didOpen:() => { lucide.createIcons(); }
|
|
}).then(() => {
|
|
if(result.success) window.location.reload();
|
|
});
|
|
}
|
|
|
|
function logout(){
|
|
Swal.fire({
|
|
html:`
|
|
<div class="swal-modern-header">
|
|
<div class="swal-modern-top">
|
|
<div class="swal-modern-icon"><i data-lucide="log-out"></i></div>
|
|
<div>
|
|
<div class="swal-modern-title">Logout Akun</div>
|
|
<div class="swal-modern-subtitle">Keluar dari Sistem TBC</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="swal-modern-body">
|
|
<p style="font-size:13px; color:#6b7280; text-align:center;">Pastikan aktivitas telah selesai sebelum keluar.</p>
|
|
</div>
|
|
`,
|
|
showCancelButton:true,
|
|
confirmButtonText:'Ya, Logout',
|
|
cancelButtonText:'Batal',
|
|
reverseButtons:true,
|
|
customClass:{
|
|
popup:'swal-modern-popup',
|
|
confirmButton:'swal-btn-confirm',
|
|
cancelButton:'swal-btn-cancel'
|
|
},
|
|
buttonsStyling:false,
|
|
didOpen:() => { lucide.createIcons(); }
|
|
}).then((result) => {
|
|
if(result.isConfirmed) document.getElementById('logout-form').submit();
|
|
});
|
|
}
|
|
</script>
|
|
</body>
|
|
</html> |