2024-12-12 18:18:26 +07:00
@ extends ( 'layouts.app' )
@ section ( 'title' )
2026-06-01 15:01:03 +07:00
Dashboard
2024-12-12 18:18:26 +07:00
@ endsection
@ section ( 'admin-content' )
2025-10-13 14:55:46 +07:00
< script src = " https://cdn.jsdelivr.net/npm/sweetalert2@11 " ></ script >
2026-06-01 15:01:03 +07:00
< script src = " https://cdn.jsdelivr.net/npm/autonumeric@4.6.0/dist/autoNumeric.min.js " ></ script >
2024-12-12 18:18:26 +07:00
< section class = " content-header " >
< div class = " container-fluid " >
< div class = " row mb-2 " >
< div class = " col-sm-6 " >
< h1 > Edit Expense Up Country </ h1 >
</ div >
< div class = " col-sm-6 " >
< ol class = " breadcrumb float-sm-right " >
< li class = " breadcrumb-item " >< a href = " { { route('dashboard.index') }} " > Dashboard </ a ></ li >
</ ol >
</ div >
</ div >
</ div >
</ section >
2026-06-01 15:01:03 +07:00
2025-01-17 16:39:37 +07:00
< style >
#loading-spinner-overlay {
position : fixed ;
top : 0 ;
left : 0 ;
width : 100 % ;
height : 100 % ;
2026-06-01 15:01:03 +07:00
background - color : rgba ( 0 , 0 , 0 , 0.5 );
z - index : 9999 ;
2025-01-17 16:39:37 +07:00
display : flex ;
justify - content : center ;
align - items : center ;
}
. spinner - wrapper {
text - align : center ;
color : white ;
}
</ style >
2026-06-01 15:01:03 +07:00
2025-10-23 17:21:46 +07:00
@ php
$attachmentCategoryLabels = $attachmentCategoryLabels ? ? ( $upCountryAttachmentCategories ? ? []);
$attachmentCategories = $attachmentCategories ? ? ( $upCountryAttachmentCategoryKeys ? ? array_keys ( $attachmentCategoryLabels ));
@ endphp
2026-06-01 15:01:03 +07:00
2024-12-12 18:18:26 +07:00
< section class = " content " >
< div class = " container-fluid " >
< div class = " card card-primary card-outline " >
< div class = " card-body " >
2026-06-01 15:01:03 +07:00
< form id = " expense-form " method = " POST " action = " { { route('forms.up-country.update', $form->id ) }} " enctype = " multipart/form-data " >
2024-12-16 17:01:55 +07:00
@ csrf
@ method ( 'PUT' )
@ include ( 'backend.layouts.partials.messages' )
2024-12-12 18:18:26 +07:00
< div class = " row " >
< div class = " col-lg-6 " >
< div class = " mb-3 " >
2025-01-03 21:37:58 +07:00
< label class = " form-label " > Pilih Rayon < span class = " font-italic font-weight-normal " > ( required ) </ span ></ label >
2024-12-16 17:01:55 +07:00
< select class = " form-control form-control-md " name = " rayon_id " required >
2024-12-12 18:18:26 +07:00
< option value = " " > Pilih Rayon </ option >
@ foreach ( $rayons as $rayon )
2025-10-23 17:21:46 +07:00
< option value = " { { $rayon->id }} " {{ $form -> rayon_id == $rayon -> id ? 'selected' : '' }} >
{{ $rayon -> name }}{{ $rayon -> cabang ? ' - ' . $rayon -> cabang -> name : '' }}
</ option >
2024-12-12 18:18:26 +07:00
@ endforeach
</ select >
</ div >
< div class = " mb-3 " >
2025-01-03 21:37:58 +07:00
< label class = " form-label " > Tanggal < span class = " font-italic font-weight-normal " > ( required ) </ span ></ label >
2026-06-01 15:01:03 +07:00
< input type = " date " class = " form-control " name = " tanggal " required
value = " { { old('tanggal', !empty( $form->tanggal ) ? date('Y-m-d', strtotime( $form->tanggal )) : '') }} " >
2024-12-12 18:18:26 +07:00
</ div >
< div class = " mb-3 " >
2025-01-03 21:37:58 +07:00
< label class = " form-label " > Tujuan < span class = " font-italic font-weight-normal " > ( required ) </ span ></ label >
2024-12-16 17:01:55 +07:00
< input type = " text " class = " form-control " name = " tujuan " required value = " { { $form->tujuan }} " >
2024-12-12 18:18:26 +07:00
</ div >
< div class = " mb-3 " >
2025-01-03 21:37:58 +07:00
< label class = " form-label " > Jarak ( km ) < span class = " font-italic font-weight-normal " > ( required ) </ span ></ label >
2024-12-16 17:01:55 +07:00
< input type = " number " class = " form-control " name = " jarak " required value = " { { $form->jarak }} " >
2024-12-12 18:18:26 +07:00
</ div >
< div class = " mb-3 " >
2025-01-03 21:37:58 +07:00
< label class = " form-label " > Allowance < span class = " font-italic font-weight-normal " > ( optional ) </ span ></ label >
2026-06-01 15:01:03 +07:00
< input type = " text " class = " form-control " name = " allowance " id = " allowance " value = " { { $form->allowance }} " >
2024-12-12 18:18:26 +07:00
</ div >
</ div >
< div class = " col-lg-6 " >
< div class = " mb-3 " >
2025-01-03 21:37:58 +07:00
< label class = " form-label " > Transport Dalam Kota < span class = " font-italic font-weight-normal " > ( optional ) </ span ></ label >
2026-06-01 15:01:03 +07:00
< input type = " text " class = " form-control " name = " transport_dalkot " id = " transport_dalkot " value = " { { $form->transport_dalkot }} " >
2025-01-03 21:37:58 +07:00
</ div >
2024-12-12 18:18:26 +07:00
< div class = " mb-3 " >
2025-01-03 21:37:58 +07:00
< label class = " form-label " > Transport Antar Kota < span class = " font-italic font-weight-normal " > ( optional ) </ span ></ label >
2026-06-01 15:01:03 +07:00
< input type = " text " class = " form-control " name = " transport_ankot " id = " transport_ankot " value = " { { $form->transport_ankot }} " >
2024-12-12 18:18:26 +07:00
</ div >
< div class = " mb-3 " >
2025-01-03 21:37:58 +07:00
< label class = " form-label " > Hotel < span class = " font-italic font-weight-normal " > ( optional ) </ span ></ label >
2026-06-01 15:01:03 +07:00
< input type = " text " class = " form-control " name = " hotel " id = " hotel " value = " { { $form->hotel }} " >
2024-12-12 18:18:26 +07:00
</ div >
2025-10-13 14:55:46 +07:00
</ div >
< div class = " col-lg-12 " >
< div class = " mb-4 " >
2025-10-23 17:21:46 +07:00
< label class = " form-label mb-0 " > Lampiran Tersimpan </ label >
< p class = " text-muted small mt-1 mb-2 " > Pratinjau , unduh , atau hapus lampiran yang telah diunggah sebelumnya .</ p >
2025-10-13 14:55:46 +07:00
< div class = " table-responsive " >
< table class = " table table-bordered align-middle " id = " existing-attachments-table " >
< thead class = " table-light " >
< tr >
2025-10-23 17:21:46 +07:00
< th style = " width: 30% " > Kategori Lampiran </ th >
< th style = " width: 30% " > Nama File </ th >
< th style = " width: 15% " class = " text-center " > Pratinjau </ th >
< th style = " width: 15% " class = " text-center " > Unduh </ th >
< th style = " width: 10% " class = " text-center " > Aksi </ th >
2025-10-13 14:55:46 +07:00
</ tr >
</ thead >
< tbody >
@ forelse ( $attachments as $attachment )
@ php
$categoryValue = $attachment [ 'file_category' ] ? ? null ;
2025-10-23 17:21:46 +07:00
$categoryLabel = $categoryValue
? ( $attachmentCategoryLabels [ $categoryValue ] ? ? ucwords ( str_replace ( '_' , ' ' , $categoryValue )))
: '-' ;
2025-10-13 14:55:46 +07:00
@ endphp
< tr data - attachment - id = " { { $attachment['id'] }} " >
< td > {{ $categoryLabel }} </ td >
< td > {{ $attachment [ 'filename' ] ? ? basename ( $attachment [ 'file_path' ]) }} </ td >
< td class = " text-center " >
< button type = " button "
class = " btn btn-sm btn-outline-secondary preview-existing-attachment "
data - preview - url = " { { $attachment['preview_url'] }} "
data - download - url = " { { $attachment['download_url'] }} "
data - preview - type = " { { $attachment['preview_type'] }} "
data - category = " { { $categoryLabel }} " >
2025-10-23 17:21:46 +07:00
Pratinjau
2025-10-13 14:55:46 +07:00
</ button >
</ td >
< td class = " text-center " >
< a href = " { { $attachment['download_url'] }} "
target = " _blank "
class = " btn btn-sm btn-outline-primary " >
2025-10-23 17:21:46 +07:00
Unduh
2025-10-13 14:55:46 +07:00
</ a >
</ td >
< td class = " text-center " >
< button type = " button "
class = " btn btn-sm btn-outline-danger delete-attachment "
data - delete - url = " { { route('forms.up-country.attachments.destroy', [ $form->id , $attachment['id'] ]) }} " >
< i class = " fas fa-trash " ></ i >
</ button >
</ td >
</ tr >
@ empty
< tr class = " existing-attachments-empty text-center text-muted " >
< td colspan = " 5 " > Belum ada lampiran tersimpan .</ td >
</ tr >
@ endforelse
</ tbody >
</ table >
</ div >
</ div >
</ div >
< div class = " col-lg-12 " >
2024-12-12 18:18:26 +07:00
< div class = " mb-3 " >
2025-10-13 14:55:46 +07:00
< div class = " d-flex align-items-center justify-content-between " >
2025-10-23 17:21:46 +07:00
< label class = " form-label mb-0 " > Tambah Lampiran Baru </ label >
2025-10-13 14:55:46 +07:00
< button type = " button " class = " btn btn-outline-primary btn-sm " id = " add-new-attachment-row " >
2025-10-23 17:21:46 +07:00
< i class = " fas fa-plus me-1 " ></ i > Tambah Lampiran
2025-10-13 14:55:46 +07:00
</ button >
</ div >
< p class = " text-muted small mt-1 mb-2 " >
2025-10-23 17:21:46 +07:00
Format file yang diperbolehkan : JPG , JPEG , PNG , atau PDF . Ukuran maksimum 5 MB per file .
2025-10-13 14:55:46 +07:00
</ p >
< div class = " table-responsive " >
< table class = " table table-bordered align-middle " id = " new-attachments-table " >
< thead class = " table-light " >
< tr >
2025-10-23 17:21:46 +07:00
< th style = " width: 30% " > Kategori Lampiran </ th >
< th style = " width: 45% " > Lampiran </ th >
< th style = " width: 15% " class = " text-center " > Pratinjau </ th >
< th style = " width: 10% " class = " text-center " > Aksi </ th >
2025-10-13 14:55:46 +07:00
</ tr >
</ thead >
< tbody >
< tr class = " new-attachments-empty text-center text-muted " >
< td colspan = " 4 " > Belum ada lampiran baru .</ td >
</ tr >
</ tbody >
</ table >
</ div >
2024-12-12 18:18:26 +07:00
</ div >
</ div >
2025-06-18 19:15:53 +07:00
< div class = " col-lg-12 " >
< div class = " mb-3 " >
< label class = " form-label " > UC Plan < span class = " font-italic font-weight-normal " > ( optional ) </ span ></ label >
< input type = " file " class = " form-control " name = " uc_plan " value = " { { old('uc_plan') }} " >
</ div >
</ div >
2024-12-16 17:01:55 +07:00
< button type = " submit " class = " btn btn-primary ml-2 " > Save </ button >
2024-12-12 18:18:26 +07:00
</ div >
2026-06-01 15:01:03 +07:00
</ form >
2025-01-17 16:39:37 +07:00
2025-10-13 14:55:46 +07:00
@ include ( 'backend.components.attachment-preview-modal' , [
'modalId' => 'existingAttachmentPreviewModal' ,
2025-10-23 17:21:46 +07:00
'title' => 'Pratinjau Lampiran' ,
2025-10-13 14:55:46 +07:00
])
@ include ( 'backend.components.attachment-preview-modal' , [
'modalId' => 'newAttachmentPreviewModal' ,
2025-10-23 17:21:46 +07:00
'title' => 'Pratinjau Lampiran' ,
2025-10-13 14:55:46 +07:00
])
2025-01-17 16:39:37 +07:00
< div id = " loading-spinner-overlay " class = " d-none " >
< div class = " spinner-wrapper " >
< div class = " spinner-border text-primary " role = " status " >
</ div >
2026-06-01 15:01:03 +07:00
< p class = " mt-2 " > Sedang mengirim , mohon tunggu ...</ p >
2025-01-17 16:39:37 +07:00
</ div >
</ div >
2024-12-12 18:18:26 +07:00
</ div >
</ div >
</ div >
</ section >
2025-01-02 13:12:42 +07:00
< script >
2026-06-01 15:01:03 +07:00
$ ( document ) . ready ( function () {
try {
// ==========================================
// 1. INISIALISASI AUTONUMERIC ASLI (KEMBALI NORMAL & ANTI MINUS)
// ==========================================
const autoNumericConfig = {
digitGroupSeparator : '.' ,
decimalCharacter : ',' ,
currencySymbol : 'Rp. ' ,
decimalPlaces : 0 ,
minimumValue : '0' , // Mencegah nilai minus
unformatOnSubmit : true // Mengirimkan angka bersih ke backend
};
2025-01-02 13:12:42 +07:00
2026-06-01 15:01:03 +07:00
const allowanceInput = new AutoNumeric ( '#allowance' , autoNumericConfig );
const dalkotInput = new AutoNumeric ( '#transport_dalkot' , autoNumericConfig );
const ankotInput = new AutoNumeric ( '#transport_ankot' , autoNumericConfig );
const hotelInput = new AutoNumeric ( '#hotel' , autoNumericConfig );
2025-01-02 13:12:42 +07:00
2026-06-01 15:01:03 +07:00
// ==========================================
// 2. SOLUSI FIX SCROLLING: Blokir Paksa Menggunakan jQuery Native
// ==========================================
$ ( '#allowance, #transport_dalkot, #transport_ankot, #hotel' ) . on ( 'wheel font-wheel' , function ( e ) {
e . preventDefault ();
$ ( this ) . blur (); // Melepas fokus kursor saat roda scroll digerakkan
});
2025-01-17 16:39:37 +07:00
2025-10-13 14:55:46 +07:00
2026-06-01 15:01:03 +07:00
// ==========================================
// 3. LOGIKA MULTI UPLOAD ATTACHMENT
// ==========================================
const attachmentCategories = @ json ( $attachmentCategories ? ? ( $upCountryAttachmentCategoryKeys ? ? []));
const attachmentCategoryLabels = @ json ( $attachmentCategoryLabels ? ? ( $upCountryAttachmentCategories ? ? []));
const fileAccept = '.jpg,.jpeg,.png,.pdf' ;
let attachmentIndex = 0 ;
let newAttachmentsTableBody = $ ( '#new-attachments-table tbody' );
let existingAttachmentsTableBody = $ ( '#existing-attachments-table tbody' );
let emptyNewRowMarkup = `<tr class="new-attachments-empty text-center text-muted"><td colspan="4">Belum ada lampiran baru.</td></tr>` ;
let emptyExistingRowMarkup = `<tr class="existing-attachments-empty text-center text-muted"><td colspan="5">Belum ada lampiran tersimpan.</td></tr>` ;
const csrfToken = $ ( 'meta[name="csrf-token"]' ) . attr ( 'content' );
if ( csrfToken ) {
$ . ajaxSetup ({
headers : {
'X-CSRF-TOKEN' : csrfToken
}
});
}
2025-10-23 17:21:46 +07:00
2026-06-01 15:01:03 +07:00
function categoryToLabel ( value ) {
if ( ! value ) return 'Pilih Kategori' ;
if ( attachmentCategoryLabels && attachmentCategoryLabels [ value ]) {
return attachmentCategoryLabels [ value ];
}
return value . replace ( / _ / g , ' ' ) . replace ( / \b\w / g , ( char ) => char . toUpperCase ());
}
2025-10-13 14:55:46 +07:00
2026-06-01 15:01:03 +07:00
function buildCategoryOptions () {
return attachmentCategories
. map (( category ) => `<option value="${category}">${categoryToLabel(category)}</option>` )
. join ( '' );
}
2025-10-13 14:55:46 +07:00
2026-06-01 15:01:03 +07:00
function resetInlinePreview ( $row ) {
$row . find ( '.attachment-inline-preview' )
. removeClass ( 'bg-light' )
. html ( '<i class="fas fa-file-upload text-muted"></i>' );
}
2025-10-13 14:55:46 +07:00
2026-06-01 15:01:03 +07:00
function clearRowData ( $row ) {
const existingUrl = $row . data ( 'objectUrl' );
if ( existingUrl ) {
URL . revokeObjectURL ( existingUrl );
}
$row . removeData ( 'objectUrl' );
$row . removeData ( 'previewType' );
$row . removeData ( 'previewSource' );
resetInlinePreview ( $row );
$row . find ( '.preview-new-attachment' ) . addClass ( 'd-none' );
$row . find ( '.preview-filename' ) . text ( '' );
}
2025-10-13 14:55:46 +07:00
2026-06-01 15:01:03 +07:00
window . addAttachmentRow = function () {
if ( ! newAttachmentsTableBody ) return ;
2025-10-13 14:55:46 +07:00
2026-06-01 15:01:03 +07:00
if ( newAttachmentsTableBody . find ( '.new-attachments-empty' ) . length ) {
newAttachmentsTableBody . empty ();
}
2025-10-13 14:55:46 +07:00
2026-06-01 15:01:03 +07:00
const index = attachmentIndex ++ ;
const row = $ ( `
<tr class="attachment-row" data-index="${index}">
<td>
<select class="form-control attachment-category" name="attachments[${index}][file_category]" required>
<option value="">${categoryToLabel('')}</option>
${buildCategoryOptions()}
</select>
</td>
<td>
<div class="d-flex align-items-center gap-2">
<div class="attachment-inline-preview border rounded d-flex align-items-center justify-content-center bg-white" style="width: 56px; height: 56px;">
<i class="fas fa-file-upload text-muted"></i>
</div>
<input type="file" class="form-control attachment-file" name="attachments[${index}][file_path]" accept="${fileAccept}" required>
</div>
<div class="small text-muted mt-1 preview-filename"></div>
</td>
<td class="text-center">
<button type="button" class="btn btn-sm btn-outline-secondary preview-new-attachment d-none" data-modal="#newAttachmentPreviewModal">
Pratinjau
</button>
</td>
<td class="text-center">
<button type="button" class="btn btn-sm btn-outline-danger remove-attachment-row">
<i class="fas fa-trash"></i>
</button>
</td>
</tr>
` );
newAttachmentsTableBody . append ( row );
}
2025-10-13 14:55:46 +07:00
2026-06-01 15:01:03 +07:00
function removeAttachmentRow ( button ) {
if ( ! newAttachmentsTableBody ) return ;
2025-10-13 14:55:46 +07:00
2026-06-01 15:01:03 +07:00
const $row = $ ( button ) . closest ( 'tr' );
clearRowData ( $row );
$row . remove ();
2025-10-13 14:55:46 +07:00
2026-06-01 15:01:03 +07:00
if ( ! newAttachmentsTableBody . find ( '.attachment-row' ) . length ) {
newAttachmentsTableBody . html ( emptyNewRowMarkup );
}
}
2025-10-13 14:55:46 +07:00
2026-06-01 15:01:03 +07:00
function setInlinePreview ( $row , type , source ) {
const previewBox = $row . find ( '.attachment-inline-preview' );
if ( type === 'image' && source ) {
previewBox
. html ( `<img src="${source}" class="img-thumbnail" style="width: 100%; height: 100%; object-fit: cover;" alt="Pratinjau lampiran">` )
. addClass ( 'bg-light' );
} else if ( type === 'pdf' ) {
previewBox
. html ( '<i class="fas fa-file-pdf text-danger fa-lg"></i>' )
. addClass ( 'bg-light' );
} else {
resetInlinePreview ( $row );
}
}
2025-10-13 14:55:46 +07:00
2026-06-01 15:01:03 +07:00
function openAttachmentModal ( modalSelector , title , type , source ) {
const $modal = $ ( modalSelector );
const $image = $modal . find ( '.attachment-preview-image' );
const $object = $modal . find ( '.attachment-preview-object' );
const $placeholder = $modal . find ( '.attachment-preview-placeholder' );
$modal . find ( '.attachment-preview-modal-title' ) . text ( title || 'Lampiran' );
$image . addClass ( 'd-none' ) . attr ( 'src' , '' );
$object . addClass ( 'd-none' ) . attr ( 'data' , '' ) . attr ( 'src' , '' );
$placeholder . removeClass ( 'd-none' );
if ( type === 'image' && source ) {
$image . attr ( 'src' , source ) . removeClass ( 'd-none' );
$placeholder . addClass ( 'd-none' );
} else if ( type === 'pdf' && source ) {
$object . attr ( 'data' , source ) . attr ( 'src' , source ) . removeClass ( 'd-none' );
$placeholder . addClass ( 'd-none' );
}
2025-10-13 14:55:46 +07:00
2026-06-01 15:01:03 +07:00
if ( window . bootstrap && bootstrap . Modal && typeof bootstrap . Modal . getOrCreateInstance === 'function' ) {
bootstrap . Modal . getOrCreateInstance ( $modal [ 0 ]) . show ();
} else {
$modal . modal ( 'show' );
}
}
2025-10-13 14:55:46 +07:00
2026-06-01 15:01:03 +07:00
function previewFile ( input ) {
const $input = $ ( input );
const $row = $input . closest ( 'tr' );
const previewButton = $row . find ( '.preview-new-attachment' );
const filenameHolder = $row . find ( '.preview-filename' );
2025-10-13 14:55:46 +07:00
2026-06-01 15:01:03 +07:00
clearRowData ( $row );
2025-10-13 14:55:46 +07:00
2026-06-01 15:01:03 +07:00
const file = input . files && input . files [ 0 ];
if ( ! file ) {
return ;
}
2025-10-13 14:55:46 +07:00
2026-06-01 15:01:03 +07:00
filenameHolder . text ( file . name );
const extension = file . name . split ( '.' ) . pop () . toLowerCase ();
if ([ 'jpg' , 'jpeg' , 'png' ] . includes ( extension )) {
const reader = new FileReader ();
reader . onload = function ( event ) {
const source = event . target . result ;
$row . data ( 'previewType' , 'image' );
$row . data ( 'previewSource' , source );
setInlinePreview ( $row , 'image' , source );
previewButton . removeClass ( 'd-none' );
};
reader . readAsDataURL ( file );
} else {
const objectUrl = URL . createObjectURL ( file );
$row . data ( 'previewType' , 'pdf' );
$row . data ( 'previewSource' , objectUrl );
$row . data ( 'objectUrl' , objectUrl );
setInlinePreview ( $row , 'pdf' );
previewButton . removeClass ( 'd-none' );
}
}
2025-10-13 14:55:46 +07:00
2026-06-01 15:01:03 +07:00
// ==========================================
// 4. INTERCEPTOR FORM SUBMIT & SWEETALERT (> 1 JUTA)
// ==========================================
const spinnerOverlay = $ ( '#loading-spinner-overlay' );
$ ( '#expense-form' ) . on ( 'submit' , function ( e ) {
e . preventDefault ();
const form = this ;
const allowance = allowanceInput . getNumber () || 0 ;
const transportDalkot = dalkotInput . getNumber () || 0 ;
const transportAnkot = ankotInput . getNumber () || 0 ;
const hotel = hotelInput . getNumber () || 0 ;
const totalExpense = allowance + transportDalkot + transportAnkot + hotel ;
if ( totalExpense > 1000000 ) {
Swal . fire ({
title : 'Nominal Melebihi Batas Expense!' ,
text : `Total pengajuan Anda adalah Rp ${new Intl.NumberFormat('id-ID').format(totalExpense)}. Jumlah ini melebihi batas standar Rp 1.000.000. Apakah yakin tetap ajukan?` ,
icon : 'warning' ,
showCancelButton : true ,
confirmButtonColor : '#3085d6' ,
cancelButtonColor : '#d33' ,
confirmButtonText : 'Yes, Tetap Ajukan!' ,
cancelButtonText : 'No, Batalkan'
}) . then (( result ) => {
if ( result . isConfirmed ) {
spinnerOverlay . removeClass ( 'd-none' ) . addClass ( 'd-flex' );
form . submit ();
}
});
} else {
spinnerOverlay . removeClass ( 'd-none' ) . addClass ( 'd-flex' );
form . submit ();
}
});
2025-10-13 14:55:46 +07:00
2026-06-01 15:01:03 +07:00
// Event Listeners DOM
$ ( '#add-new-attachment-row' ) . on ( 'click' , function ( e ) {
e . preventDefault ();
addAttachmentRow ();
});
2025-10-13 14:55:46 +07:00
2026-06-01 15:01:03 +07:00
$ ( document ) . on ( 'click' , '.remove-attachment-row' , function () {
removeAttachmentRow ( this );
});
2025-10-13 14:55:46 +07:00
2026-06-01 15:01:03 +07:00
$ ( document ) . on ( 'change' , '.attachment-file' , function () {
previewFile ( this );
});
2025-10-13 14:55:46 +07:00
2026-06-01 15:01:03 +07:00
$ ( document ) . on ( 'click' , '.preview-new-attachment' , function () {
const $row = $ ( this ) . closest ( 'tr' );
const previewType = $row . data ( 'previewType' );
const previewSource = $row . data ( 'previewSource' );
const category = categoryToLabel ( $row . find ( '.attachment-category' ) . val ());
openAttachmentModal ( '#newAttachmentPreviewModal' , category , previewType , previewSource );
2025-10-13 14:55:46 +07:00
});
2026-06-01 15:01:03 +07:00
$ ( document ) . on ( 'click' , '.preview-existing-attachment' , function () {
const button = $ ( this );
const previewType = button . data ( 'preview-type' );
const previewUrl = button . data ( 'preview-url' );
const downloadUrl = button . data ( 'download-url' );
const category = button . data ( 'category' ) || 'Lampiran' ;
2025-10-13 14:55:46 +07:00
2026-06-01 15:01:03 +07:00
if ( ! previewUrl ) {
if ( downloadUrl ) {
window . open ( downloadUrl , '_blank' );
}
2025-10-13 14:55:46 +07:00
return ;
}
2026-06-01 15:01:03 +07:00
openAttachmentModal ( '#existingAttachmentPreviewModal' , category , previewType , previewUrl );
});
2025-10-13 14:55:46 +07:00
2026-06-01 15:01:03 +07:00
$ ( document ) . on ( 'click' , '.delete-attachment' , function () {
const button = $ ( this );
const deleteUrl = button . data ( 'delete-url' );
const $row = button . closest ( 'tr' );
Swal . fire ({
title : 'Hapus lampiran?' ,
text : 'Lampiran yang dihapus tidak dapat dikembalikan.' ,
icon : 'warning' ,
showCancelButton : true ,
confirmButtonText : 'Ya, hapus' ,
cancelButtonText : 'Batal'
}) . then (( result ) => {
if ( ! result . isConfirmed ) return ;
$ . ajax ({
url : deleteUrl ,
type : 'DELETE' ,
success : function ( response ) {
$row . remove ();
if ( ! existingAttachmentsTableBody . find ( 'tr' ) . not ( '.existing-attachments-empty' ) . length ) {
existingAttachmentsTableBody . html ( emptyExistingRowMarkup );
}
Swal . fire ( 'Berhasil' , response ? . message || 'Lampiran berhasil dihapus.' , 'success' );
},
error : function ( xhr ) {
const message = xhr ? . responseJSON ? . message || 'Gagal menghapus lampiran.' ;
Swal . fire ( 'Error' , message , 'error' );
}
});
2025-10-13 14:55:46 +07:00
});
});
2026-06-01 15:01:03 +07:00
} catch ( err ) {
console . error ( " Local Script Error: " , err );
}
2025-01-17 16:39:37 +07:00
});
2025-01-02 13:12:42 +07:00
</ script >
2026-06-01 15:01:03 +07:00
@ endsection