TIF_E41221524/resources/views/profil.blade.php

483 lines
28 KiB
PHP

<link rel="stylesheet" href="{{ asset('assets/css/style.css') }}">
<div class="d-flex" style="min-height:100vh;">
{{-- SIDEBAR --}}
@include('sidebar')
{{-- CONTENT --}}
<div class="flex-grow-1 p-4">
<div class="container-fluid">
<div class="main-body">
<nav aria-label="breadcrumb" class="main-breadcrumb">
<ol class="breadcrumb">
<li class="breadcrumb-item active" aria-current="page">
Profil & Manajemen Pengguna
</li>
</ol>
</nav>
<div class="container-fluid">
{{-- Notifikasi Error Global --}}
@if ($errors->any())
<div class="alert alert-danger alert-dismissible fade show" role="alert">
<strong>Gagal!</strong> Periksa kembali inputan Anda.
<ul>
@foreach ($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
@endif
{{-- Form Update Profil --}}
<form action="{{ route('profil.update') }}" method="POST" enctype="multipart/form-data">
@csrf
@method('PUT')
<div class="row gutters-sm">
{{-- KIRI: FOTO PROFIL --}}
<div class="col-md-4 mb-3">
<div class="card shadow-sm">
<div class="card-body text-center">
<div class="d-flex flex-column align-items-center">
{{-- Preview Foto Otomatis --}}
<img id="previewFoto"
src="{{ Auth::user()->foto ? asset('foto_profil/' . Auth::user()->foto) : asset('img/default-avatar.png') }}"
class="rounded-circle mb-2" width="150" height="150"
style="object-fit: cover; border: 3px solid #f8f9fc;">
<div class="mt-3 w-100 text-left">
<label for="foto" class="small text-muted">Ganti Foto Profil</label>
<input type="file" name="foto" id="foto"
class="form-control form-control-sm @error('foto') is-invalid @enderror"
accept="image/*" onchange="previewImage()">
@error('foto')
<div class="invalid-feedback">{{ $message }}</div>
@enderror
</div>
<div class="mt-3">
<h4>{{ Auth::user()->nama_lengkap }}</h4>
<span class="badge badge-info">{{ strtoupper(Auth::user()->role) }}</span>
</div>
</div>
</div>
</div>
</div>
{{-- KANAN: FORM DATA DIRI --}}
<div class="col-md-8">
<div class="card mb-3 shadow-sm border-0">
<div class="card-body">
{{-- Notifikasi Sukses --}}
@if (session('success'))
<div class="alert alert-success alert-dismissible fade show" role="alert">
<i class="fas fa-check-circle mr-2"></i> {{ session('success') }}
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
@endif
@if (session('info'))
<div class="alert alert-info alert-dismissible fade show" role="alert">
<i class="fas fa-info-circle mr-2"></i> {{ session('info') }}
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
@endif
<div class="row align-items-center">
<div class="col-sm-3"><strong>ID</strong></div>
<div class="col-sm-8 text-secondary">{{ Auth::user()->id }}</div>
<div class="col-sm-1 text-right"><i class="fas fa-lock text-muted"></i></div>
</div>
<hr>
<div class="row align-items-center">
<div class="col-sm-3"><strong>Username</strong></div>
<div class="col-sm-8">
{{-- Atribut 'readonly' membuat user tidak bisa mengetik, tapi data tetap terkirim --}}
<input type="text" name="username"
class="form-control form-control-sm bg-light @error('username') is-invalid @enderror"
value="{{ Auth::user()->username }}"
readonly>
</div>
{{-- Ikon diganti jadi gembok (fas fa-lock) agar user paham ini terkunci --}}
<div class="col-sm-1 text-right">
<i class="fas fa-lock text-muted"></i>
</div>
</div>
<hr>
<div class="row align-items-center">
<div class="col-sm-3"><strong>Password Baru</strong></div>
<div class="col-sm-8">
<input type="password" name="password" class="form-control form-control-sm"
placeholder="Kosongkan jika tidak ingin ganti password">
</div>
<div class="col-sm-1 text-right"><i class="fas fa-key text-primary"></i></div>
</div>
<hr>
<div class="row align-items-center">
<div class="col-sm-3"><strong>Nama Lengkap <span class="text-danger">*</span></strong></div>
<div class="col-sm-8">
<input type="text" name="nama_lengkap" class="form-control form-control-sm @error('nama_lengkap') is-invalid @enderror"
value="{{ old('nama_lengkap', Auth::user()->nama_lengkap) }}" required>
</div>
<div class="col-sm-1 text-right"><i class="fas fa-pencil-alt text-primary"></i></div>
</div>
<hr>
<div class="row align-items-center">
<div class="col-sm-3"><strong>Role</strong></div>
<div class="col-sm-8 text-secondary">{{ ucfirst(Auth::user()->role) }}</div>
<div class="col-sm-1 text-right"><i class="fas fa-lock text-muted"></i></div>
</div>
<div class="mt-4 text-right">
<button type="submit" class="btn btn-primary btn-sm px-4 shadow">
<i class="fas fa-save mr-1"></i> Simpan Semua Perubahan
</button>
</div>
</div>
</div>
</div>
</div>
</form>
</div>
{{-- Script Live Preview Gambar --}}
<script>
function previewImage() {
const foto = document.querySelector('#foto');
const imgPreview = document.querySelector('#previewFoto');
const oFReader = new FileReader();
oFReader.readAsDataURL(foto.files[0]);
oFReader.onload = function(oFREvent) {
imgPreview.src = oFREvent.target.result;
}
}
</script>
{{-- TABEL DATA PENGGUNA --}}
<div class="modal fade" id="userModal" tabindex="-1" role="dialog" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="modalTitle">Tambah Pengguna Baru</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<form id="userForm" method="POST">
@csrf
<div id="methodPlaceholder"></div>
<div class="modal-body">
<div class="form-group">
<label>Username</label>
<input type="text" name="username" id="username" class="form-control" required>
</div>
<div class="form-group">
<label>Nama Lengkap</label>
<input type="text" name="nama_lengkap" id="nama_lengkap" class="form-control" required>
</div>
<div class="form-group" id="passwordGroup">
<label>Password</label>
<input type="password" name="password" id="password" class="form-control">
</div>
<div class="form-group">
<label>Role</label>
<select name="role" id="role" class="form-control" required>
<option value="user">USER</option>
<option value="admin">ADMIN</option>
<option value="super admin">SUPER ADMIN</option>
</select>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Batal</button>
<button type="submit" id="btnSubmit" class="btn btn-success">Tambah Pengguna</button>
</div>
</form>
</div>
</div>
</div>
<div class="row mt-4">
<div class="col-12">
<div class="card shadow mb-4">
<div class="card-header py-3 bg-white d-flex justify-content-between align-items-center">
<h6 class="m-0 font-weight-bold text-primary"><i class="fas fa-users mr-2"></i> Daftar Seluruh Pengguna</h6>
<button type="button" class="btn btn-success btn-sm btn-tambah">
<i class="fas fa-plus"></i> Tambah User
</button>
</div>
<div class="card-body">
<div class="table-responsive">
<table class="table table-bordered table-hover" width="100%">
<thead class="bg-light">
<tr>
<th width="5%">ID</th>
<th>Username</th>
<th>Nama Lengkap</th>
<th>Role</th>
<th class="text-center" width="15%">Aksi</th>
</tr>
</thead>
<tbody>
@forelse ($users as $u)
<tr>
<td>{{ $u->id }}</td>
<td>{{ $u->username }}</td>
<td>{{ $u->nama_lengkap }}</td>
<td>
<span class="badge {{ $u->role == 'admin' ? 'badge-danger' : 'badge-primary' }}">
{{ strtoupper($u->role) }}
</span>
</td>
<td class="text-center">
<button class="btn btn-warning btn-sm btn-edit"
data-id="{{ $u->id }}"
data-username="{{ $u->username }}"
data-nama="{{ $u->nama_lengkap }}"
data-role="{{ $u->role }}">
<i class="fas fa-edit text-white"></i>
</button>
<button class="btn btn-danger btn-sm btn-hapus-modal"
data-id="{{ $u->id }}"
data-nama="{{ $u->nama_lengkap }}">
<i class="fas fa-trash"></i>
</button>
</td>
</tr>
@empty
<tr>
<td colspan="5" class="text-center">Data belum tersedia.</td>
</tr>
@endforelse
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
{{-- MODAL TAMBAH/EDIT USER --}}
<div class="modal fade" id="modalEditUser" tabindex="-1" role="dialog">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Edit Role Pengguna</h5>
</div>
<form id="formEditUser" method="POST">
@csrf
@method('PUT')
<div class="modal-body">
<div class="form-group">
<label>Username</label>
<input type="text" name="username" id="modal_username" class="form-control" readonly>
</div>
<div class="form-group">
<label>Nama Lengkap</label>
<input type="text" name="nama_lengkap" id="modal_nama" class="form-control" readonly>
</div>
<div class="form-group">
<label>Role</label>
<select name="role" id="modal_role" class="form-control">
<option value="user">USER</option>
<option value="admin">ADMIN</option>
<option value="super admin">SUPER ADMIN</option>
</select>
</div>
</div>
<div class="modal-footer">
<button type="submit" class="btn btn-primary">Simpan Perubahan</button>
</div>
</form>
</div>
</div>
</div>
{{-- MODAL HAPUS --}}
<div class="modal fade" id="deleteModal" tabindex="-1" role="dialog" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered" role="document">
<div class="modal-content text-center p-4">
<div class="modal-body">
<div class="mb-3">
<div style="font-size: 50px; color: #ffbc8e; border: 4px solid #ffbc8e; border-radius: 50%; width: 100px; height: 100px; display: flex; align-items: center; justify-content: center; margin: 0 auto;">!</div>
</div>
<h2 class="font-weight-bold">Hapus User?</h2>
<p class="text-muted">Data user <b id="del_nama"></b> tidak dapat dikembalikan!</p>
<div class="mt-4">
<button type="button" class="btn btn-danger px-4" id="confirmDelete">Ya, Hapus!</button>
<button type="button" class="btn btn-secondary px-4 tutup-modal">Batal</button>
</div>
</div>
</div>
</div>
</div>
{{-- SCRIPTS --}}
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.0/dist/js/bootstrap.bundle.min.js"></script>
<script>
$(document).ready(function() {
let deleteId = null;
let originalData = {
username: '',
nama: '',
role: ''
};
// 1. Fungsi Tutup Modal
$(document).on('click', '.tutup-modal', function(e) {
e.preventDefault();
$('.modal').modal('hide');
$('body').removeClass('modal-open');
$('.modal-backdrop').remove();
});
// 2. Fungsi Reset Form
function resetFormState() {
$('#userForm')[0].reset();
$('#methodField').empty();
$('#passwordRow').show();
$('#modal_password').prop('required', true);
// Kembalikan tampilan input ke default
$('#modal_username, #modal_nama').prop('readonly', false).css('background-color', '#fff');
$('.form-control').removeClass('is-invalid');
}
// 3. Tombol Tambah (Membuka Modal)
function resetFormState() {
$('#userForm')[0].reset(); // Kosongkan semua input
$('#methodPlaceholder').html(''); // Hapus @method('PUT') jika sebelumnya habis edit
$('#passwordGroup').show(); // Tampilkan input password (karena biasanya kalau edit password dikosongkan)
$('#username').prop('readonly', false); // Pastikan username bisa diisi
}
$(document).ready(function() {
$('.btn-tambah').on('click', function() {
resetFormState();
$('#modalTitle').text('Tambah Pengguna Baru');
$('#userForm').attr('action', "{{ route('users.store') }}");
$('#btnSubmit').removeClass('btn-primary').addClass('btn-success').text('Tambah Pengguna');
$('#userModal').modal('show');
});
});
// 4. Tombol Edit (Membuka Modal & Isi Data)
$(document).ready(function() {
$(document).on('click', '.btn-edit', function() {
// Ambil data dari atribut tombol
var id = $(this).data('id');
var username = $(this).data('username');
var nama = $(this).data('nama'); // Pastikan di tombol ada data-nama
var role = $(this).data('role');
// Isi input modal
$('#modal_username').val(username);
$('#modal_nama').val(nama); // Mengisi Nama Lengkap
$('#modal_role').val(role);
// SET ACTION FORM (Penting untuk cegah 404)
// Pastikan url ini sama dengan yang ada di web.php
var actionUrl = "{{ url('admin/users/update') }}/" + id;
$('#formEditUser').attr('action', actionUrl);
// Tampilkan modal
$('#modalEditUser').modal('show');
});
});
// 5. VALIDASI SAAT SUBMIT (BAGIAN PALING PENTING)
$('#userForm').on('submit', function(e) {
const form = $(this); // Ambil form yang sedang aktif
const isEdit = $('#methodField').html().includes('PUT');
// Mengambil nilai input KHUSUS dari dalam form modal ini saja
const currentUsername = form.find('#modal_username').val() ? form.find('#modal_username').val().trim() : "";
const currentNama = form.find('#modal_nama').val() ? form.find('#modal_nama').val().trim() : "";
const currentRole = form.find('#modal_role').val();
const currentPass = form.find('#modal_password').val();
// Pengecekan apakah kosong (Cegah error "Gagal" yang anda alami)
if (currentUsername === "" || currentNama === "") {
e.preventDefault();
Swal.fire({
icon: 'error',
title: 'Gagal!',
text: 'Username dan Nama wajib diisi! Pastikan Anda telah mengetik dengan benar.',
confirmButtonColor: '#d33'
});
return false;
}
// Validasi minimal 3 karakter untuk Nama Lengkap
if (currentNama.length < 3) {
e.preventDefault();
Swal.fire({
icon: 'warning',
title: 'Perhatian',
text: 'Nama Lengkap minimal harus 3 karakter!'
});
return false;
}
// Jika sedang EDIT, cek apakah ada perubahan
if (isEdit) {
if (currentUsername === originalData.username &&
currentRole === originalData.role &&
currentPass === "" &&
currentNama === originalData.nama) {
e.preventDefault();
Swal.fire({
icon: 'info',
title: 'Tidak Ada Perubahan',
text: 'Anda belum mengubah data apapun pada user ini.',
confirmButtonColor: '#3085d6'
});
return false;
}
}
// Jika lolos semua validasi, form akan ter-submit secara otomatis
});
// 6. Tombol Hapus (Konfirmasi)
$(document).on('click', '.btn-hapus-modal', function() {
deleteId = $(this).data('id');
$('#del_nama').text($(this).data('nama'));
$('#deleteModal').modal('show');
});
$('#confirmDelete').on('click', function() {
const form = $('<form>', {
'action': "/users/" + deleteId,
'method': 'POST'
}).append('@csrf', '@method("DELETE")');
$('body').append(form);
form.submit();
});
// Otomatis reset saat modal ditutup
$('#userModal').on('hidden.bs.modal', function() {
resetFormState();
});
});
</script>
</div>
</div>
</div>
</div>