update HR dan Payroll
This commit is contained in:
@@ -1,418 +1,95 @@
|
||||
<div class="container mt-4">
|
||||
|
||||
<div class="card modern-card shadow-sm border-0 rounded-4">
|
||||
|
||||
<div class="card-body p-4">
|
||||
|
||||
<div class="d-flex justify-content-between mb-3">
|
||||
|
||||
<h5 class="mb-0">
|
||||
Leave Requests
|
||||
</h5>
|
||||
|
||||
<button class="btn btn-warning btn-add">
|
||||
Tambah Leave
|
||||
</button>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="table-responsive">
|
||||
|
||||
<table id="tableLeave"
|
||||
class="table modern-table align-middle w-100">
|
||||
|
||||
<thead class="table-light">
|
||||
|
||||
<tr>
|
||||
|
||||
<th width="5%">No</th>
|
||||
<th>Finger ID</th>
|
||||
<th>Employee</th>
|
||||
<th>Jenis Leave</th>
|
||||
<th>Tanggal Mulai</th>
|
||||
<th>Tanggal Selesai</th>
|
||||
<th>Total</th>
|
||||
<th>Status</th>
|
||||
<th width="15%">Aksi</th>
|
||||
|
||||
</tr>
|
||||
|
||||
</thead>
|
||||
|
||||
<tbody></tbody>
|
||||
|
||||
</table>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<?php $this->load->view('hr_payroll/_header',array('active_menu'=>'leave_requests','title'=>'Cuti & Izin','subtitle'=>'Kelola pengajuan secara tertib dari draft, persetujuan HR, hingga masuk ke perhitungan kehadiran.','action_html'=>$permissions['create']?'<button type="button" class="btn btn-warning btn-add-leave"><i class="bi bi-plus-lg"></i> Buat Pengajuan</button>':'')); ?>
|
||||
|
||||
<div class="leave-flow" aria-label="Alur pengajuan cuti">
|
||||
<span><b>1</b><small>Buat Draft</small></span><i class="bi bi-chevron-right"></i>
|
||||
<span><b>2</b><small>Ajukan</small></span><i class="bi bi-chevron-right"></i>
|
||||
<span><b>3</b><small>Review HR</small></span><i class="bi bi-chevron-right"></i>
|
||||
<span><b>4</b><small>Disetujui / Ditolak</small></span>
|
||||
</div>
|
||||
|
||||
<!-- MODAL -->
|
||||
<div class="modal fade" id="modalLeave">
|
||||
|
||||
<div class="modal-dialog modal-dialog-centered">
|
||||
|
||||
<div class="modal-content rounded-4">
|
||||
|
||||
<div class="modal-header bg-warning text-white">
|
||||
|
||||
<h5 class="modal-title">
|
||||
Tambah Leave
|
||||
</h5>
|
||||
|
||||
<button class="btn-close btn-close-white"
|
||||
data-bs-dismiss="modal"></button>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="modal-body">
|
||||
|
||||
<input type="hidden" id="inputId">
|
||||
|
||||
<label class="fw-semibold">
|
||||
Employee
|
||||
</label>
|
||||
|
||||
<select class="form-control select-search"
|
||||
id="employee_id">
|
||||
|
||||
<option value="">
|
||||
Pilih Employee
|
||||
</option>
|
||||
|
||||
<?php foreach($employees as $e): ?>
|
||||
|
||||
<option value="<?= $e->id ?>">
|
||||
|
||||
<?= $e->fingerprint_user_id ?>
|
||||
-
|
||||
<?= $e->full_name ?>
|
||||
|
||||
</option>
|
||||
|
||||
<?php endforeach; ?>
|
||||
|
||||
</select>
|
||||
|
||||
<label class="fw-semibold mt-2">
|
||||
Jenis Cuti / Izin
|
||||
</label>
|
||||
|
||||
<select class="form-control"
|
||||
id="leave_type">
|
||||
|
||||
<option value="annual">
|
||||
Cuti Tahunan
|
||||
</option>
|
||||
|
||||
<option value="sick">
|
||||
Sakit
|
||||
</option>
|
||||
|
||||
<option value="permit">
|
||||
Izin
|
||||
</option>
|
||||
|
||||
<option value="maternity">
|
||||
Cuti Melahirkan
|
||||
</option>
|
||||
|
||||
<option value="unpaid">
|
||||
Cuti Tidak Dibayar
|
||||
</option>
|
||||
|
||||
</select>
|
||||
|
||||
<div class="row">
|
||||
|
||||
<div class="col-md-6">
|
||||
|
||||
<label class="fw-semibold mt-2">
|
||||
Start Date
|
||||
</label>
|
||||
|
||||
<input type="date"
|
||||
class="form-control"
|
||||
id="start_date">
|
||||
|
||||
</div>
|
||||
|
||||
<div class="col-md-6">
|
||||
|
||||
<label class="fw-semibold mt-2">
|
||||
End Date
|
||||
</label>
|
||||
|
||||
<input type="date"
|
||||
class="form-control"
|
||||
id="end_date">
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<label class="fw-semibold mt-2">
|
||||
Approval Status
|
||||
</label>
|
||||
|
||||
<select class="form-control"
|
||||
id="approval_status">
|
||||
|
||||
<option value="pending">
|
||||
Pending
|
||||
</option>
|
||||
|
||||
<option value="approved">
|
||||
Approved
|
||||
</option>
|
||||
|
||||
<option value="rejected">
|
||||
Rejected
|
||||
</option>
|
||||
|
||||
</select>
|
||||
|
||||
<label class="fw-semibold mt-2">
|
||||
Reason
|
||||
</label>
|
||||
|
||||
<textarea class="form-control"
|
||||
id="reason"
|
||||
rows="4"></textarea>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="modal-footer">
|
||||
|
||||
<button class="btn btn-secondary"
|
||||
data-bs-dismiss="modal">
|
||||
|
||||
Batal
|
||||
|
||||
</button>
|
||||
|
||||
<button class="btn btn-warning"
|
||||
id="btnSimpan">
|
||||
|
||||
Simpan
|
||||
|
||||
</button>
|
||||
|
||||
</div>
|
||||
<div class="leave-metrics">
|
||||
<article><small>Semua Pengajuan</small><strong data-leave-count="all"><?=number_format($counts['all'],0,',','.')?></strong><span>Seluruh dokumen</span></article>
|
||||
<article><small>Draft</small><strong data-leave-count="draft"><?=number_format($counts['draft'],0,',','.')?></strong><span>Belum diajukan</span></article>
|
||||
<article class="metric-warning"><small>Menunggu Persetujuan</small><strong data-leave-count="submitted"><?=number_format($counts['submitted'],0,',','.')?></strong><span>Perlu tindakan HR</span></article>
|
||||
<article class="metric-success"><small>Disetujui</small><strong data-leave-count="approved"><?=number_format($counts['approved'],0,',','.')?></strong><span>Aktif pada kehadiran</span></article>
|
||||
</div>
|
||||
|
||||
<section class="card border-0 leave-card">
|
||||
<div class="card-body p-0">
|
||||
<nav class="leave-tabs" aria-label="Status pengajuan">
|
||||
<button type="button" class="active" data-status="">Semua <b data-tab-count="all"><?=$counts['all']?></b></button>
|
||||
<button type="button" data-status="draft">Draft <b data-tab-count="draft"><?=$counts['draft']?></b></button>
|
||||
<button type="button" data-status="submitted">Menunggu <b data-tab-count="submitted"><?=$counts['submitted']?></b></button>
|
||||
<button type="button" data-status="approved">Disetujui <b data-tab-count="approved"><?=$counts['approved']?></b></button>
|
||||
<button type="button" data-status="rejected">Ditolak <b data-tab-count="rejected"><?=$counts['rejected']?></b></button>
|
||||
</nav>
|
||||
<div class="leave-toolbar">
|
||||
<select id="filterEmployee" class="form-select select-search" data-placeholder="Semua karyawan"><option value="">Semua karyawan</option><?php foreach($employees as$employee):?><option value="<?=$employee->id?>"><?=html_escape(($employee->employee_code?:$employee->fingerprint_user_id).' - '.$employee->full_name)?></option><?php endforeach?></select>
|
||||
<select id="filterType" class="form-select"><option value="">Semua jenis</option><option value="annual">Cuti Tahunan</option><option value="sick">Sakit</option><option value="permit">Izin</option><option value="maternity">Cuti Melahirkan</option><option value="unpaid">Cuti Tidak Dibayar</option></select>
|
||||
<button type="button" class="btn btn-outline-secondary" id="refreshLeave"><i class="bi bi-arrow-clockwise"></i> Muat Ulang</button>
|
||||
</div>
|
||||
<div class="table-responsive">
|
||||
<table id="tableLeave" class="table align-middle w-100 mb-0">
|
||||
<thead><tr><th>Pengajuan</th><th>Karyawan</th><th>Jenis</th><th>Periode</th><th>Status</th><th>Diproses Oleh</th><th>Aksi</th></tr></thead>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<div class="modal fade" id="leaveModal" tabindex="-1" data-bs-backdrop="static">
|
||||
<div class="modal-dialog modal-dialog-centered modal-lg"><div class="modal-content">
|
||||
<div class="modal-header"><div><small class="text-muted">FORM PENGAJUAN</small><h5 class="modal-title">Buat Pengajuan Cuti / Izin</h5></div><button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Tutup"></button></div>
|
||||
<form id="leaveForm" data-ajax="true">
|
||||
<div class="modal-body">
|
||||
<input type="hidden" name="id" id="leaveId">
|
||||
<div id="rejectionNotice" class="alert alert-danger d-none"></div>
|
||||
<div class="row g-3">
|
||||
<div class="col-12"><label class="form-label">Karyawan <span class="text-danger">*</span></label><select class="form-select select-search" name="employee_id" id="employeeId" data-placeholder="Cari karyawan" required><option value=""></option><?php foreach($employees as$employee):?><option value="<?=$employee->id?>"><?=html_escape(($employee->employee_code?:$employee->fingerprint_user_id).' - '.$employee->full_name)?></option><?php endforeach?></select></div>
|
||||
<div class="col-md-6"><label class="form-label">Jenis Cuti / Izin <span class="text-danger">*</span></label><select class="form-select" name="leave_type" id="leaveType" required><option value="annual">Cuti Tahunan</option><option value="sick">Sakit</option><option value="permit">Izin</option><option value="maternity">Cuti Melahirkan</option><option value="unpaid">Cuti Tidak Dibayar</option></select></div>
|
||||
<div class="col-md-3"><label class="form-label">Tanggal Mulai <span class="text-danger">*</span></label><input type="date" class="form-control" name="start_date" id="startDate" required></div>
|
||||
<div class="col-md-3"><label class="form-label">Tanggal Selesai <span class="text-danger">*</span></label><input type="date" class="form-control" name="end_date" id="endDate" required></div>
|
||||
<div class="col-12"><label class="form-label">Alasan Pengajuan <span class="text-danger">*</span></label><textarea class="form-control" name="reason" id="leaveReason" rows="4" maxlength="2000" placeholder="Jelaskan kebutuhan cuti atau izin secara ringkas dan jelas" required></textarea><div class="form-text">Status persetujuan ditentukan melalui proses Ajukan dan tindakan approver, bukan dari form ini.</div></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer"><button type="button" class="btn btn-light" data-bs-dismiss="modal">Tutup</button><button type="submit" class="btn btn-warning" id="saveLeave"><i class="bi bi-save"></i> Simpan Draft</button></div>
|
||||
</form>
|
||||
</div></div>
|
||||
</div>
|
||||
|
||||
<div class="modal fade" id="leaveDetailModal" tabindex="-1">
|
||||
<div class="modal-dialog modal-dialog-centered modal-lg"><div class="modal-content">
|
||||
<div class="modal-header"><div><small class="text-muted">DETAIL & RIWAYAT</small><h5 class="modal-title" id="detailTitle">Pengajuan Cuti</h5></div><button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Tutup"></button></div>
|
||||
<div class="modal-body" id="leaveDetailBody"></div>
|
||||
<div class="modal-footer"><button type="button" class="btn btn-light" data-bs-dismiss="modal">Tutup</button></div>
|
||||
</div></div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
|
||||
$(function(){
|
||||
|
||||
let table = $('#tableLeave').DataTable({
|
||||
processing:true,
|
||||
responsive:true,
|
||||
autoWidth:false,
|
||||
ajax:{
|
||||
url:`<?= base_url(); ?>leaverequests/get_data`,
|
||||
dataSrc:'data'
|
||||
},
|
||||
order:[]
|
||||
});
|
||||
|
||||
// =====================================
|
||||
// RESET
|
||||
// =====================================
|
||||
function resetForm(){
|
||||
|
||||
$('#inputId').val('');
|
||||
$('#employee_id').val('');
|
||||
$('#leave_type').val('annual');
|
||||
$('#start_date').val('');
|
||||
$('#end_date').val('');
|
||||
$('#approval_status').val('pending');
|
||||
$('#reason').val('');
|
||||
|
||||
$('#modalLeave .modal-title')
|
||||
.text('Tambah Leave');
|
||||
}
|
||||
|
||||
// =====================================
|
||||
// ADD
|
||||
// =====================================
|
||||
$('.btn-add').click(function(){
|
||||
|
||||
resetForm();
|
||||
|
||||
$('#btnSimpan')
|
||||
.data('action','add');
|
||||
|
||||
$('#modalLeave').modal('show');
|
||||
|
||||
});
|
||||
|
||||
// =====================================
|
||||
// SAVE UPDATE
|
||||
// =====================================
|
||||
$('#btnSimpan').click(function(){
|
||||
|
||||
let action = $(this).data('action');
|
||||
|
||||
let data = {
|
||||
|
||||
id: $('#inputId').val(),
|
||||
|
||||
employee_id: $('#employee_id').val(),
|
||||
|
||||
leave_type: $('#leave_type').val(),
|
||||
|
||||
start_date: $('#start_date').val(),
|
||||
|
||||
end_date: $('#end_date').val(),
|
||||
|
||||
approval_status: $('#approval_status').val(),
|
||||
|
||||
reason: $('#reason').val()
|
||||
};
|
||||
|
||||
if(
|
||||
!data.employee_id ||
|
||||
!data.start_date ||
|
||||
!data.end_date
|
||||
){
|
||||
|
||||
Swal.fire(
|
||||
'Warning',
|
||||
'Data wajib diisi',
|
||||
'warning'
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
let url = action == 'add'
|
||||
? `<?= base_url(); ?>leaverequests/save`
|
||||
: `<?= base_url(); ?>leaverequests/update`;
|
||||
|
||||
$.ajax({
|
||||
url:url,
|
||||
type:'POST',
|
||||
data:data,
|
||||
dataType:'json',
|
||||
success:function(res){
|
||||
|
||||
if(res.status){
|
||||
|
||||
$('#modalLeave').modal('hide');
|
||||
|
||||
table.ajax.reload(null,false);
|
||||
|
||||
Swal.fire(
|
||||
'Sukses',
|
||||
res.message,
|
||||
'success'
|
||||
);
|
||||
|
||||
} else {
|
||||
|
||||
Swal.fire(
|
||||
'Error',
|
||||
res.message,
|
||||
'error'
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
// =====================================
|
||||
// EDIT
|
||||
// =====================================
|
||||
$(document).on('click','.btn-edit',function(){
|
||||
|
||||
let id = $(this).data('id');
|
||||
|
||||
$.get(
|
||||
`<?= base_url(); ?>leaverequests/detail/` + id,
|
||||
function(res){
|
||||
|
||||
$('#inputId').val(res.id);
|
||||
|
||||
$('#employee_id').val(res.employee_id);
|
||||
|
||||
$('#leave_type').val(res.leave_type);
|
||||
|
||||
$('#start_date').val(res.start_date);
|
||||
|
||||
$('#end_date').val(res.end_date);
|
||||
|
||||
$('#approval_status')
|
||||
.val(res.approval_status);
|
||||
|
||||
$('#reason').val(res.reason);
|
||||
|
||||
$('#modalLeave .modal-title')
|
||||
.text('Edit Leave');
|
||||
|
||||
$('#btnSimpan')
|
||||
.data('action','edit');
|
||||
|
||||
$('#modalLeave').modal('show');
|
||||
|
||||
},
|
||||
'json'
|
||||
);
|
||||
|
||||
});
|
||||
|
||||
// =====================================
|
||||
// DELETE
|
||||
// =====================================
|
||||
$(document).on('click','.btn-delete',function(){
|
||||
|
||||
let id = $(this).data('id');
|
||||
|
||||
Swal.fire({
|
||||
title:'Yakin hapus?',
|
||||
text:'Data tidak bisa dikembalikan',
|
||||
icon:'warning',
|
||||
showCancelButton:true
|
||||
}).then((result)=>{
|
||||
|
||||
if(result.isConfirmed){
|
||||
|
||||
$.get(
|
||||
`<?= base_url(); ?>leaverequests/delete/` + id,
|
||||
function(res){
|
||||
|
||||
if(res.status){
|
||||
|
||||
table.ajax.reload(null,false);
|
||||
|
||||
Swal.fire(
|
||||
'Sukses',
|
||||
res.message,
|
||||
'success'
|
||||
);
|
||||
}
|
||||
|
||||
},
|
||||
'json'
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
const permissions=<?=json_encode($permissions)?>,base='<?=base_url('leaverequests/')?>',csrf=()=>({[APP_CSRF.name]:APP_CSRF.value});
|
||||
const types={annual:'Cuti Tahunan',sick:'Sakit',permit:'Izin',maternity:'Cuti Melahirkan',unpaid:'Cuti Tidak Dibayar'};
|
||||
const statuses={draft:'Draft',submitted:'Menunggu Persetujuan',approved:'Disetujui',rejected:'Ditolak',cancelled:'Dibatalkan'};
|
||||
const esc=value=>$('<div>').text(value==null?'-':value).html();
|
||||
const date=value=>value?String(value).slice(0,10).split('-').reverse().join('/'):'-';
|
||||
const badge=status=>'<span class="leave-status leave-status-'+esc(status)+'">'+esc(statuses[status]||status)+'</span>';
|
||||
const toast=(message,icon)=>AppAlert.toast(message,icon||'success');
|
||||
function fail(xhr){let message=xhr.responseJSON&&xhr.responseJSON.message;if(!message&&xhr.statusText==='timeout')message='Waktu proses habis. Silakan coba kembali.';toast(message||'Proses tidak berhasil.','error')}
|
||||
function post(url,data){return $.ajax({url:url,type:'POST',data:Object.assign({},data||{},csrf()),dataType:'json',timeout:30000})}
|
||||
function actions(row){let out='<div class="d-flex flex-wrap gap-1"><button type="button" class="btn btn-sm btn-outline-primary leave-detail" data-id="'+row.id+'"><i class="bi bi-eye"></i> Detail</button>';if((row.workflow_status==='draft'||row.workflow_status==='rejected')&&permissions.update)out+='<button type="button" class="btn btn-sm btn-outline-secondary leave-edit" data-id="'+row.id+'"><i class="bi bi-pencil"></i> Edit</button>';if(row.workflow_status==='draft'&&permissions.create)out+='<button type="button" class="btn btn-sm btn-warning leave-submit" data-id="'+row.id+'"><i class="bi bi-send"></i> Ajukan</button>';if(row.workflow_status==='submitted'&&permissions.approve)out+='<button type="button" class="btn btn-sm btn-success leave-approve" data-id="'+row.id+'"><i class="bi bi-check-lg"></i> Setujui</button><button type="button" class="btn btn-sm btn-outline-danger leave-reject" data-id="'+row.id+'"><i class="bi bi-x-lg"></i> Tolak</button>';if((row.workflow_status==='draft'||row.workflow_status==='rejected')&&(permissions.update||permissions.create))out+='<button type="button" class="btn btn-sm btn-outline-danger leave-cancel" data-id="'+row.id+'" title="Batalkan"><i class="bi bi-trash"></i></button>';return out+'</div>'}
|
||||
const table=$('#tableLeave').DataTable({processing:true,responsive:true,autoWidth:false,pageLength:25,order:[],ajax:{url:base+'get_data',data:d=>{d.status=$('.leave-tabs button.active').data('status')||'';d.type=$('#filterType').val();d.employee_id=$('#filterEmployee').val()},dataSrc:function(response){updateCounts(response.summary||{});return response.data||[]}},columns:[{data:'request_no',render:(value,type,row)=>'<button type="button" class="btn btn-link p-0 fw-semibold leave-detail" data-id="'+row.id+'">'+esc(value)+'</button><small class="d-block text-muted">Dibuat '+esc(row.creator_name||'-')+'</small>'},{data:'full_name',render:(value,type,row)=>'<strong>'+esc(value)+'</strong><small class="d-block text-muted">'+esc(row.employee_code||row.fingerprint_user_id)+' · '+esc(row.department_name||'-')+'</small>'},{data:'leave_type',render:value=>types[value]||value},{data:null,render:row=>date(row.start_date)+' – '+date(row.end_date)+'<small class="d-block text-muted">'+Number(row.total_days||0).toLocaleString('id-ID')+' hari</small>'},{data:'workflow_status',render:(value,type,row)=>badge(value)+(value==='rejected'&&row.rejection_reason?'<small class="d-block text-danger mt-1">'+esc(row.rejection_reason)+'</small>':'')},{data:null,render:row=>row.workflow_status==='approved'?esc(row.approver_name||'-'):row.workflow_status==='rejected'?esc(row.rejector_name||'-'):row.workflow_status==='submitted'?'<span class="text-warning-emphasis">Menunggu HR</span>':'-'},{data:null,orderable:false,searchable:false,render:actions}],language:{search:'Cari:',lengthMenu:'Tampilkan _MENU_',info:'_START_–_END_ dari _TOTAL_',infoEmpty:'Belum ada pengajuan',zeroRecords:'Pengajuan tidak ditemukan',processing:'Memuat data...',paginate:{previous:'Sebelumnya',next:'Berikutnya'}}});
|
||||
function updateCounts(summary){Object.keys(summary).forEach(key=>{$('[data-leave-count="'+key+'"]').text(Number(summary[key]||0).toLocaleString('id-ID'));$('[data-tab-count="'+key+'"]').text(Number(summary[key]||0).toLocaleString('id-ID'))})}
|
||||
function reload(){table.ajax.reload(null,false)}
|
||||
$('.leave-tabs button').on('click',function(){$('.leave-tabs button').removeClass('active');$(this).addClass('active');reload()});
|
||||
$('#filterEmployee,#filterType').on('change',reload);$('#refreshLeave').on('click',reload);
|
||||
function resetForm(){$('#leaveForm')[0].reset();$('#leaveId').val('');$('#employeeId').val(null).trigger('change');$('#leaveType').val('annual');$('#rejectionNotice').addClass('d-none').empty();$('#leaveModal .modal-title').text('Buat Pengajuan Cuti / Izin')}
|
||||
$('.btn-add-leave').on('click',function(){resetForm();bootstrap.Modal.getOrCreateInstance(document.getElementById('leaveModal')).show()});
|
||||
$('#leaveForm').on('submit',function(event){event.preventDefault();let button=$('#saveLeave').prop('disabled',true).html('<span class="spinner-border spinner-border-sm"></span> Menyimpan');$.ajax({url:base+'save',type:'POST',data:$(this).serialize(),dataType:'json',timeout:30000}).done(response=>{bootstrap.Modal.getInstance(document.getElementById('leaveModal')).hide();reload();toast(response.message,'success')}).fail(fail).always(()=>button.prop('disabled',false).html('<i class="bi bi-save"></i> Simpan Draft'))});
|
||||
$(document).on('click','.leave-edit',function(){let id=$(this).data('id');$.get(base+'detail/'+id).done(response=>{let row=response.leave;resetForm();$('#leaveId').val(row.id);$('#employeeId').val(String(row.employee_id)).trigger('change');$('#leaveType').val(row.leave_type);$('#startDate').val(row.start_date);$('#endDate').val(row.end_date);$('#leaveReason').val(row.reason);if(row.rejection_reason)$('#rejectionNotice').removeClass('d-none').html('<strong>Alasan penolakan:</strong> '+esc(row.rejection_reason));$('#leaveModal .modal-title').text('Perbaiki '+row.request_no);bootstrap.Modal.getOrCreateInstance(document.getElementById('leaveModal')).show()}).fail(fail)});
|
||||
$(document).on('click','.leave-detail',function(){let id=$(this).data('id');$('#leaveDetailBody').html('<div class="text-center py-5"><span class="spinner-border text-warning"></span><p class="mt-2 mb-0">Memuat detail...</p></div>');bootstrap.Modal.getOrCreateInstance(document.getElementById('leaveDetailModal')).show();$.get(base+'detail/'+id).done(response=>{let row=response.leave,history=(response.history||[]).map(item=>'<li><span class="leave-history-dot"></span><div><strong>'+esc({submitted:'Diajukan',approved:'Disetujui',rejected:'Ditolak',cancelled:'Dibatalkan'}[item.action]||item.action)+'</strong><small>'+esc(item.user_name||'-')+' · '+esc(item.created_at)+'</small>'+(item.notes?'<p>'+esc(item.notes)+'</p>':'')+'</div></li>').join('');$('#detailTitle').text(row.request_no);$('#leaveDetailBody').html('<div class="leave-detail-grid"><span>Karyawan<strong>'+esc(row.full_name)+'</strong><small>'+esc(row.employee_code||row.fingerprint_user_id)+'</small></span><span>Jenis<strong>'+esc(types[row.leave_type]||row.leave_type)+'</strong></span><span>Periode<strong>'+date(row.start_date)+' – '+date(row.end_date)+'</strong><small>'+esc(row.total_days)+' hari</small></span><span>Status<strong>'+badge(row.workflow_status)+'</strong></span><span>Diajukan oleh<strong>'+esc(row.submitter_name||'-')+'</strong><small>'+esc(row.submitted_at||'-')+'</small></span><span>Disetujui oleh<strong>'+esc(row.approver_name||'-')+'</strong><small>'+esc(row.approved_at||'-')+'</small></span></div><div class="leave-reason"><small>ALASAN PENGAJUAN</small><p>'+esc(row.reason)+'</p></div>'+(row.rejection_reason?'<div class="alert alert-danger"><strong>Alasan penolakan</strong><br>'+esc(row.rejection_reason)+'</div>':'')+'<h6 class="mt-4">Riwayat Persetujuan</h6><ul class="leave-history">'+(history||'<li><span class="leave-history-dot"></span><div><strong>Draft dibuat</strong><small>'+esc(row.creator_name||'-')+' · '+esc(row.created_at)+'</small></div></li>')+'</ul>')}).fail(fail)});
|
||||
$(document).on('click','.leave-submit',function(){let id=$(this).data('id'),button=$(this),original=button.html();AppAlert.confirm({title:'Ajukan cuti / izin?',text:'Setelah diajukan, data tidak dapat diedit sampai diputuskan oleh approver.',confirmButtonText:'Ya, Ajukan'}).then(result=>{if(!result.isConfirmed)return;button.prop('disabled',true).html('<span class="spinner-border spinner-border-sm"></span> Memproses');post(base+'submit/'+id).done(response=>{reload();toast(response.message,'success')}).fail(fail).always(()=>button.prop('disabled',false).html(original))})});
|
||||
$(document).on('click','.leave-approve',function(){let id=$(this).data('id');AppAlert.prompt({title:'Setujui pengajuan?',input:'textarea',inputLabel:'Catatan approver (opsional)',confirmButtonText:'Setujui',icon:'question'}).then(result=>{if(result.isConfirmed)post(base+'approve/'+id,{notes:result.value||''}).done(response=>{reload();toast(response.message,'success')}).fail(fail)})});
|
||||
$(document).on('click','.leave-reject',function(){let id=$(this).data('id');AppAlert.prompt({title:'Tolak pengajuan?',input:'textarea',inputLabel:'Alasan penolakan',inputPlaceholder:'Jelaskan alasan agar pengajuan dapat diperbaiki',inputValidator:value=>!String(value||'').trim()?'Alasan penolakan wajib diisi.':undefined,confirmButtonText:'Tolak Pengajuan',icon:'warning'}).then(result=>{if(result.isConfirmed)post(base+'reject/'+id,{reason:result.value}).done(response=>{reload();toast(response.message,'success')}).fail(fail)})});
|
||||
$(document).on('click','.leave-cancel',function(){let id=$(this).data('id');AppAlert.confirm({title:'Batalkan Draft?',text:'Dokumen tetap disimpan sebagai histori dan tidak memengaruhi kehadiran.',confirmButtonText:'Ya, Batalkan'}).then(result=>{if(result.isConfirmed)post(base+'cancel/'+id).done(response=>{reload();toast(response.message,'success')}).fail(fail)})});
|
||||
const focus=new URLSearchParams(location.search).get('focus');if(focus)table.one('draw.dt',()=>setTimeout(()=>$('.leave-detail[data-id="'+String(focus).replace(/[^0-9]/g,'')+'"]').first().trigger('click'),100));
|
||||
});
|
||||
|
||||
</script>
|
||||
</script>
|
||||
|
||||
Reference in New Issue
Block a user