feature: update message for login feature
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
@props(['id', 'title' => 'Đã xảy ra lỗi', 'message' => '', 'buttonText' => 'Đóng'])
|
||||
@props(['id', 'title' => 'Đã xảy ra lỗi', 'message' => '', 'buttonText' => 'Đóng', 'onclick' => null])
|
||||
|
||||
<div id="{{ $id }}" class="fixed inset-0 z-[100] hidden flex-col items-center justify-center outline-none opacity-0 transition-opacity duration-300" aria-labelledby="modal-title-{{ $id }}" role="dialog" aria-modal="true">
|
||||
<div class="absolute inset-0 bg-slate-900/60 backdrop-blur-sm cursor-pointer" onclick="closeModal('{{ $id }}')"></div>
|
||||
@@ -14,7 +14,7 @@
|
||||
<p class="text-slate-500 text-sm leading-relaxed">{{ $message }}</p>
|
||||
</div>
|
||||
<div class="px-6 py-4 bg-slate-50 flex justify-center border-t border-slate-100">
|
||||
<button type="button" onclick="closeModal('{{ $id }}')" class="w-full sm:w-auto px-6 py-2 bg-red-600 hover:bg-red-700 text-white text-sm font-semibold rounded-lg shadow-sm transition-all duration-200 cursor-pointer text-center">
|
||||
<button type="button" onclick="{{ $onclick ?? "closeModal('{$id}')" }}" class="w-full sm:w-auto px-6 py-2 bg-red-600 hover:bg-red-700 text-white text-sm font-semibold rounded-lg shadow-sm transition-all duration-200 cursor-pointer text-center">
|
||||
{{ $buttonText }}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
@props(['id', 'title' => 'Thông tin', 'message' => '', 'buttonText' => 'Đóng'])
|
||||
@props(['id', 'title' => 'Thông tin', 'message' => '', 'buttonText' => 'Đóng', 'onclick' => null])
|
||||
|
||||
<div id="{{ $id }}" class="fixed inset-0 z-[100] hidden flex-col items-center justify-center outline-none opacity-0 transition-opacity duration-300" aria-labelledby="modal-title-{{ $id }}" role="dialog" aria-modal="true">
|
||||
<div class="absolute inset-0 bg-slate-900/60 backdrop-blur-sm cursor-pointer" onclick="closeModal('{{ $id }}')"></div>
|
||||
@@ -14,7 +14,7 @@
|
||||
<p class="text-slate-500 text-sm leading-relaxed">{{ $message }}</p>
|
||||
</div>
|
||||
<div class="px-6 py-4 bg-slate-50 flex justify-center border-t border-slate-100">
|
||||
<button type="button" onclick="closeModal('{{ $id }}')" class="w-full sm:w-auto px-6 py-2 bg-blue-600 hover:bg-blue-700 text-white text-sm font-semibold rounded-lg shadow-sm transition-all duration-200 cursor-pointer text-center">
|
||||
<button type="button" onclick="{{ $onclick ?? "closeModal('{$id}')" }}" class="w-full sm:w-auto px-6 py-2 bg-blue-600 hover:bg-blue-700 text-white text-sm font-semibold rounded-lg shadow-sm transition-all duration-200 cursor-pointer text-center">
|
||||
{{ $buttonText }}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
@props(['id', 'title' => 'Cảnh báo', 'message' => '', 'buttonText' => 'Đã hiểu'])
|
||||
@props(['id', 'title' => 'Cảnh báo', 'message' => '', 'buttonText' => 'Đã hiểu', 'onclick' => null])
|
||||
|
||||
<div id="{{ $id }}" class="fixed inset-0 z-[100] hidden flex-col items-center justify-center outline-none opacity-0 transition-opacity duration-300" aria-labelledby="modal-title-{{ $id }}" role="dialog" aria-modal="true">
|
||||
<div class="absolute inset-0 bg-slate-900/60 backdrop-blur-sm cursor-pointer" onclick="closeModal('{{ $id }}')"></div>
|
||||
@@ -14,7 +14,7 @@
|
||||
<p class="text-slate-500 text-sm leading-relaxed">{{ $message }}</p>
|
||||
</div>
|
||||
<div class="px-6 py-4 bg-slate-50 flex justify-center border-t border-slate-100">
|
||||
<button type="button" onclick="closeModal('{{ $id }}')" class="w-full sm:w-auto px-6 py-2 bg-amber-500 hover:bg-amber-600 text-white text-sm font-semibold rounded-lg shadow-sm transition-all duration-200 cursor-pointer text-center">
|
||||
<button type="button" onclick="{{ $onclick ?? "closeModal('{$id}')" }}" class="w-full sm:w-auto px-6 py-2 bg-amber-500 hover:bg-amber-600 text-white text-sm font-semibold rounded-lg shadow-sm transition-all duration-200 cursor-pointer text-center">
|
||||
{{ $buttonText }}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -65,7 +65,7 @@
|
||||
|
||||
<!-- Form -->
|
||||
<div class="w-full max-w-[380px] mx-auto flex-1 relative z-10">
|
||||
<form action="{{ route('login') }}" method="POST" class="space-y-5">
|
||||
<form action="{{ route('login') }}" method="POST" class="space-y-5" novalidate>
|
||||
@csrf
|
||||
|
||||
<div class="min-h-[40px] flex items-center justify-center transition-all duration-300" aria-live="polite">
|
||||
@@ -180,5 +180,91 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Dialogs -->
|
||||
@if(session('dialog_error_permission'))
|
||||
<x-error-dialog id="modal-error-permission" title="Truy cập bị từ chối" message="{{ session('dialog_error_permission') }}" buttonText="Đồng ý" />
|
||||
@endif
|
||||
|
||||
@if(session('session_expired'))
|
||||
<x-warning-dialog id="modal-session-expired" title="Phiên làm việc hết hạn" message="Phiên đăng nhập đã hết hạn. Vui lòng đăng nhập lại." buttonText="OK" onclick="handleSessionExpiredOk()" />
|
||||
@endif
|
||||
|
||||
@if(session('dialog_first_login'))
|
||||
<x-info-dialog id="modal-first-login" title="Yêu cầu đổi mật khẩu" message="Vui lòng đổi mật khẩu trước khi tiếp tục sử dụng hệ thống." buttonText="OK" onclick="handleFirstLoginOk()" />
|
||||
@endif
|
||||
|
||||
@if(session('dialog_error_brute_force'))
|
||||
<x-error-dialog id="modal-error-brute-force" title="Tài khoản bị khóa" message="{{ session('dialog_error_brute_force') }}" buttonText="Đồng ý" />
|
||||
@endif
|
||||
|
||||
<script>
|
||||
window.openModal = function(id) {
|
||||
const modal = document.getElementById(id);
|
||||
if (!modal) return;
|
||||
document.body.style.overflow = 'hidden';
|
||||
modal.classList.remove('hidden');
|
||||
modal.classList.add('flex');
|
||||
requestAnimationFrame(() => {
|
||||
modal.classList.remove('opacity-0');
|
||||
modal.classList.add('opacity-100');
|
||||
const panel = modal.querySelector('.modal-panel');
|
||||
if (panel) {
|
||||
panel.classList.remove('scale-95', 'translate-y-4');
|
||||
panel.classList.add('scale-100', 'translate-y-0');
|
||||
}
|
||||
});
|
||||
modal.setAttribute('tabindex', '-1');
|
||||
modal.focus();
|
||||
const escHandler = function(e) {
|
||||
if (e.key === 'Escape') {
|
||||
closeModal(id);
|
||||
modal.removeEventListener('keydown', escHandler);
|
||||
}
|
||||
};
|
||||
modal.addEventListener('keydown', escHandler);
|
||||
};
|
||||
|
||||
window.closeModal = function(id) {
|
||||
const modal = document.getElementById(id);
|
||||
if (!modal) return;
|
||||
modal.classList.remove('opacity-100');
|
||||
modal.classList.add('opacity-0');
|
||||
const panel = modal.querySelector('.modal-panel');
|
||||
if (panel) {
|
||||
panel.classList.remove('scale-100', 'translate-y-0');
|
||||
panel.classList.add('scale-95', 'translate-y-4');
|
||||
}
|
||||
setTimeout(() => {
|
||||
modal.classList.add('hidden');
|
||||
modal.classList.remove('flex');
|
||||
document.body.style.overflow = '';
|
||||
}, 300);
|
||||
};
|
||||
|
||||
window.handleSessionExpiredOk = function() {
|
||||
closeModal('modal-session-expired');
|
||||
window.location.href = "{{ route('login') }}";
|
||||
};
|
||||
|
||||
window.handleFirstLoginOk = function() {
|
||||
closeModal('modal-first-login');
|
||||
window.location.href = "{{ route('user.change_password') }}";
|
||||
};
|
||||
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
@if(session('dialog_error_permission'))
|
||||
openModal('modal-error-permission');
|
||||
@endif
|
||||
@if(session('session_expired'))
|
||||
openModal('modal-session-expired');
|
||||
@endif
|
||||
@if(session('dialog_first_login'))
|
||||
openModal('modal-first-login');
|
||||
@endif
|
||||
@if(session('dialog_error_brute_force'))
|
||||
openModal('modal-error-brute-force');
|
||||
@endif
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -261,13 +261,13 @@
|
||||
<!-- All Case Modals/Toasts rendered as Reusable components -->
|
||||
|
||||
<!-- Case 1: Login failed -->
|
||||
<x-toast id="toast-case-1" type="error" message="Đăng nhập thất bại. Vui lòng kiểm tra lại Email hoặc Mật khẩu." />
|
||||
<x-toast id="toast-case-1" type="error" message="Thông tin đăng nhập không đúng. Vui lòng nhập lại" />
|
||||
|
||||
<!-- Case 2: Access denied -->
|
||||
<x-error-dialog id="modal-case-2" title="Truy cập bị từ chối" message="Tài khoản của bạn không có quyền truy cập vào trang quản trị này. Vui lòng liên hệ với quản trị viên nếu đây là một sự nhầm lẫn." buttonText="Đồng ý" />
|
||||
<x-error-dialog id="modal-case-2" title="Truy cập bị từ chối" message="Bạn không có quyền truy cập. Vui lòng liên hệ quản trị viên" buttonText="Đồng ý" />
|
||||
|
||||
<!-- Case 3: First login (change password required) -->
|
||||
<x-info-dialog id="modal-case-3" title="Yêu cầu đổi mật khẩu" message="Chào mừng bạn đến với hệ thống Thankcard! Đây là lần đầu tiên bạn đăng nhập, vui lòng đổi mật khẩu mới để tiếp tục sử dụng hệ thống." buttonText="Đổi mật khẩu ngay" />
|
||||
<x-info-dialog id="modal-case-3" title="Yêu cầu đổi mật khẩu" message="Vui lòng đổi mật khẩu trước khi tiếp tục sử dụng hệ thống." buttonText="OK" />
|
||||
|
||||
<!-- Case 4: Delete user confirmation -->
|
||||
<x-confirm-dialog id="modal-case-4" title="Xóa người dùng" message="Bạn có chắc chắn muốn xóa tài khoản của nhân viên Nguyễn Văn A (MSNV: NV0001)? Hành động này không thể hoàn tác và tất cả dữ liệu liên quan sẽ bị xóa." confirmText="Xóa vĩnh viễn" cancelText="Hủy bỏ" type="danger" />
|
||||
|
||||
@@ -2,54 +2,60 @@
|
||||
@section('title', 'Đổi Mật Khẩu')
|
||||
|
||||
@section('content')
|
||||
<div class="form-container mt-10">
|
||||
<div class="form-header">
|
||||
<h3 class="form-header-title">Đổi Mật Khẩu</h3>
|
||||
<div class="max-w-[480px] mx-auto bg-white rounded-[24px] shadow-[0_10px_30px_rgba(15,23,42,0.05)] p-8 mt-6">
|
||||
<div class="text-center mb-8">
|
||||
<div class="w-12 h-12 bg-blue-50 text-[#3462f7] rounded-2xl flex items-center justify-center mx-auto mb-4">
|
||||
<svg class="w-6 h-6" fill="none" stroke="currentColor" stroke-width="2.2" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M15.75 5.25a3 3 0 013 3m3 0a6 6 0 01-7.029 5.912c-.563-.097-1.159.026-1.563.43L10.5 17.25H8.25v2.25H6v2.25H2.25v-2.818c0-.597.237-1.17.659-1.591l6.499-6.499c.404-.404.527-1 .43-1.563A6 6 0 1121.75 8.25z"/>
|
||||
</svg>
|
||||
</div>
|
||||
<h3 class="text-[20px] font-extrabold text-[#1a2b49]">Đổi mật khẩu</h3>
|
||||
<p class="text-[13px] text-gray-500 font-medium mt-1">Cập nhật mật khẩu mới để bảo vệ tài khoản</p>
|
||||
</div>
|
||||
|
||||
<form action="{{ route('user.update_password') }}" method="POST">
|
||||
@csrf
|
||||
<div class="form-body">
|
||||
<div class="space-y-6">
|
||||
@if(Auth::user()->first_login == \App\Models\User::FIRST_LOGIN_TRUE)
|
||||
<div class="mb-6 p-4 bg-orange-50 border border-orange-200 text-orange-800 rounded-lg text-sm font-medium leading-relaxed flex items-start gap-2 shadow-sm">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-6 h-6 shrink-0 text-orange-500 mt-0.5">
|
||||
<div class="p-4 bg-amber-50/70 border border-amber-100 text-amber-800 rounded-2xl text-xs font-medium leading-relaxed flex items-start gap-2 shadow-sm">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" class="w-5 h-5 shrink-0 text-amber-600">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z" />
|
||||
</svg>
|
||||
<span>Đây là lần đầu tiên bạn đăng nhập vào hệ thống. Để đảm bảo an toàn, hệ thống yêu cầu bạn đổi mật khẩu trước khi sử dụng các chức năng.</span>
|
||||
<span>Đây là lần đầu tiên bạn đăng nhập. Vui lòng đổi mật khẩu để tiếp tục sử dụng hệ thống.</span>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<div class="form-group">
|
||||
<label class="form-label" for="password">Mật khẩu mới <span class="text-red-500">*</span></label>
|
||||
<div class="form-input-group">
|
||||
<span class="form-input-icon">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-5 h-5">
|
||||
<div class="flex flex-col">
|
||||
<label class="text-[13px] font-bold text-gray-700 mb-1.5" for="password">Mật khẩu mới <span class="text-red-500">*</span></label>
|
||||
<div class="relative flex items-center">
|
||||
<span class="absolute left-4 text-gray-400">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" class="w-5 h-5">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M16.5 10.5V6.75a4.5 4.5 0 10-9 0V10.5m-2.812 10.5h14.625c.621 0 1.125-.504 1.125-1.125V11.25c0-.621-.504-1.125-1.125-1.125H3.75c-.621 0-1.125.504-1.125 1.125v7.875c0 .621.504 1.125 1.125 1.125z" />
|
||||
</svg>
|
||||
</span>
|
||||
<input type="password" name="password" id="password" class="form-input form-input-with-icon" required placeholder="Nhập mật khẩu mới">
|
||||
<input type="password" name="password" id="password" class="w-full h-[48px] pl-12 pr-4 bg-[#F8FAFC] border border-gray-200 rounded-xl outline-none text-[#1a2b49] text-[14px] placeholder-gray-400 focus:border-[#3462f7] focus:bg-white focus:ring-4 focus:ring-[#3462f7]/10 hover:border-gray-300 transition-all duration-200" required placeholder="Nhập mật khẩu mới">
|
||||
</div>
|
||||
@error('password')<span class="error-text">{{ $message }}</span>@enderror
|
||||
@error('password')<span class="text-red-500 text-[12px] font-semibold mt-1.5 block">{{ $message }}</span>@enderror
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="form-label" for="password_confirmation">Xác nhận lại mật khẩu mới <span class="text-red-500">*</span></label>
|
||||
<div class="form-input-group">
|
||||
<span class="form-input-icon">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-5 h-5">
|
||||
<div class="flex flex-col">
|
||||
<label class="text-[13px] font-bold text-gray-700 mb-1.5" for="password_confirmation">Xác nhận lại mật khẩu mới <span class="text-red-500">*</span></label>
|
||||
<div class="relative flex items-center">
|
||||
<span class="absolute left-4 text-gray-400">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" class="w-5 h-5">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M9 12.75L11.25 15 15 9.75M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
|
||||
</svg>
|
||||
</span>
|
||||
<input type="password" name="password_confirmation" id="password_confirmation" class="form-input form-input-with-icon" required placeholder="Nhập lại mật khẩu mới">
|
||||
<input type="password" name="password_confirmation" id="password_confirmation" class="w-full h-[48px] pl-12 pr-4 bg-[#F8FAFC] border border-gray-200 rounded-xl outline-none text-[#1a2b49] text-[14px] placeholder-gray-400 focus:border-[#3462f7] focus:bg-white focus:ring-4 focus:ring-[#3462f7]/10 hover:border-gray-300 transition-all duration-200" required placeholder="Nhập lại mật khẩu mới">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-footer">
|
||||
@if(Auth::user()->first_login != \App\Models\User::FIRST_LOGIN_TRUE)
|
||||
<a href="{{ route('user.dashboard') }}" class="btn-secondary">Hủy bỏ</a>
|
||||
@endif
|
||||
<button type="submit" class="btn-primary">Xác Nhận Đổi Mật Khẩu</button>
|
||||
<div class="flex items-center gap-3 pt-4">
|
||||
@if(Auth::user()->first_login != \App\Models\User::FIRST_LOGIN_TRUE)
|
||||
<a href="{{ route('user.dashboard') }}" class="cursor-pointer flex-1 flex items-center justify-center h-[46px] rounded-xl border border-gray-200 bg-white hover:bg-gray-50 text-gray-600 text-[14px] font-bold shadow-sm transition-all duration-200">Hủy bỏ</a>
|
||||
@endif
|
||||
<button type="submit" class="cursor-pointer flex-1 flex items-center justify-center h-[46px] rounded-xl bg-[#3462f7] hover:bg-[#254edb] text-white text-[14px] font-bold shadow-md shadow-blue-500/10 transition-all duration-200">Xác nhận đổi mật khẩu</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user