fix login auto detect menu link, and partial update tchnician role dealer

This commit is contained in:
2025-07-09 18:32:49 +07:00
parent e468672bbe
commit e59841fd23
14 changed files with 1362 additions and 103 deletions

View File

@@ -39,6 +39,7 @@
<tr>
<th>No</th>
<th>Nama Role</th>
<th>Dealer Tambahan</th>
<th>Aksi</th>
</tr>
</thead>
@@ -47,13 +48,30 @@
<tr>
<td>{{ $loop->iteration }}</td>
<td>{{ $role->name }}</td>
<td>
@if($role->dealers->count() > 0)
<div class="dealer-list">
@foreach($role->dealers->take(3) as $dealer)
<span class="badge badge-info mr-1 mb-1">{{ $dealer->name }}</span>
@endforeach
@if($role->dealers->count() > 3)
<span class="badge badge-secondary">+{{ $role->dealers->count() - 3 }} more</span>
@endif
</div>
@else
<span class="text-muted">Tidak ada dealer tambahan untuk role ini</span>
@endif
</td>
<td>
<div class="d-flex">
@can('update', $menus['roleprivileges.index'])
<button class="btn btn-sm btn-bold btn-warning mr-2" onclick="editRole({{$role->id}})"> Edit</button>
@endcan
@can('delete', $menus['roleprivileges.index'])
<button class="btn btn-sm btn-bold btn-danger" onclick="deleteRole({{$role->id}}, '{{$role->name}}')">Hapus</button>
<button class="btn btn-sm btn-bold btn-danger mr-2" onclick="deleteRole({{$role->id}}, '{{$role->name}}')">Hapus</button>
@endcan
@can('create', $menus['roleprivileges.index'])
<button class="btn btn-sm btn-bold btn-success" onclick="assignDealer({{$role->id}})"> Tambah Dealer</button>
@endcan
</div>
</td>
@@ -183,6 +201,141 @@
</form>
</div>
</div>
<div class="modal fade" id="assignDealerModal" tabindex="-1" role="dialog" aria-labelledby="assignDealerModalLabel" aria-hidden="true">
<div class="modal-dialog modal-lg" role="document">
<form id="assignDealerForm" method="POST">
@csrf
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="assignDealerModalLabel">
Assign Dealer ke Role
</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<div class="alert alert-light border">
<strong>Petunjuk:</strong> Pilih dealer yang akan di-assign ke role ini. Dealer yang sudah di-assign akan otomatis tercentang.
</div>
<div class="form-group">
<label class="font-weight-bold">
Daftar Dealer
</label>
<div class="dealer-checkboxes border rounded p-3" style="max-height: 350px; overflow-y: auto;">
<div class="row">
@foreach ($dealers as $dealer)
<div class="col-md-6 mb-2">
<div class="form-check custom-checkbox">
<input class="form-check-input dealer-checkbox" type="checkbox"
name="dealers[]" value="{{ $dealer->id }}"
id="dealer_{{ $dealer->id }}">
<label class="form-check-label d-flex align-items-center" for="dealer_{{ $dealer->id }}">
<div class="dealer-info">
<div class="dealer-name font-weight-semibold">{{ $dealer->name }}</div>
<div class="dealer-code text-muted small">
<i class="fas fa-tag mr-1"></i>
{{ $dealer->dealer_code }}
</div>
</div>
</label>
</div>
</div>
@endforeach
</div>
</div>
</div>
<div class="form-group mb-0">
<div class="d-flex justify-content-between align-items-center">
<div>
<button type="button" class="btn btn-outline-primary btn-sm mr-2" onclick="selectAllDealers()">
Pilih Semua
</button>
<button type="button" class="btn btn-outline-secondary btn-sm" onclick="deselectAllDealers()">
Hapus Semua
</button>
</div>
<div class="text-muted small">
<span id="selectedCount">0</span> dealer dipilih
</div>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">
Batal
</button>
<button type="submit" class="btn btn-primary" id="submitBtn">
Simpan Perubahan
</button>
</div>
</div>
</form>
</div>
</div>
@endsection
@section('styles')
<style>
.custom-checkbox .form-check-label {
cursor: pointer;
padding: 0.5rem;
border-radius: 0.25rem;
transition: background-color 0.2s ease;
width: 100%;
}
.custom-checkbox .form-check-label:hover {
background-color: #f8f9fa;
}
.custom-checkbox .form-check-input:checked + .form-check-label {
background-color: #e8f5e8;
border-left: 3px solid #28a745;
}
.dealer-info {
flex: 1;
margin-left: 0.5rem;
}
.dealer-name {
font-weight: 500;
margin-bottom: 0.125rem;
}
.dealer-code {
font-size: 0.75rem;
color: #6c757d;
}
.dealer-checkboxes::-webkit-scrollbar {
width: 6px;
}
.dealer-checkboxes::-webkit-scrollbar-track {
background: #f1f1f1;
}
.dealer-checkboxes::-webkit-scrollbar-thumb {
background: #c1c1c1;
border-radius: 3px;
}
.dealer-checkboxes::-webkit-scrollbar-thumb:hover {
background: #a8a8a8;
}
/* Responsive improvements */
@media (max-width: 768px) {
.dealer-checkboxes .col-md-6 {
flex: 0 0 100%;
max-width: 100%;
}
}
</style>
@endsection
@section('javascripts')
@@ -296,17 +449,145 @@
}
})
}
function assignDealer(roleId) {
// Set form action
let url = '{{ route("roleprivileges.assignDealer", ":id") }}'.replace(':id', roleId);
$("#assignDealerForm").attr("action", url);
// Reset checkboxes and counter
$('.dealer-checkbox').prop('checked', false);
updateSelectedCount();
// Load existing assigned dealers
$.ajax({
url: '{{ route("roleprivileges.getAssignedDealers", ":id") }}'.replace(':id', roleId),
type: 'GET',
success: function(response) {
if (response.assignedDealers) {
response.assignedDealers.forEach(function(dealerId) {
$(`#dealer_${dealerId}`).prop('checked', true);
});
}
updateSelectedCount();
},
error: function() {
console.log('Error loading assigned dealers');
updateSelectedCount();
}
});
$("#assignDealerModal").modal("show");
}
function selectAllDealers() {
$('.dealer-checkbox').prop('checked', true);
updateSelectedCount();
}
function deselectAllDealers() {
$('.dealer-checkbox').prop('checked', false);
updateSelectedCount();
}
function updateSelectedCount() {
const selectedCount = $('.dealer-checkbox:checked').length;
$('#selectedCount').text(selectedCount);
// Update submit button state
if (selectedCount > 0) {
$('#submitBtn').prop('disabled', false).removeClass('btn-secondary').addClass('btn-primary');
} else {
$('#submitBtn').prop('disabled', true).removeClass('btn-primary').addClass('btn-secondary');
}
}
$(document).ready(function () {
// Add event handlers for modal close buttons
$('.close, [data-dismiss="modal"]').on("click", function () {
$("#roleModal").modal("hide");
$("#roleEditModal").modal("hide");
$("#assignDealerModal").modal("hide");
});
// Also handle the "Close" button
$('.btn-secondary[data-dismiss="modal"]').on("click", function () {
$("#roleModal").modal("hide");
$("#roleEditModal").modal("hide");
$("#assignDealerModal").modal("hide");
});
// Event listener for dealer checkboxes
$(document).on('change', '.dealer-checkbox', function() {
updateSelectedCount();
});
// Handle form submission for assign dealer
$("#assignDealerForm").on("submit", function(e) {
e.preventDefault();
// Validate if at least one dealer is selected
const selectedDealers = $('.dealer-checkbox:checked').length;
if (selectedDealers === 0) {
Swal.fire({
title: 'Peringatan!',
text: 'Silakan pilih minimal satu dealer',
icon: 'warning',
confirmButtonText: 'OK'
});
return;
}
// Disable submit button and show loading
const submitBtn = $('#submitBtn');
const originalText = submitBtn.html();
submitBtn.prop('disabled', true).html('<i class="fas fa-spinner fa-spin mr-1"></i>Menyimpan...');
let formData = new FormData(this);
let url = $(this).attr("action");
$.ajax({
url: url,
type: 'POST',
data: formData,
processData: false,
contentType: false,
success: function(response) {
if (response.success) {
Swal.fire({
title: 'Berhasil!',
text: response.message,
icon: 'success',
confirmButtonText: 'OK'
}).then(() => {
location.reload();
});
} else {
Swal.fire({
title: 'Error!',
text: response.message || 'Terjadi kesalahan',
icon: 'error',
confirmButtonText: 'OK'
});
}
},
error: function(xhr) {
let message = 'Terjadi kesalahan';
if (xhr.responseJSON && xhr.responseJSON.message) {
message = xhr.responseJSON.message;
}
Swal.fire({
title: 'Error!',
text: message,
icon: 'error',
confirmButtonText: 'OK'
});
},
complete: function() {
// Re-enable submit button
submitBtn.prop('disabled', false).html(originalText);
}
});
});
});
</script>