Files
backend_parkir/resources/views/setup/petugas/petugas.blade.php
T

287 lines
19 KiB
PHP

@extends('layouts.master')
@section('styles')
<style>
.foto-thumb { width: 48px; height: 48px; object-fit: cover; border-radius: 6px; border: 1px solid #dee2e6; }
.foto-preview { width: 120px; height: 120px; object-fit: cover; border-radius: 8px; border: 1px solid #dee2e6; }
.card-body label { font-size: 13px; color: #6c757d; }
</style>
@endsection
@section('content')
<div class="container-fluid page-body-wrapper">
<div class="main-panel">
<div class="content-wrapper">
<div class="row">
<div class="col-12 grid-margin stretch-card">
<div class="card">
<div class="card-body">
<div class="d-flex justify-content-between align-items-center mb-3">
<h4 class="card-title mb-0">Master Petugas / Pegawai</h4>
<button class="btn btn-primary btn-sm" id="btnAdd" type="button">
<i class="fa fa-plus me-1"></i>Tambah
</button>
</div>
<div class="table-responsive">
<table class="table table-bordered table-striped" id="petugas-table">
<thead>
<tr>
<th class="text-center" width="5%">Foto</th>
<th>Nomer</th>
<th>Nama</th>
<th>Username</th>
<th>Level</th>
<th class="text-center">Bisa Login</th>
<th class="text-center">Status</th>
<th class="text-center" width="18%">Aksi</th>
</tr>
</thead>
<tbody>
@forelse ($petugas as $p)
<tr>
<td class="text-center">
<img class="foto-thumb" src="{{ route('petugas.foto', $p->id, false) }}" alt="foto" loading="lazy">
</td>
<td>{{ $p->nomer }}</td>
<td>{{ $p->nama }}</td>
<td>{{ $p->username }}</td>
<td>{{ $levels->firstWhere('level_code', $p->level_pegawai)->level_name ?? $p->level_pegawai }}</td>
<td class="text-center">
<span class="badge {{ $p->bisalogin == 1 ? 'bg-success' : 'bg-secondary' }}">
{{ $p->bisalogin == 1 ? 'Ya' : 'Tidak' }}
</span>
</td>
<td class="text-center">
<span class="badge {{ $p->status == 1 ? 'bg-success' : 'bg-danger' }}">
{{ $p->status == 1 ? 'Aktif' : 'Nonaktif' }}
</span>
</td>
<td class="text-center">
<button class="btn btn-info btn-sm btn-detail" type="button" data-id="{{ $p->id }}">Detail</button>
<button class="btn btn-warning btn-sm btn-edit" type="button" data-id="{{ $p->id }}">Ubah</button>
<button class="btn btn-danger btn-sm btn-delete" type="button" data-id="{{ $p->id }}" data-nama="{{ $p->nama }}">Hapus</button>
</td>
</tr>
@empty
<tr><td colspan="8" class="text-center">Belum ada data petugas.</td></tr>
@endforelse
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- MODAL FORM -->
<div class="modal fade" id="modal-petugas" tabindex="-1" data-bs-backdrop="static">
<div class="modal-dialog modal-lg modal-dialog-scrollable">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="modal-title">Tambah Petugas</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<form id="form-petugas" enctype="multipart/form-data">
@csrf
<input type="hidden" name="_method" id="form-method" value="POST">
<input type="hidden" id="form-id" value="">
<div class="modal-body">
<div class="row g-2">
<div class="col-md-3 text-center">
<img class="foto-preview mb-2" id="foto-preview" src="{{ asset('images/no-image.jpg') }}" alt="preview">
<input type="file" class="form-control form-control-sm" name="foto" id="foto" accept="image/*">
<small class="text-muted">JPG/PNG/BMP, maks 2MB</small>
</div>
<div class="col-md-9">
<div class="row g-2">
<div class="col-md-6"><label class="form-label">Nomer *</label><input class="form-control" name="nomer" id="f-nomer" maxlength="50" required></div>
<div class="col-md-6"><label class="form-label">Nama *</label><input class="form-control" name="nama" id="f-nama" maxlength="50" required></div>
<div class="col-md-6"><label class="form-label">Username *</label><input class="form-control" name="username" id="f-username" maxlength="50" required></div>
<div class="col-md-6"><label class="form-label">Password <span id="pw-hint">*</span></label><input type="text" class="form-control" name="password" id="f-password" maxlength="50" placeholder="Kosongkan jika tidak diubah"></div>
<div class="col-md-6"><label class="form-label">Level</label>
<select class="form-select" name="level_pegawai" id="f-level">
<option value="">-- Pilih --</option>
@foreach ($levels as $lv)
<option value="{{ $lv->level_code }}">{{ $lv->level_name }}</option>
@endforeach
</select>
</div>
<div class="col-md-6"><label class="form-label">NIP</label><input class="form-control" name="nip" id="f-nip" maxlength="50"></div>
<div class="col-md-4"><label class="form-label">Bisa Login</label>
<select class="form-select" name="bisalogin" id="f-bisalogin"><option value="1">Ya</option><option value="0">Tidak</option></select>
</div>
<div class="col-md-4"><label class="form-label">Status</label>
<select class="form-select" name="status" id="f-status"><option value="1">Aktif</option><option value="0">Nonaktif</option></select>
</div>
<div class="col-md-4"><label class="form-label">Jenis Kelamin</label>
<select class="form-select" name="jeniskelamin" id="f-jk"><option value="0">Laki-laki</option><option value="1">Perempuan</option></select>
</div>
<div class="col-md-6"><label class="form-label">Agama</label><input class="form-control" name="agama" id="f-agama" maxlength="50"></div>
<div class="col-md-6"><label class="form-label">Telepon</label><input class="form-control" name="telepon" id="f-telepon" maxlength="255"></div>
<div class="col-md-6"><label class="form-label">Tgl Lahir</label><input type="date" class="form-control" name="tgl_lahir" id="f-tgl-lahir"></div>
<div class="col-md-6"><label class="form-label">Tgl Masuk</label><input type="date" class="form-control" name="tgl_masuk" id="f-tgl-masuk"></div>
<div class="col-md-6"><label class="form-label">Email</label><input class="form-control" name="email" id="f-email" maxlength="64"></div>
<div class="col-md-6"><label class="form-label">Alamat</label><input class="form-control" name="alamat" id="f-alamat" maxlength="100"></div>
<div class="col-md-6"><label class="form-label">Alamat Lahir</label><input class="form-control" name="alamat_lahir" id="f-alamat-lahir" maxlength="255"></div>
<div class="col-md-6"><label class="form-label">Alamat Sekarang</label><input class="form-control" name="alamat_sekarang" id="f-alamat-sekarang" maxlength="255"></div>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<button type="submit" class="btn btn-primary">Simpan</button>
<button type="button" class="btn btn-danger" data-bs-dismiss="modal">Batal</button>
</div>
</form>
</div>
</div>
</div>
<!-- MODAL DETAIL -->
<div class="modal fade" id="modal-detail" tabindex="-1">
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content">
<div class="modal-header"><h5 class="modal-title">Detail Petugas</h5><button class="btn-close" data-bs-dismiss="modal"></button></div>
<div class="modal-body" id="detail-body"></div>
</div>
</div>
</div>
</div>
@endsection
@section('javascript')
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.4/jquery.min.js"></script>
<script src="{{ asset('vendor/sweetalert2/dist/sweetalert2.min.js') }}"></script>
<script>
$(function () {
const csrf = $('meta[name="csrf-token"]').attr('content');
const noImage = '{{ asset('images/no-image.jpg') }}';
const levelMap = @json($levels->pluck('level_name', 'level_code'));
const routes = {
store: '{{ route('petugas.store', [], false) }}',
show: '{{ route('petugas.show', ':id', false) }}',
update: '{{ route('petugas.update', ':id', false) }}',
destroy: '{{ route('petugas.destroy', ':id', false) }}',
foto: '{{ route('petugas.foto', ':id', false) }}'
};
const modal = new bootstrap.Modal(document.getElementById('modal-petugas'));
function errMsg(xhr) {
if (xhr.status === 419) return 'Sesi berakhir, silakan muat ulang halaman.';
if (xhr.status === 422 && xhr.responseJSON?.errors) {
return Object.values(xhr.responseJSON.errors).flat().join('\n');
}
return xhr.responseJSON?.message || 'Operasi gagal.';
}
$('#foto').on('change', function () {
const f = this.files[0];
$('#foto-preview').attr('src', f ? URL.createObjectURL(f) : noImage);
});
$('#btnAdd').on('click', function () {
$('#form-petugas')[0].reset();
$('#form-id').val('');
$('#form-method').val('POST');
$('#pw-hint').text('*');
$('#f-password').prop('required', true);
$('#foto-preview').attr('src', noImage);
$('#modal-title').text('Tambah Petugas');
modal.show();
});
$(document).on('click', '.btn-edit', function () {
const id = $(this).data('id');
const btn = $(this); const btnHtml = btn.html();
btn.prop('disabled', true).html('<span class="spinner-border spinner-border-sm"></span>');
$.get(routes.show.replace(':id', id), function (r) {
const d = r.data;
$('#form-id').val(d.id);
$('#form-method').val('PUT');
$('#pw-hint').text('(kosongkan jika tidak diubah)');
$('#f-password').prop('required', false).val('');
$('#f-nomer').val(d.nomer);
$('#f-nama').val(d.nama);
$('#f-username').val(d.username);
$('#f-level').val(d.level_pegawai);
$('#f-nip').val(d.nip);
$('#f-bisalogin').val(d.bisalogin ?? 1);
$('#f-status').val(d.status ?? 1);
$('#f-jk').val(d.jeniskelamin ?? 0);
$('#f-agama').val(d.agama);
$('#f-telepon').val(d.telepon);
$('#f-tgl-lahir').val(d.tgl_lahir);
$('#f-tgl-masuk').val(d.tgl_masuk);
$('#f-email').val(d.email);
$('#f-alamat').val(d.alamat);
$('#f-alamat-lahir').val(d.alamat_lahir);
$('#f-alamat-sekarang').val(d.alamat_sekarang);
$('#foto').val('');
$('#foto-preview').attr('src', r.has_foto ? routes.foto.replace(':id', d.id) + '?t=' + Date.now() : noImage);
$('#modal-title').text('Ubah Petugas');
modal.show();
}).fail(xhr => Swal.fire({icon: 'error', title: 'Gagal memuat data', text: errMsg(xhr)})).always(() => btn.prop('disabled', false).html(btnHtml));
});
$('#form-petugas').on('submit', function (e) {
e.preventDefault();
const id = $('#form-id').val();
const isEdit = !!id;
const url = isEdit ? routes.update.replace(':id', encodeURIComponent(id)) : routes.store;
const fd = new FormData(this);
if (isEdit) fd.set('_method', 'PUT');
const saveBtn = $(this).find('[type="submit"]'); const saveHtml = saveBtn.html();
saveBtn.prop('disabled', true).html('<span class="spinner-border spinner-border-sm me-1"></span>Menyimpan...');
$.ajax({
url: url, type: 'POST', data: fd, processData: false, contentType: false,
headers: {'X-CSRF-TOKEN': csrf},
success: () => window.location.reload(),
error: xhr => {
saveBtn.prop('disabled', false).html(saveHtml);
Swal.fire({icon: 'error', title: 'Gagal menyimpan', text: errMsg(xhr)});
}
});
});
$(document).on('click', '.btn-delete', function () {
const id = $(this).data('id');
const nama = $(this).data('nama');
Swal.fire({title: 'Hapus petugas?', text: nama, icon: 'warning', showCancelButton: true, confirmButtonText: 'Ya, hapus', cancelButtonText: 'Batal', confirmButtonColor: '#dc3545', showLoaderOnConfirm: true, preConfirm: () => $.ajax({url: routes.destroy.replace(':id', encodeURIComponent(id)), type: 'DELETE', headers: {'X-CSRF-TOKEN': csrf}}).catch(xhr => { Swal.showValidationMessage(errMsg(xhr)); })})
.then(res => {
if (res.isConfirmed && res.value) {
Swal.fire({icon: 'success', title: 'Berhasil', text: 'Petugas dihapus.', timer: 1500, showConfirmButton: false}).then(() => window.location.reload());
}
});
});
$(document).on('click', '.btn-detail', function () {
const id = $(this).data('id');
const btn = $(this); const btnHtml = btn.html();
btn.prop('disabled', true).html('<span class="spinner-border spinner-border-sm"></span>');
$('#detail-body').html('<div class="text-center py-3"><span class="spinner-border spinner-border-sm me-2"></span>Memuat...</div>');
new bootstrap.Modal(document.getElementById('modal-detail')).show();
$.get(routes.show.replace(':id', id), function (r) {
const d = r.data;
const img = r.has_foto ? routes.foto.replace(':id', d.id) : noImage;
$('#detail-body').html(
'<div class="text-center mb-3"><img src="' + img + '" class="foto-preview" alt="foto"></div>' +
'<dl class="row mb-0">' +
'<dt class="col-4">Nomer</dt><dd class="col-8">' + (d.nomer ?? '-') + '</dd>' +
'<dt class="col-4">Nama</dt><dd class="col-8">' + (d.nama ?? '-') + '</dd>' +
'<dt class="col-4">Username</dt><dd class="col-8">' + (d.username ?? '-') + '</dd>' +
'<dt class="col-4">Level</dt><dd class="col-8">' + (levelMap[d.level_pegawai] ?? d.level_pegawai ?? '-') + '</dd>' +
'<dt class="col-4">NIP</dt><dd class="col-8">' + (d.nip ?? '-') + '</dd>' +
'<dt class="col-4">Telepon</dt><dd class="col-8">' + (d.telepon ?? '-') + '</dd>' +
'<dt class="col-4">Alamat</dt><dd class="col-8">' + (d.alamat ?? '-') + '</dd>' +
'<dt class="col-4">Tgl Lahir</dt><dd class="col-8">' + (d.tgl_lahir ?? '-') + '</dd>' +
'<dt class="col-4">Tgl Masuk</dt><dd class="col-8">' + (d.tgl_masuk ?? '-') + '</dd>' +
'</dl>'
);
}).fail(xhr => $('#detail-body').html('<div class="text-danger text-center">' + errMsg(xhr) + '</div>')).always(() => btn.prop('disabled', false).html(btnHtml));
});
});
</script>
@endsection