SIPDAM/samooapk/resources/views/Admin/Gaji/Kasbon.blade.php

409 lines
21 KiB
PHP

<x-app-layout>
@push('styles')
<link rel="stylesheet" href="{{ asset('css/tugas.css') }}">
<style>
.pug-stat-kasbon::before { background: linear-gradient(90deg, var(--pug-green), var(--pug-green-m)); }
.pug-stat-lunas::before { background: linear-gradient(90deg, var(--pug-green), var(--pug-green-m)); }
.pug-stat-belum::before { background: linear-gradient(90deg, var(--pug-rose), #f87171); }
.pug-stat-nominal::before { background: linear-gradient(90deg, var(--pug-cyan), #06b6d4); }
</style>
@endpush
<div class="pug-wrap">
<div class="pug-inner">
{{-- ── PAGE HEADER ── --}}
<div style="display:flex; align-items:center; justify-content:space-between; margin-bottom:24px;">
<div style="display:flex; align-items:center; gap:12px;">
<div class="pug-icon-wrap" style="background: linear-gradient(135deg, var(--pug-green), var(--pug-green-m)); box-shadow: 0 4px 14px rgba(26,122,74,0.25);">
<i class="fas fa-hand-holding-usd"></i>
</div>
<div>
<div class="pug-page-title">Data Kasbon</div>
<div class="pug-page-sub">Kelola pinjaman dan kasbon teknisi</div>
</div>
</div>
<button onclick="openAddModal()" class="pug-btn-primary" style="background: linear-gradient(135deg, var(--pug-green), var(--pug-green-m)); box-shadow: 0 4px 14px rgba(26,122,74,0.25);">
<i class="fas fa-plus"></i> Tambah Kasbon
</button>
</div>
@if(session('success'))
<div class="pug-alert pug-alert-ok" role="alert">
<i class="fas fa-check-circle"></i>
<span>{{ session('success') }}</span>
</div>
@endif
{{-- ── DYNAMIC ALERT ── --}}
<div id="dynamicAlert" class="pug-alert" role="alert" style="display: none; margin-bottom: 24px;">
<i id="alertIcon" class="fas"></i>
<span id="alertMessage"></span>
</div>
{{-- ── STATISTICS CARDS ── --}}
<div class="pug-stats" style="grid-template-columns: repeat(5, 1fr);">
<div class="pug-stat pug-stat-kasbon" onclick="setFilter('status', '')" style="cursor: pointer;">
<div class="pug-stat-icon" style="background: var(--pug-cyan-l); color: var(--pug-cyan);"><i class="fas fa-hand-holding-usd"></i></div>
<div class="pug-stat-label">TOTAL KASBON</div>
<div class="pug-stat-val">{{ $totalKasbon ?? 0 }}</div>
<div style="font-size:11px;color:var(--t3);">Semua catatan kasbon</div>
</div>
<div class="pug-stat pug-stat-lunas" onclick="setFilter('status', 'lunas')" style="cursor: pointer;">
<div class="pug-stat-icon" style="background: var(--pug-green-l); color: var(--pug-green);"><i class="fas fa-check-circle"></i></div>
<div class="pug-stat-label">LUNAS</div>
<div class="pug-stat-val">{{ $kasbonLunas ?? 0 }}</div>
<div style="font-size:11px;color:var(--t3);">Kasbon sudah diselesaikan</div>
</div>
<div class="pug-stat pug-stat-belum" onclick="setFilter('status', 'belum_lunas')" style="cursor: pointer;">
<div class="pug-stat-icon" style="background: var(--pug-rose-l); color: var(--pug-rose);"><i class="fas fa-clock"></i></div>
<div class="pug-stat-label">BELUM LUNAS</div>
<div class="pug-stat-val">{{ $kasbonBelumLunas ?? 0 }}</div>
<div style="font-size:11px;color:var(--t3);">Menunggu pelunasan</div>
</div>
<div class="pug-stat pug-stat-nominal" style="background: linear-gradient(135deg, var(--pug-rose), #f43f5e); color: #fff;">
<div class="pug-stat-icon" style="background: rgba(255,255,255,0.2); color: #fff;"><i class="fas fa-exclamation-triangle"></i></div>
<div class="pug-stat-label" style="color: rgba(255,255,255,0.8);">NOMINAL BELUM LUNAS</div>
<div class="pug-stat-val" style="font-size: 24px; margin-top: 10px; color: #fff;">Rp {{ number_format($totalNominalBelumLunas ?? 0, 0, ',', '.') }}</div>
<div style="font-size:11px;color:rgba(255,255,255,0.7);">Total hutang aktif</div>
</div>
<div class="pug-stat pug-stat-nominal">
<div class="pug-stat-icon" style="background: var(--pug-cyan-l); color: var(--pug-cyan);"><i class="fas fa-money-bill-wave"></i></div>
<div class="pug-stat-label">TOTAL NOMINAL</div>
<div class="pug-stat-val" style="font-size: 24px; margin-top: 10px;">Rp {{ number_format($totalNominal ?? 0, 0, ',', '.') }}</div>
<div style="font-size:11px;color:var(--t3);">Akumulasi seluruh kasbon</div>
</div>
</div>
{{-- ── TOOLBAR FILTER ── --}}
<div class="pug-toolbar" style="margin-bottom: 24px;">
<form method="GET" action="{{ route('kasbon.index') }}" id="filterForm" class="pug-toolbar-form">
<div class="pug-toolbar-item" style="flex: 2;">
<label class="pug-field-label">Pilih Teknisi (Cari Langsung)</label>
<select name="id_teknisi" class="pug-input" onchange="this.form.submit()">
<option value="">Semua Teknisi</option>
@foreach($teknisis as $t)
<option value="{{ $t->id_teknisi }}" {{ request('id_teknisi') == $t->id_teknisi ? 'selected' : '' }}>{{ $t->nama }}</option>
@endforeach
</select>
</div>
<div class="pug-toolbar-item" style="flex: 1;">
<label class="pug-field-label">Periode Bulan</label>
<input type="month" name="month" class="pug-input" value="{{ request('month', date('Y-m')) }}" onchange="this.form.submit()">
</div>
<input type="hidden" name="status" value="{{ request('status') }}">
<div class="pug-toolbar-item item-btn">
<button type="button" class="pug-reset-btn" onclick="window.location.href='{{ route('kasbon.index') }}'">
<i class="fas fa-redo"></i> Reset
</button>
</div>
</form>
</div>
{{-- ── DATA TABLE ── --}}
<div class="pug-panel">
<div class="pug-panel-head">
<div class="pug-panel-head-left">
<i class="fas fa-list-ul" style="color:var(--pug-green);margin-right:8px;"></i>
Daftar Kasbon
</div>
<div class="pug-panel-head-right">
Menampilkan {{ $kasbons->total() }} data kasbon
</div>
</div>
<div class="table-responsive">
<table class="pug-table">
<thead>
<tr>
<th width="60">No</th>
<th>Teknisi</th>
<th>Tanggal</th>
<th>Jumlah</th>
<th>Status</th>
<th>Keterangan</th>
<th width="120">Aksi</th>
</tr>
</thead>
<tbody>
@forelse($kasbons as $index => $kasbon)
<tr>
<td>
<span class="pug-rownum">{{ str_pad($kasbons->firstItem() + $index, 2, '0', STR_PAD_LEFT) }}</span>
</td>
<td>
<div style="display:flex; align-items:center; gap:12px;">
<div class="pug-av" style="background: linear-gradient(135deg, var(--pug-green), var(--pug-green-m));">
{{ strtoupper(substr($kasbon->teknisi->nama ?? 'T', 0, 1)) }}
</div>
<div>
<div class="pug-av-name">{{ $kasbon->teknisi->nama ?? 'Unknown' }}</div>
</div>
</div>
</td>
<td>
<div class="pug-date">{{ \Carbon\Carbon::parse($kasbon->tanggal_kasbon)->format('d/m/Y') }}</div>
<div style="font-size: 11px; color: var(--pug-t4);">{{ \Carbon\Carbon::parse($kasbon->tanggal_kasbon)->isoFormat('dddd') }}</div>
</td>
<td>
<div class="pug-money" style="color: var(--pug-rose);">Rp {{ number_format($kasbon->jumlah_kasbon, 0, ',', '.') }}</div>
</td>
<td>
@if($kasbon->status == 'lunas')
<span class="pug-badge pug-badge-green">
<i class="fas fa-check-circle"></i> Lunas
</span>
@else
<span class="pug-badge pug-badge-rose">
<i class="fas fa-clock"></i> Belum Lunas
</span>
@endif
</td>
<td>
<div style="font-size: 13px; color: var(--pug-t2); max-width: 200px;" class="text-truncate" title="{{ $kasbon->keperluan }}">
{{ $kasbon->keperluan ?? '-' }}
</div>
</td>
<td>
<div class="pug-actions">
<button class="pug-action-btn pug-action-edit" onclick="editKasbon({{ $kasbon->id_kasbon }})" title="Edit">
<i class="fas fa-edit"></i>
</button>
@if($kasbon->status == 'belum_lunas')
<button class="pug-action-btn pug-action-view" onclick="lunasKasbon({{ $kasbon->id_kasbon }})" title="Tandai Lunas" style="color: var(--pug-green);">
<i class="fas fa-check-double"></i>
</button>
@endif
<button class="pug-action-btn pug-action-del" onclick="deleteKasbon({{ $kasbon->id_kasbon }})" title="Hapus">
<i class="fas fa-trash"></i>
</button>
</div>
</td>
</tr>
@empty
<tr>
<td colspan="7">
<div class="pug-empty">
<div class="pug-empty-icon" style="background: var(--pug-cyan-l); color: var(--pug-cyan);"><i class="fas fa-hand-holding-usd"></i></div>
<div class="pug-empty-title">Data Kasbon Tidak Ditemukan</div>
<div class="pug-empty-sub">Belum ada catatan kasbon untuk periode ini.</div>
</div>
</td>
</tr>
@endforelse
</tbody>
</table>
</div>
@if($kasbons->hasPages())
<div class="pug-pag">
{{ $kasbons->appends(request()->query())->links() }}
</div>
@endif
</div>
</div>
</div>
{{-- ── MODAL TAMBAH/EDIT ── --}}
<div class="pug-overlay" id="kasbonModal">
<div class="pug-modal pug-modal-sm">
<div class="pug-modal-header">
<div class="pug-modal-title"><i class="fas fa-hand-holding-usd"></i> <span id="modalTitle">Tambah Kasbon Baru</span></div>
<button class="pug-close-btn" onclick="closeModal('kasbonModal')"><i class="fas fa-times"></i></button>
</div>
<form id="kasbonForm" method="POST">
@csrf
<input type="hidden" name="_method" id="formMethod" value="POST">
<input type="hidden" id="kasbonId">
<div class="pug-form-grid">
<div class="pug-form-field pug-form-full">
<label class="pug-form-label"><i class="fas fa-user-tie"></i> Pilih Teknisi <span class="req">*</span></label>
<select name="id_teknisi" id="modal_id_teknisi" class="pug-select" required>
<option value=""> Pilih Teknisi </option>
@foreach($teknisis as $t)
<option value="{{ $t->id_teknisi }}">{{ $t->nama }}</option>
@endforeach
</select>
</div>
<div class="pug-form-field">
<label class="pug-form-label"><i class="fas fa-calendar-alt"></i> Tanggal <span class="req">*</span></label>
<input type="date" name="tanggal_kasbon" id="modal_tanggal_kasbon" class="pug-text-input" value="{{ date('Y-m-d') }}" required>
</div>
<div class="pug-form-field">
<label class="pug-form-label"><i class="fas fa-money-bill-wave"></i> Jumlah Kasbon <span class="req">*</span></label>
<div style="position:relative;">
<span style="position:absolute; left:12px; top:11px; font-size:13px; color:var(--pug-t3); font-weight:700;">Rp</span>
<input type="number" name="jumlah_kasbon" id="modal_jumlah_kasbon" class="pug-text-input" style="padding-left:38px;" placeholder="0" required>
</div>
</div>
<div class="pug-form-field pug-form-full" id="statusField" style="display:none;">
<label class="pug-form-label"><i class="fas fa-info-circle"></i> Status</label>
<select name="status" id="modal_status" class="pug-select">
<option value="belum_lunas">Belum Lunas</option>
<option value="lunas">Lunas</option>
</select>
</div>
<div class="pug-form-field pug-form-full">
<label class="pug-form-label"><i class="fas fa-sticky-note"></i> Keperluan / Keterangan <span class="req">*</span></label>
<textarea name="keterangan" id="modal_keperluan" class="pug-textarea" rows="3" placeholder="Contoh: Keperluan mendesak keluarga, perbaikan motor, dll..." required></textarea>
</div>
</div>
<div class="pug-modal-footer">
<button type="button" class="pug-btn-cancel" onclick="closeModal('kasbonModal')">Batal</button>
<button type="submit" class="pug-btn-submit" style="background: linear-gradient(135deg, var(--pug-green), var(--pug-green-m));">Simpan Data Kasbon</button>
</div>
</form>
</div>
</div>
@push('scripts')
<script>
const appUrl = "{{ url('/') }}";
function openAddModal() {
document.getElementById('modalTitle').textContent = 'Tambah Kasbon Baru';
document.getElementById('kasbonForm').action = "{{ route('kasbon.store') }}";
document.getElementById('formMethod').value = 'POST';
document.getElementById('kasbonId').value = '';
document.getElementById('kasbonForm').reset();
document.getElementById('modal_tanggal_kasbon').value = new Date().toISOString().split('T')[0];
document.getElementById('statusField').style.display = 'none';
document.getElementById('kasbonModal').classList.add('show');
}
function editKasbon(id) {
fetch(`${appUrl}/kasbon/${id}/edit`, { headers: { 'Accept': 'application/json', 'X-Requested-With': 'XMLHttpRequest' } })
.then(r => r.json())
.then(res => {
if(res.success) {
const k = res.kasbon;
document.getElementById('modalTitle').textContent = 'Edit Data Kasbon';
document.getElementById('kasbonForm').action = `${appUrl}/kasbon/${id}`;
document.getElementById('formMethod').value = 'PUT';
document.getElementById('kasbonId').value = k.id_kasbon;
document.getElementById('modal_id_teknisi').value = k.id_teknisi;
document.getElementById('modal_tanggal_kasbon').value = k.tanggal_kasbon.split('T')[0];
document.getElementById('modal_jumlah_kasbon').value = Math.floor(k.jumlah_kasbon);
document.getElementById('modal_status').value = k.status;
document.getElementById('modal_keperluan').value = k.keperluan;
document.getElementById('statusField').style.display = 'block';
document.getElementById('kasbonModal').classList.add('show');
}
});
}
function closeModal(id) { document.getElementById(id).classList.remove('show'); }
function showCustomAlert(message, type = 'success') {
const alertEl = document.getElementById('dynamicAlert');
const iconEl = document.getElementById('alertIcon');
const msgEl = document.getElementById('alertMessage');
if (type === 'success') {
alertEl.className = 'pug-alert pug-alert-ok';
iconEl.className = 'fas fa-check-circle';
} else {
alertEl.className = 'pug-alert pug-alert-err';
iconEl.className = 'fas fa-exclamation-circle';
}
msgEl.textContent = message;
alertEl.style.display = 'flex';
// Scroll to alert smoothly
alertEl.scrollIntoView({ behavior: 'smooth', block: 'center' });
// Auto-hide after 6 seconds
if (window.alertTimeout) clearTimeout(window.alertTimeout);
window.alertTimeout = setTimeout(() => {
alertEl.style.display = 'none';
}, 6000);
}
document.getElementById('kasbonForm').addEventListener('submit', function(e) {
e.preventDefault();
const id = document.getElementById('kasbonId').value;
const method = document.getElementById('formMethod').value;
const formData = new FormData(this);
const url = method === 'POST' ? "{{ route('kasbon.store') }}" : `${appUrl}/kasbon/${id}`;
fetch(url, {
method: 'POST',
body: formData,
headers: {
'X-CSRF-TOKEN': '{{ csrf_token() }}',
'X-Requested-With': 'XMLHttpRequest',
'Accept': 'application/json'
}
})
.then(r => r.json())
.then(res => {
if(res.success) location.reload();
else {
closeModal('kasbonModal');
showCustomAlert(res.message || 'Cek kembali isian Anda.', 'error');
}
})
.catch(err => {
console.error(err);
closeModal('kasbonModal');
showCustomAlert('Terjadi kesalahan koneksi.', 'error');
});
});
function lunasKasbon(id) {
if(!confirm('Tandai kasbon ini sebagai LUNAS?')) return;
fetch(`${appUrl}/kasbon/${id}/lunas`, {
method: 'POST',
headers: {
'X-CSRF-TOKEN': '{{ csrf_token() }}',
'X-Requested-With': 'XMLHttpRequest',
'Accept': 'application/json'
}
})
.then(r => r.json())
.then(res => {
if(res.success) location.reload();
else showCustomAlert('Gagal update status.', 'error');
});
}
function deleteKasbon(id) {
if(!confirm('Hapus data kasbon ini? Aksi ini tidak dapat dibatalkan.')) return;
fetch(`${appUrl}/kasbon/${id}`, {
method: 'DELETE',
headers: {
'X-CSRF-TOKEN': '{{ csrf_token() }}',
'X-Requested-With': 'XMLHttpRequest',
'Accept': 'application/json'
}
})
.then(r => r.json())
.then(res => {
if(res.success) location.reload();
else showCustomAlert('Gagal menghapus data.', 'error');
});
}
function setFilter(key, val) {
const url = new URL(window.location.href);
if(val) url.searchParams.set(key, val);
else url.searchParams.delete(key);
window.location.href = url.toString();
}
</script>
@endpush
</x-app-layout>