Hidupkan CRUD level-user: store/show/update/destroy + inline form + cegah hapus level terpakai
This commit is contained in:
@@ -7,6 +7,7 @@
|
|||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Support\Facades\Auth;
|
use Illuminate\Support\Facades\Auth;
|
||||||
|
use Illuminate\Support\Facades\DB;
|
||||||
use Illuminate\Support\Facades\Log;
|
use Illuminate\Support\Facades\Log;
|
||||||
|
|
||||||
class LevelUserController extends Controller
|
class LevelUserController extends Controller
|
||||||
@@ -43,7 +44,24 @@ public function create()
|
|||||||
*/
|
*/
|
||||||
public function store(Request $request)
|
public function store(Request $request)
|
||||||
{
|
{
|
||||||
//
|
$data = $request->validate(
|
||||||
|
[
|
||||||
|
'level_code' => 'required|string|max:10|unique:level_user,level_code',
|
||||||
|
'level_name' => 'required|string|max:30',
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'level_code.unique' => 'Kode level sudah dipakai, ganti dengan yang unik.',
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
$level = LevelPegawai::create([
|
||||||
|
'level_code' => $data['level_code'],
|
||||||
|
'level_name' => $data['level_name'],
|
||||||
|
'create_by' => Auth::user()->nomer ?? Auth::user()->username ?? 'system',
|
||||||
|
'create_date' => now(),
|
||||||
|
]);
|
||||||
|
|
||||||
|
return response()->json(['success' => true, 'message' => 'Level pengguna berhasil ditambahkan.', 'data' => $level], 201);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -54,7 +72,7 @@ public function store(Request $request)
|
|||||||
*/
|
*/
|
||||||
public function show($id)
|
public function show($id)
|
||||||
{
|
{
|
||||||
Log::info($id);
|
return response()->json(['success' => true, 'data' => LevelPegawai::findOrFail($id)]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -65,7 +83,7 @@ public function show($id)
|
|||||||
*/
|
*/
|
||||||
public function edit($id)
|
public function edit($id)
|
||||||
{
|
{
|
||||||
//
|
return response()->json(['success' => true, 'data' => LevelPegawai::findOrFail($id)]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -77,7 +95,17 @@ public function edit($id)
|
|||||||
*/
|
*/
|
||||||
public function update(Request $request, $id)
|
public function update(Request $request, $id)
|
||||||
{
|
{
|
||||||
//
|
// level_code tidak bisa diubah (dipakai relasi pegawai.level_pegawai)
|
||||||
|
$data = $request->validate(['level_name' => 'required|string|max:30']);
|
||||||
|
|
||||||
|
$level = LevelPegawai::findOrFail($id);
|
||||||
|
$level->update([
|
||||||
|
'level_name' => $data['level_name'],
|
||||||
|
'update_by' => Auth::id(),
|
||||||
|
'update_date' => now(),
|
||||||
|
]);
|
||||||
|
|
||||||
|
return response()->json(['success' => true, 'message' => 'Level pengguna berhasil diperbarui.', 'data' => $level]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -88,6 +116,18 @@ public function update(Request $request, $id)
|
|||||||
*/
|
*/
|
||||||
public function destroy($id)
|
public function destroy($id)
|
||||||
{
|
{
|
||||||
//
|
$level = LevelPegawai::findOrFail($id);
|
||||||
|
|
||||||
|
$dipakai = DB::table('pegawai')->where('level_pegawai', $level->level_code)->count();
|
||||||
|
if ($dipakai > 0) {
|
||||||
|
return response()->json([
|
||||||
|
'success' => false,
|
||||||
|
'message' => "Level {$level->level_code} dipakai {$dipakai} pegawai, tidak bisa dihapus.",
|
||||||
|
], 409);
|
||||||
|
}
|
||||||
|
|
||||||
|
$level->delete();
|
||||||
|
|
||||||
|
return response()->json(['success' => true, 'message' => 'Level pengguna berhasil dihapus.']);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,8 @@ class LevelPegawai extends Model
|
|||||||
use HasFactory;
|
use HasFactory;
|
||||||
|
|
||||||
protected $table = 'level_user';
|
protected $table = 'level_user';
|
||||||
|
protected $primaryKey = 'level_id';
|
||||||
|
public $timestamps = false; // pakai create_date / update_date manual
|
||||||
|
|
||||||
protected $fillable = [
|
protected $fillable = [
|
||||||
'level_code', 'level_name','create_by','create_date','update_date','update_by'
|
'level_code', 'level_name','create_by','create_date','update_date','update_by'
|
||||||
|
|||||||
@@ -56,9 +56,9 @@
|
|||||||
<div class="card shadow-sm h-100">
|
<div class="card shadow-sm h-100">
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<h4 class="card-title">Daftar Pintu/Pos</h4>
|
<h4 class="card-title">Daftar Level Pengguna</h4>
|
||||||
<div class="table-responsive mb-2">
|
<div class="table-responsive mb-2">
|
||||||
<table class="table table-bordered table-selectable" id="example" data-url="">
|
<table class="table table-bordered table-selectable" id="level-table" data-url="">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th class="p-3" width="3%">No.</th>
|
<th class="p-3" width="3%">No.</th>
|
||||||
@@ -73,9 +73,9 @@
|
|||||||
<tr>
|
<tr>
|
||||||
<td class="text-center">{{ $loop->iteration }}</td>
|
<td class="text-center">{{ $loop->iteration }}</td>
|
||||||
<td class="text-center" hidden>{{ $level->level_id }}</td>
|
<td class="text-center" hidden>{{ $level->level_id }}</td>
|
||||||
<td class="text-center" width="7%">{{ $level->level_code }} </td>
|
<td class="text-center" width="7%" data-level-id="{{ $level->level_id }}" data-level-code="{{ $level->level_code }}" data-level-name="{{ $level->level_name }}">{{ $level->level_code }} </td>
|
||||||
<td>{{ $level->level_name }}</td>
|
<td>{{ $level->level_name }}</td>
|
||||||
<td class="text-center" width="10%">{{ \Carbon\Carbon::parse($level->create_date)->format('Y-m-d')}}</td>
|
<td class="text-center" width="10%">{{ $level->create_date ? \Carbon\Carbon::parse($level->create_date)->format('Y-m-d') : '-' }}</td>
|
||||||
<td class="text-center" width="12%">
|
<td class="text-center" width="12%">
|
||||||
<button type="button" class="user-acess" data-bs-toggle="modal" title="Izin Akses" data-bs-target=".bd-ubah-modal-lg"><i class="fa-solid fa-user-gear"></i></button>
|
<button type="button" class="user-acess" data-bs-toggle="modal" title="Izin Akses" data-bs-target=".bd-ubah-modal-lg"><i class="fa-solid fa-user-gear"></i></button>
|
||||||
<button type="button" class="user-menu" data-bs-toggle="modal" id="menuakses" title="Menu Akses" data-bs-target=".user-menu-modal-lg"><i class="fa-solid fa-bars"></i></button>
|
<button type="button" class="user-menu" data-bs-toggle="modal" id="menuakses" title="Menu Akses" data-bs-target=".user-menu-modal-lg"><i class="fa-solid fa-bars"></i></button>
|
||||||
@@ -86,11 +86,11 @@
|
|||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
<div class="d-flex justify-content-center align-items-center mt-2">
|
<div class="d-flex justify-content-center align-items-center mt-2">
|
||||||
<div>
|
<div class="d-flex gap-2">
|
||||||
<button class="btn btn-primary btn-sm add-button" data-bs-toggle="modal" data-bs-target=".bd-example-modal-lg">Tambah</button>
|
<button class="btn btn-primary btn-sm" id="btnAddLevel" type="button">Tambah</button>
|
||||||
<button class="btn btn-warning btn-sm edit-button" id="btnEdit" data-bs-toggle="modal" data-bs-target=".bd-ubah-modal-lg">Ubah</button>
|
<button class="btn btn-warning btn-sm" id="btnEditLevel" type="button" disabled>Ubah</button>
|
||||||
<button class="btn btn-danger btn-sm" id="btnDelete">Hapus</button>
|
<button class="btn btn-danger btn-sm" id="btnDeleteLevel" type="button" disabled>Hapus</button>
|
||||||
<button class="btn btn-danger btn-sm" id="btnDelete">Detail</button>
|
<button class="btn btn-info btn-sm" id="btnDetailLevel" type="button" disabled>Detail</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -102,6 +102,12 @@
|
|||||||
<!-- END MEMMBER MODAL -->
|
<!-- END MEMMBER MODAL -->
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="modal fade" id="level-detail-modal" tabindex="-1">
|
||||||
|
<div class="modal-dialog modal-dialog-centered"><div class="modal-content">
|
||||||
|
<div class="modal-header"><h5 class="modal-title">Detail Level Pengguna</h5><button class="btn-close" data-bs-dismiss="modal"></button></div>
|
||||||
|
<div class="modal-body" id="level-detail-body"></div>
|
||||||
|
</div></div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -120,85 +126,65 @@
|
|||||||
<script src="{{asset ('vendor/sweetalert2/dist/sweetalert2.min.js') }}"></script>
|
<script src="{{asset ('vendor/sweetalert2/dist/sweetalert2.min.js') }}"></script>
|
||||||
<script src="{{asset ('js/custom.min.js') }}"></script>
|
<script src="{{asset ('js/custom.min.js') }}"></script>
|
||||||
<script src="{{asset ('js/dlabnav-init.js') }}"></script>
|
<script src="{{asset ('js/dlabnav-init.js') }}"></script>
|
||||||
{{-- <script>
|
<script>
|
||||||
$(document).ready(function () {
|
$(function () {
|
||||||
|
let selected = null;
|
||||||
|
const csrf = $('meta[name="csrf-token"]').attr('content');
|
||||||
|
const routes = {
|
||||||
|
store: '{{ route('levelUser.store', [], false) }}',
|
||||||
|
show: '{{ route('levelUser.show', ':id', false) }}',
|
||||||
|
update: '{{ route('levelUser.update', ':id', false) }}',
|
||||||
|
destroy: '{{ route('levelUser.destroy', ':id', false) }}'
|
||||||
|
};
|
||||||
|
|
||||||
$(document).on('click', '.user-menu', function () {
|
function setSelected(row) {
|
||||||
|
$('#level-table tbody tr').removeClass('table-active');
|
||||||
|
selected = row ? $(row).find('[data-level-id]').data() : null;
|
||||||
|
if (row) $(row).addClass('table-active');
|
||||||
|
$('#btnDetailLevel, #btnEditLevel, #btnDeleteLevel').prop('disabled', !selected);
|
||||||
|
}
|
||||||
|
|
||||||
let id = $(this).data('id')
|
function formRow(mode, level) {
|
||||||
|
const isEdit = mode === 'edit';
|
||||||
|
return `<tr class="level-form-row"><td colspan="5"><form class="level-inline-form" data-mode="${mode}" data-id="${level?.levelId || ''}"><div class="row g-2 align-items-end"><div class="col-md-3"><label class="form-label mb-1">Level Code</label><input class="form-control" name="level_code" maxlength="10" value="${level?.levelCode || ''}" ${isEdit ? 'readonly' : ''} required></div><div class="col-md-5"><label class="form-label mb-1">Level Pengguna</label><input class="form-control" name="level_name" maxlength="30" value="${level?.levelName || ''}" required></div><div class="col-md-4 d-flex gap-2"><button class="btn btn-success" type="submit">Simpan</button><button class="btn btn-light border cancel-level-form" type="button">Batal</button></div></div></form></td></tr>`;
|
||||||
|
}
|
||||||
|
|
||||||
let url = "{{ route() }}"
|
$('#level-table tbody').on('click', 'tr:not(.level-form-row)', function () { setSelected(this); });
|
||||||
});
|
$('#btnAddLevel').on('click', function () { $('.level-form-row').remove(); $('#level-table tbody').prepend(formRow('create')); setSelected(null); });
|
||||||
|
$('#btnEditLevel').on('click', function () { if (!selected) return; $('.level-form-row').remove(); $('#level-table tbody tr').filter(function(){ return $(this).find('[data-level-id]').data('level-id') === selected.levelId; }).after(formRow('edit', selected)); });
|
||||||
// MODE EDIT
|
$(document).on('click', '.cancel-level-form', function () { $(this).closest('tr').remove(); });
|
||||||
$(document).on('click', '.btn-edit', function () {
|
|
||||||
|
|
||||||
$('.view-mode').addClass('d-none');
|
|
||||||
$('.edit-mode').removeClass('d-none');
|
|
||||||
|
|
||||||
$('.btn-edit').addClass('d-none');
|
|
||||||
$('.btn-save, .btn-cancel').removeClass('d-none');
|
|
||||||
});
|
|
||||||
|
|
||||||
// CANCEL
|
|
||||||
$(document).on('click', '.btn-cancel', function () {
|
|
||||||
|
|
||||||
$('.edit-mode').addClass('d-none');
|
|
||||||
$('.view-mode').removeClass('d-none');
|
|
||||||
|
|
||||||
$('.btn-save, .btn-cancel').addClass('d-none');
|
|
||||||
$('.btn-edit').removeClass('d-none');
|
|
||||||
});
|
|
||||||
|
|
||||||
// SAVE
|
|
||||||
$(document).on('click', '.btn-save', function () {
|
|
||||||
|
|
||||||
let dataToSend = {};
|
|
||||||
|
|
||||||
$('.edit-mode').each(function () {
|
|
||||||
let key = $(this).data('key');
|
|
||||||
dataToSend[key] = $(this).val();
|
|
||||||
});
|
|
||||||
|
|
||||||
console.log(dataToSend);
|
|
||||||
let gateId = $('.edit-row').data('id');
|
|
||||||
|
|
||||||
|
$(document).on('submit', '.level-inline-form', function (event) {
|
||||||
|
event.preventDefault(); const form = $(this); const id = form.data('id'); const edit = form.data('mode') === 'edit';
|
||||||
|
const btn = form.find('[type="submit"]'); const btnHtml = btn.html();
|
||||||
|
btn.prop('disabled', true).html('<span class="spinner-border spinner-border-sm me-1"></span>Menyimpan...');
|
||||||
$.ajax({
|
$.ajax({
|
||||||
url: "{{ route('hardware.update', '') }}/" + gateId,
|
url: edit ? routes.update.replace(':id', encodeURIComponent(id)) : routes.store,
|
||||||
type: "PUT",
|
type: edit ? 'PUT' : 'POST', data: form.serialize(), headers: {'X-CSRF-TOKEN': csrf},
|
||||||
data: {
|
success: () => window.location.reload(),
|
||||||
_token: "{{ csrf_token() }}",
|
error: xhr => {
|
||||||
data: dataToSend
|
btn.prop('disabled', false).html(btnHtml);
|
||||||
},
|
Swal.fire({icon: 'error', title: 'Gagal menyimpan', text: xhr.responseJSON?.message || Object.values(xhr.responseJSON?.errors || {}).flat().join('\n') || 'Gagal menyimpan level.'});
|
||||||
success: function () {
|
|
||||||
|
|
||||||
$('.edit-mode').each(function () {
|
|
||||||
let val = $(this).val();
|
|
||||||
$(this).siblings('.view-mode').text(val);
|
|
||||||
});
|
|
||||||
|
|
||||||
$('.btn-cancel').click();
|
|
||||||
Swal.fire({icon: 'success', title: 'Berhasil', text: 'Level pengguna tersimpan.'});
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
function formatValue(key, value) {
|
$('#btnDeleteLevel').on('click', function () {
|
||||||
|
if (!selected) return;
|
||||||
// kalau field *_avail kita kasih badge
|
Swal.fire({title:'Hapus level?', text:`${selected.levelCode} - ${selected.levelName}`, icon:'warning', showCancelButton:true, confirmButtonText:'Ya, hapus', cancelButtonText:'Batal', confirmButtonColor:'#dc3545', showLoaderOnConfirm: true, preConfirm: () => $.ajax({url: routes.destroy.replace(':id', encodeURIComponent(selected.levelId)), type:'DELETE', headers:{'X-CSRF-TOKEN':csrf}}).catch(xhr => { Swal.showValidationMessage(xhr.responseJSON?.message || 'Level tidak dapat dihapus.'); })})
|
||||||
if (key.includes('_avail')) {
|
.then(result => { if (result.isConfirmed && result.value) { Swal.fire({icon: 'success', title: 'Berhasil', text: 'Level dihapus.', timer: 1500, showConfirmButton: false}).then(() => window.location.reload()); } });
|
||||||
|
|
||||||
if (value == 1) {
|
|
||||||
return `<span class="badge rounded-pill bg-success px-3">ON</span>`;
|
|
||||||
} else {
|
|
||||||
return `<span class="badge rounded-pill bg-danger px-3">OFF</span>`;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// default
|
|
||||||
return value ?? '-';
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
</script> --}}
|
$('#btnDetailLevel').on('click', function () {
|
||||||
|
if (!selected) return;
|
||||||
|
const btn = $(this); const btnHtml = btn.html();
|
||||||
|
btn.prop('disabled', true).html('<span class="spinner-border spinner-border-sm me-1"></span>Memuat...');
|
||||||
|
$('#level-detail-body').html('<div class="text-center py-3"><span class="spinner-border spinner-border-sm me-2"></span>Memuat detail...</div>');
|
||||||
|
new bootstrap.Modal(document.getElementById('level-detail-modal')).show();
|
||||||
|
$.get(routes.show.replace(':id', encodeURIComponent(selected.levelId)), function(r) {
|
||||||
|
$('#level-detail-body').html(`<dl class="row mb-0"><dt class="col-5">Level Code</dt><dd class="col-7">${r.data.level_code}</dd><dt class="col-5">Nama Level</dt><dd class="col-7">${r.data.level_name}</dd><dt class="col-5">Dibuat</dt><dd class="col-7">${r.data.create_date ?? '-'}</dd><dt class="col-5">Diubah</dt><dd class="col-7">${r.data.update_date ?? '-'}</dd></dl>`);
|
||||||
|
}).fail(xhr => { $('#level-detail-body').html('<div class="text-danger text-center">' + (xhr.responseJSON?.message || 'Gagal memuat detail.') + '</div>'); }).always(() => btn.prop('disabled', false).html(btnHtml));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
@endsection
|
@endsection
|
||||||
|
|||||||
Reference in New Issue
Block a user