perling/resources/views/auth/signin.blade.php

148 lines
5.5 KiB
PHP

<!-- meta tags and other links -->
<!DOCTYPE html>
<html lang="en" data-theme="light">
<x-head/>
<link rel="stylesheet" href="{{ asset('assets/css/login/login.css') }}">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons/font/bootstrap-icons.css">
<body>
<div class="container">
<div class="login-card">
<div class="login-image">
<img src="{{ asset('assets/images/auth/monas.svg')}}" alt="Monumen Nasional" style="max-width: 100%; max-height: 500px;">
</div>
<!-- Right Section with Login Form -->
<div class="login-form">
<img src="{{ asset('assets/images/auth/logo-login.svg') }}" alt="Balai Sertifikasi Elektronik" class="logo">
<h1 class="text-login">Login</h1>
<p class="subtext">Silakan masuk menggunakan email/username</p>
<form id="login-form" action="#" method="POST" style="width: 100%;">
@csrf
<div class="form-group">
<input type="text" id="identifier" name="identifier" placeholder="Email atau Username" required>
</div>
<div class="form-group">
<div class="password-container">
<input type="password" id="password" name="password" placeholder="Kata Sandi" required>
<span class="password-toggle">
<i class="bi bi-eye"></i>
</span>
</div>
</div>
<div class="mb-2">
<small id="login-error" class="text-danger" style="display:none;"></small>
</div>
<button id="btn-login" type="submit" class="login-button">Login</button>
</form>
</div>
</div>
</div>
</body>
<x-script />
<script>
// Clear any leftover tokens on signin page
try {
localStorage.removeItem('auth_token');
localStorage.removeItem('auth_user');
} catch (e) {}
document.querySelector('.password-toggle').addEventListener('click', function() {
const passwordInput = document.getElementById('password');
const icon = this.querySelector('i');
if (passwordInput.type === 'password') {
passwordInput.type = 'text';
icon.className = 'bi bi-eye-slash';
} else {
passwordInput.type = 'password';
icon.className = 'bi bi-eye';
}
});
const form = document.getElementById('login-form');
const btn = document.getElementById('btn-login');
const errorBox = document.getElementById('login-error');
form.addEventListener('submit', async function (e) {
e.preventDefault();
errorBox.style.display = 'none';
errorBox.textContent = '';
const identifier = document.getElementById('identifier').value.trim();
const password = document.getElementById('password').value;
if (!identifier || !password) return;
// Validasi kompleksitas password (min 8, upper, lower, digit, special)
const strongPwd = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[^A-Za-z0-9]).{8,}$/;
if (!strongPwd.test(password)) {
errorBox.textContent = 'Password minimal 8 karakter dan harus mengandung huruf besar, huruf kecil, angka, dan simbol khusus.';
errorBox.style.display = 'inline';
return;
}
const originalText = btn.textContent;
btn.disabled = true;
btn.textContent = 'Memproses...';
try {
const resp = await fetch('{{ url('/api/auth/login') }}', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json',
},
body: JSON.stringify({
identifier: identifier,
password: password,
device_name: 'web-portal'
})
});
const data = await resp.json().catch(() => ({}));
if (!resp.ok || !data.success) {
throw new Error((data && (data.message || (data.errors && (data.errors.identifier?.[0] || data.errors.password?.[0])))) || 'Login gagal');
}
// Simpan token (Catatan: localStorage memiliki risiko XSS; gunakan hati-hati)
localStorage.setItem('auth_token', data.token);
localStorage.setItem('auth_user', JSON.stringify(data.user || {}));
// Start web session agar middleware permission berfungsi
const sessionResp = await fetch('{{ route('login.session') }}', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json',
'X-CSRF-TOKEN': document.querySelector('input[name=_token]').value,
},
body: JSON.stringify({ identifier, password })
});
if (!sessionResp.ok) {
throw new Error('Gagal membuat sesi login web');
}
// Redirect ke dashboard
window.location.href = '{{ route('dashboard.index') }}';
} catch (err) {
errorBox.textContent = err.message || 'Login gagal';
errorBox.style.display = 'inline';
} finally {
btn.disabled = false;
btn.textContent = originalText;
}
});
</script>
</html>