Files
2026-09-16 23:20:08 +07:00

409 lines
27 KiB
PHP

<?php require_once APP_ROOT . '/app/Views/layouts/header.php'; ?>
<?php
$thaiMonths = [
1 => 'มกราคม', 2 => 'กุมภาพันธ์', 3 => 'มีนาคม', 4 => 'เมษายน',
5 => 'พฤษภาคม', 6 => 'มิถุนายน', 7 => 'กรกฎาคม', 8 => 'สิงหาคม',
9 => 'กันยายน', 10 => 'ตุลาคม', 11 => 'พฤศจิกายน', 12 => 'ธันวาคม'
];
$yearBe = $period['year_no'] > 2500 ? $period['year_no'] : $period['year_no'] + 543;
$periodName = $thaiMonths[$period['month_no']] . ' ' . $yearBe;
// Prepare options for javascript
$incomeOptions = '<option value="">-- เลือกรายการรับ --</option>';
foreach ($masterIncomes as $mi) {
$incomeOptions .= '<option value="' . $mi['id'] . '">' . htmlspecialchars($mi['code'] . ' - ' . $mi['name']) . '</option>';
}
$deductionOptions = '<option value="">-- เลือกรายการจ่าย --</option>';
foreach ($masterDeductions as $md) {
$deductionOptions .= '<option value="' . $md['id'] . '">' . htmlspecialchars($md['code'] . ' - ' . $md['name']) . '</option>';
}
?>
<div class="mb-6">
<div class="flex items-center gap-2 text-sm text-slate-500 dark:text-slate-400 mb-2">
<a href="<?= BASE_URL ?>/payroll" class="hover:text-sky-500 transition-colors">จัดการงวดเงินเดือน</a>
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" class="w-3 h-3"><path stroke-linecap="round" stroke-linejoin="round" d="m8.25 4.5 7.5 7.5-7.5 7.5" /></svg>
<a href="<?= BASE_URL ?>/payroll/details/<?= $period['id'] ?>" class="hover:text-sky-500 transition-colors">รายละเอียดงวด</a>
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" class="w-3 h-3"><path stroke-linecap="round" stroke-linejoin="round" d="m8.25 4.5 7.5 7.5-7.5 7.5" /></svg>
<span class="text-slate-800 dark:text-slate-200 font-medium">แก้ไขข้อมูลพนักงาน</span>
</div>
<div class="flex flex-col md:flex-row md:items-center justify-between gap-4">
<div>
<h2 class="text-2xl font-bold text-slate-800 dark:text-white">แก้ไขข้อมูลรายบุคคล</h2>
<p class="text-slate-500 dark:text-slate-400 text-sm mt-1">ประจำเดือน <?= $periodName ?></p>
</div>
<a href="<?= BASE_URL ?>/payroll/details/<?= $period['id'] ?>" class="inline-flex items-center px-4 py-2 bg-white dark:bg-slate-800 border border-slate-200 dark:border-slate-700 rounded-xl text-sm font-medium text-slate-700 dark:text-slate-300 hover:bg-slate-50 dark:hover:bg-slate-700 transition-colors shadow-sm">
ย้อนกลับ
</a>
</div>
</div>
<div class="grid grid-cols-1 lg:grid-cols-4 gap-6 relative">
<!-- Profile Card (Left) -->
<div class="lg:col-span-1 space-y-6">
<div class="bg-white dark:bg-slate-800 rounded-2xl p-6 shadow-sm border border-slate-100 dark:border-slate-700">
<div class="flex flex-col items-center text-center">
<div class="w-24 h-24 mb-4 relative">
<img class="w-24 h-24 rounded-full object-cover bg-sky-50 border-4 border-white dark:border-slate-800 shadow-sm" src="<?= BASE_URL ?>/employee/image/<?= htmlspecialchars($employee['national_id']) ?>" alt="<?= htmlspecialchars($employee['first_name']) ?>" onerror="this.src='data:image/svg+xml;utf8,<svg xmlns=\'http://www.w3.org/2000/svg\' viewBox=\'0 0 24 24\' fill=\'%2394a3b8\'><path fill-rule=\'evenodd\' d=\'M7.5 6a4.5 4.5 0 1 1 9 0 4.5 4.5 0 0 1-9 0ZM3.751 20.105a8.25 8.25 0 0 1 16.498 0 .75.75 0 0 1-.437.695A18.683 18.683 0 0 1 12 22.5c-2.786 0-5.433-.608-7.812-1.7a.75.75 0 0 1-.437-.695Z\' clip-rule=\'evenodd\'/></svg>'">
<div class="absolute inset-0 rounded-full shadow-inner pointer-events-none"></div>
</div>
<h3 class="text-lg font-bold text-slate-800 dark:text-white"><?= htmlspecialchars($employee['first_name'] . ' ' . $employee['last_name']) ?></h3>
<p class="text-sm text-slate-500 dark:text-slate-400 mt-1"><?= htmlspecialchars($employee['position'] ?: 'ไม่ระบุตำแหน่ง') ?></p>
<div class="mt-4 w-full bg-slate-50 dark:bg-slate-700/50 rounded-xl p-3 text-left">
<div class="text-xs text-slate-500 dark:text-slate-400 mb-1">เลขบัตรประชาชน</div>
<div class="text-sm font-medium text-slate-800 dark:text-slate-200 font-mono"><?= htmlspecialchars($employee['national_id']) ?></div>
<div class="text-xs text-slate-500 dark:text-slate-400 mt-3 mb-1">แผนก</div>
<div class="text-sm font-medium text-slate-800 dark:text-slate-200"><?= htmlspecialchars($employee['department'] ?: '-') ?></div>
<div class="text-xs text-slate-500 dark:text-slate-400 mt-3 mb-1">ธนาคาร</div>
<input type="text" name="bank_name" form="editEmployeeForm" value="<?= htmlspecialchars($employee['bank_name'] ?? 'ธนาคารกรุงไทย จำกัด(มหาชน)') ?>" placeholder="ชื่อธนาคาร" class="w-full text-sm rounded-md border-0 py-1.5 px-2 text-slate-900 dark:text-white shadow-sm ring-1 ring-inset ring-slate-300 dark:ring-slate-600 focus:ring-2 focus:ring-inset focus:ring-sky-500 bg-white dark:bg-slate-800 mb-2">
<div class="text-xs text-slate-500 dark:text-slate-400 mb-1">เลขที่บัญชี</div>
<input type="text" name="bank_account" form="editEmployeeForm" value="<?= htmlspecialchars($employee['bank_account'] ?? '') ?>" placeholder="เลขที่บัญชี" class="w-full text-sm rounded-md border-0 py-1.5 px-2 text-slate-900 dark:text-white shadow-sm ring-1 ring-inset ring-slate-300 dark:ring-slate-600 focus:ring-2 focus:ring-inset focus:ring-sky-500 bg-white dark:bg-slate-800 font-mono">
</div>
</div>
</div>
<!-- Summary Card -->
<div class="bg-white dark:bg-slate-800 rounded-2xl p-6 shadow-sm border border-slate-100 dark:border-slate-700 sticky top-4">
<h4 class="text-sm font-semibold text-slate-800 dark:text-white uppercase tracking-wider mb-4">สรุปยอดเงิน</h4>
<div class="space-y-3 text-sm">
<div class="flex justify-between items-center text-emerald-600 dark:text-emerald-400">
<span>รายรับรวม</span>
<span class="font-medium" id="sumTotalIncome">+ 0.00</span>
</div>
<div class="flex justify-between items-center text-red-500 dark:text-red-400">
<span>รายจ่ายรวม</span>
<span class="font-medium" id="sumTotalDeduction">- 0.00</span>
</div>
<div class="pt-3 mt-3 border-t border-slate-100 dark:border-slate-700 flex justify-between items-center">
<span class="font-bold text-slate-800 dark:text-white">ยอดรับสุทธิ</span>
<span class="text-lg font-bold text-sky-600 dark:text-sky-400" id="sumNetSalary">0.00</span>
</div>
</div>
</div>
</div>
<!-- Form Data (Right) -->
<div class="lg:col-span-3">
<form action="<?= BASE_URL ?>/payroll/employee/update" method="POST" id="editEmployeeForm" class="bg-white dark:bg-slate-800 rounded-2xl shadow-sm border border-slate-100 dark:border-slate-700">
<input type="hidden" name="employee_salary_id" value="<?= $employee['id'] ?>">
<input type="hidden" name="salary_month_id" value="<?= $employee['salary_month_id'] ?>">
<div class="p-6 border-b border-slate-100 dark:border-slate-700 bg-slate-50/50 dark:bg-slate-900/20">
<div class="flex items-center justify-between mb-4">
<h3 class="text-lg font-semibold text-emerald-600 flex items-center">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" class="w-5 h-5 mr-2"><path stroke-linecap="round" stroke-linejoin="round" d="M12 4.5v15m7.5-7.5h-15" /></svg>
รายการรับ (Incomes)
</h3>
<button type="button" onclick="addIncomeRow()" class="text-sm text-emerald-600 hover:text-emerald-700 font-medium px-3 py-1.5 rounded-lg hover:bg-emerald-50 dark:hover:bg-emerald-900/30 transition-colors">+ เพิ่มรายการรับ</button>
</div>
<div class="space-y-3" id="incomeContainer">
<?php if (empty($incomes)): ?>
<div class="text-sm text-slate-400 italic text-center py-4 empty-msg">ไม่มีรายการรับ</div>
<?php else: ?>
<?php foreach ($incomes as $inc): ?>
<div class="flex items-center gap-3 bg-white dark:bg-slate-800 p-3 rounded-xl border border-slate-200 dark:border-slate-700 income-row">
<div class="flex-1">
<select name="income_id[]" class="searchable-select w-full" required>
<option value="">-- เลือกรายการรับ --</option>
<?php foreach ($masterIncomes as $mi): ?>
<option value="<?= $mi['id'] ?>" <?= $mi['id'] == $inc['income_master_id'] ? 'selected' : '' ?>><?= htmlspecialchars($mi['code'] . ' - ' . $mi['name']) ?></option>
<?php endforeach; ?>
</select>
</div>
<div class="w-40">
<input type="text" name="income_amount[]" value="<?= number_format($inc['amount'], 2) ?>" oninput="calculateTotal()" class="w-full rounded-lg border-0 py-2 px-3 text-slate-900 dark:text-white shadow-sm ring-1 ring-inset ring-slate-300 dark:ring-slate-600 focus:ring-2 focus:ring-inset focus:ring-sky-500 sm:text-sm bg-slate-50 dark:bg-slate-900 font-mono text-right number-input" required>
</div>
<button type="button" onclick="this.closest('.income-row').remove(); calculateTotal(); checkEmpty('income');" class="p-2 text-slate-400 hover:text-red-500 transition-colors">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-5 h-5"><path stroke-linecap="round" stroke-linejoin="round" d="M14.74 9-.346 9m-4.788 0L9.26 9m9.968-3.21c.342.052.682.107 1.022.166m-1.022-.165L18.16 19.673a2.25 2.25 0 0 1-2.244 2.077H8.084a2.25 2.25 0 0 1-2.244-2.077L4.772 5.79m14.456 0a48.108 48.108 0 0 0-3.478-.397m-12 .562c.34-.059.68-.114 1.022-.165m0 0a48.11 48.11 0 0 1 3.478-.397m7.5 0v-.916c0-1.18-.91-2.164-2.09-2.201a51.964 51.964 0 0 0-3.32 0c-1.18.037-2.09 1.022-2.09 2.201v.916m7.5 0a48.667 48.667 0 0 0-7.5 0" /></svg>
</button>
</div>
<?php endforeach; ?>
<?php endif; ?>
</div>
</div>
<div class="p-6 border-b border-slate-100 dark:border-slate-700 bg-slate-50/50 dark:bg-slate-900/20">
<div class="flex items-center justify-between mb-4">
<h3 class="text-lg font-semibold text-red-500 flex items-center">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" class="w-5 h-5 mr-2"><path stroke-linecap="round" stroke-linejoin="round" d="M5 12h14" /></svg>
รายการจ่าย (Deductions)
</h3>
<button type="button" onclick="addDeductionRow()" class="text-sm text-red-500 hover:text-red-600 font-medium px-3 py-1.5 rounded-lg hover:bg-red-50 dark:hover:bg-red-900/30 transition-colors">+ เพิ่มรายการจ่าย</button>
</div>
<div class="space-y-3" id="deductionContainer">
<?php if (empty($deductions)): ?>
<div class="text-sm text-slate-400 italic text-center py-4 empty-msg">ไม่มีรายการจ่าย</div>
<?php else: ?>
<?php foreach ($deductions as $ded): ?>
<div class="flex items-center gap-3 bg-white dark:bg-slate-800 p-3 rounded-xl border border-slate-200 dark:border-slate-700 deduction-row">
<div class="flex-1">
<select name="deduction_id[]" class="searchable-select w-full" required>
<option value="">-- เลือกรายการจ่าย --</option>
<?php foreach ($masterDeductions as $md): ?>
<option value="<?= $md['id'] ?>" <?= $md['id'] == $ded['deduction_master_id'] ? 'selected' : '' ?>><?= htmlspecialchars($md['code'] . ' - ' . $md['name']) ?></option>
<?php endforeach; ?>
</select>
</div>
<div class="w-40">
<input type="text" name="deduction_amount[]" value="<?= number_format($ded['amount'], 2) ?>" oninput="calculateTotal()" class="w-full rounded-lg border-0 py-2 px-3 text-slate-900 dark:text-white shadow-sm ring-1 ring-inset ring-slate-300 dark:ring-slate-600 focus:ring-2 focus:ring-inset focus:ring-sky-500 sm:text-sm bg-slate-50 dark:bg-slate-900 font-mono text-right number-input" required>
</div>
<button type="button" onclick="this.closest('.deduction-row').remove(); calculateTotal(); checkEmpty('deduction');" class="p-2 text-slate-400 hover:text-red-500 transition-colors">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-5 h-5"><path stroke-linecap="round" stroke-linejoin="round" d="M14.74 9-.346 9m-4.788 0L9.26 9m9.968-3.21c.342.052.682.107 1.022.166m-1.022-.165L18.16 19.673a2.25 2.25 0 0 1-2.244 2.077H8.084a2.25 2.25 0 0 1-2.244-2.077L4.772 5.79m14.456 0a48.108 48.108 0 0 0-3.478-.397m-12 .562c.34-.059.68-.114 1.022-.165m0 0a48.11 48.11 0 0 1 3.478-.397m7.5 0v-.916c0-1.18-.91-2.164-2.09-2.201a51.964 51.964 0 0 0-3.32 0c-1.18.037-2.09 1.022-2.09 2.201v.916m7.5 0a48.667 48.667 0 0 0-7.5 0" /></svg>
</button>
</div>
<?php endforeach; ?>
<?php endif; ?>
</div>
</div>
<div class="p-6 flex items-center justify-end gap-3 bg-slate-50 dark:bg-slate-800 rounded-b-2xl">
<a href="<?= BASE_URL ?>/payroll/details/<?= $period['id'] ?>" class="px-5 py-2.5 bg-white dark:bg-slate-700 border border-slate-300 dark:border-slate-600 rounded-xl text-sm font-medium text-slate-700 dark:text-slate-300 hover:bg-slate-50 dark:hover:bg-slate-600 transition-colors shadow-sm">
ยกเลิก
</a>
<button type="submit" class="px-5 py-2.5 bg-sky-500 hover:bg-sky-600 text-white rounded-xl text-sm font-medium transition-colors shadow-sm flex items-center">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" class="w-4 h-4 mr-2"><path stroke-linecap="round" stroke-linejoin="round" d="M9 12.75 11.25 15 15 9.75M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z" /></svg>
บันทึกข้อมูล
</button>
</div>
</form>
</div>
</div>
<script>
// Master data options for JS
const incomeOptions = `<?= $incomeOptions ?>`;
const deductionOptions = `<?= $deductionOptions ?>`;
function addIncomeRow() {
const container = document.getElementById('incomeContainer');
const emptyMsg = container.querySelector('.empty-msg');
if (emptyMsg) emptyMsg.remove();
const row = document.createElement('div');
row.className = 'flex items-center gap-3 bg-white dark:bg-slate-800 p-3 rounded-xl border border-slate-200 dark:border-slate-700 income-row';
row.innerHTML = `
<div class="flex-1">
<select name="income_id[]" class="searchable-select w-full" required>
${incomeOptions}
</select>
</div>
<div class="w-40">
<input type="text" name="income_amount[]" value="0.00" oninput="calculateTotal()" class="w-full rounded-lg border-0 py-2 px-3 text-slate-900 dark:text-white shadow-sm ring-1 ring-inset ring-slate-300 dark:ring-slate-600 focus:ring-2 focus:ring-inset focus:ring-sky-500 sm:text-sm bg-slate-50 dark:bg-slate-900 font-mono text-right number-input" required>
</div>
<button type="button" onclick="this.closest('.income-row').remove(); calculateTotal(); checkEmpty('income');" class="p-2 text-slate-400 hover:text-red-500 transition-colors">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-5 h-5"><path stroke-linecap="round" stroke-linejoin="round" d="M14.74 9-.346 9m-4.788 0L9.26 9m9.968-3.21c.342.052.682.107 1.022.166m-1.022-.165L18.16 19.673a2.25 2.25 0 0 1-2.244 2.077H8.084a2.25 2.25 0 0 1-2.244-2.077L4.772 5.79m14.456 0a48.108 48.108 0 0 0-3.478-.397m-12 .562c.34-.059.68-.114 1.022-.165m0 0a48.11 48.11 0 0 1 3.478-.397m7.5 0v-.916c0-1.18-.91-2.164-2.09-2.201a51.964 51.964 0 0 0-3.32 0c-1.18.037-2.09 1.022-2.09 2.201v.916m7.5 0a48.667 48.667 0 0 0-7.5 0" /></svg>
</button>
`;
container.appendChild(row);
initNumberFormat(row.querySelector('.number-input'));
// Initialize Select2 on the new row
$(row).find('.searchable-select').select2({
width: '100%',
matcher: function(params, data) {
if ($.trim(params.term) === '') return data;
if (typeof data.text === 'undefined') return null;
var q = params.term.toLowerCase();
if (data.text.toLowerCase().indexOf(q) > -1 || (data.id && data.id.toLowerCase().indexOf(q) > -1)) {
return $.extend({}, data, true);
}
return null;
}
});
}
function addDeductionRow() {
const container = document.getElementById('deductionContainer');
const emptyMsg = container.querySelector('.empty-msg');
if (emptyMsg) emptyMsg.remove();
const row = document.createElement('div');
row.className = 'flex items-center gap-3 bg-white dark:bg-slate-800 p-3 rounded-xl border border-slate-200 dark:border-slate-700 deduction-row';
row.innerHTML = `
<div class="flex-1">
<select name="deduction_id[]" class="searchable-select w-full" required>
${deductionOptions}
</select>
</div>
<div class="w-40">
<input type="text" name="deduction_amount[]" value="0.00" oninput="calculateTotal()" class="w-full rounded-lg border-0 py-2 px-3 text-slate-900 dark:text-white shadow-sm ring-1 ring-inset ring-slate-300 dark:ring-slate-600 focus:ring-2 focus:ring-inset focus:ring-sky-500 sm:text-sm bg-slate-50 dark:bg-slate-900 font-mono text-right number-input" required>
</div>
<button type="button" onclick="this.closest('.deduction-row').remove(); calculateTotal(); checkEmpty('deduction');" class="p-2 text-slate-400 hover:text-red-500 transition-colors">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-5 h-5"><path stroke-linecap="round" stroke-linejoin="round" d="M14.74 9-.346 9m-4.788 0L9.26 9m9.968-3.21c.342.052.682.107 1.022.166m-1.022-.165L18.16 19.673a2.25 2.25 0 0 1-2.244 2.077H8.084a2.25 2.25 0 0 1-2.244-2.077L4.772 5.79m14.456 0a48.108 48.108 0 0 0-3.478-.397m-12 .562c.34-.059.68-.114 1.022-.165m0 0a48.11 48.11 0 0 1 3.478-.397m7.5 0v-.916c0-1.18-.91-2.164-2.09-2.201a51.964 51.964 0 0 0-3.32 0c-1.18.037-2.09 1.022-2.09 2.201v.916m7.5 0a48.667 48.667 0 0 0-7.5 0" /></svg>
</button>
`;
container.appendChild(row);
initNumberFormat(row.querySelector('.number-input'));
// Initialize Select2 on the new row
$(row).find('.searchable-select').select2({
width: '100%',
matcher: function(params, data) {
if ($.trim(params.term) === '') return data;
if (typeof data.text === 'undefined') return null;
var q = params.term.toLowerCase();
if (data.text.toLowerCase().indexOf(q) > -1 || (data.id && data.id.toLowerCase().indexOf(q) > -1)) {
return $.extend({}, data, true);
}
return null;
}
});
}
function checkEmpty(type) {
const container = document.getElementById(type + 'Container');
const rows = container.querySelectorAll('.' + type + '-row');
if (rows.length === 0) {
container.innerHTML = `<div class="text-sm text-slate-400 italic text-center py-4 empty-msg">ไม่มีรายการ${type === 'income' ? 'รับ' : 'จ่าย'}</div>`;
}
}
function parseAmt(val) {
if (!val) return 0;
return parseFloat(val.toString().replace(/,/g, '')) || 0;
}
function formatNumber(num) {
return num.toLocaleString('en-US', {minimumFractionDigits: 2, maximumFractionDigits: 2});
}
function calculateTotal() {
let totalIncome = 0;
document.querySelectorAll('input[name="income_amount[]"]').forEach(input => {
totalIncome += parseAmt(input.value);
});
let totalDeduction = 0;
document.querySelectorAll('input[name="deduction_amount[]"]').forEach(input => {
totalDeduction += parseAmt(input.value);
});
const netSalary = totalIncome - totalDeduction;
document.getElementById('sumTotalIncome').innerText = '+ ' + formatNumber(totalIncome);
document.getElementById('sumTotalDeduction').innerText = '- ' + formatNumber(totalDeduction);
document.getElementById('sumNetSalary').innerText = formatNumber(netSalary);
}
// Auto-format numbers on blur
function initNumberFormat(el) {
el.addEventListener('blur', function() {
const val = parseAmt(this.value);
this.value = formatNumber(val);
calculateTotal();
});
// Allow only numbers and dots
el.addEventListener('input', function() {
let val = this.value;
val = val.replace(/[^0-9.,]/g, '');
this.value = val;
});
}
document.querySelectorAll('.number-input').forEach(initNumberFormat);
// Initial calculation
calculateTotal();
</script>
<!-- Select2 for Searchable Dropdowns -->
<link href="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/css/select2.min.css" rel="stylesheet" />
<style type="text/tailwindcss">
/* Select2 Tailwind Override */
.select2-container--default .select2-selection--single {
@apply w-full rounded-lg py-2 px-3 text-slate-900 shadow-sm ring-1 ring-inset ring-slate-300 focus:ring-2 focus:ring-inset focus:ring-sky-500 sm:text-sm bg-slate-50 outline-none transition-all;
border: none !important;
border-radius: 0.5rem !important;
height: 36px !important;
}
.select2-container--default.select2-container--open .select2-selection--single {
@apply ring-2 ring-inset ring-sky-500;
}
.select2-container--default .select2-selection--single .select2-selection__rendered {
line-height: 20px;
padding-left: 0;
@apply text-slate-900;
}
.select2-container--default .select2-selection--single .select2-selection__arrow {
height: 34px;
right: 8px;
}
.select2-dropdown {
@apply border-0 shadow-lg rounded-lg overflow-hidden ring-1 ring-slate-200 mt-1;
}
.select2-search--dropdown {
@apply p-2 bg-slate-50 border-b border-slate-100;
}
.select2-search--dropdown .select2-search__field {
@apply w-full rounded-md border-0 py-1.5 px-3 text-slate-900 shadow-sm ring-1 ring-inset ring-slate-300 focus:ring-2 focus:ring-inset focus:ring-sky-500 sm:text-sm;
}
.select2-results__option {
@apply px-3 py-2 text-sm text-slate-700 cursor-pointer transition-colors;
}
.select2-container--default .select2-results__option--highlighted[aria-selected] {
@apply bg-sky-50 text-sky-700;
}
.select2-container--default .select2-results__option[aria-selected=true] {
@apply bg-slate-100 text-slate-900 font-medium;
}
/* Dark Mode Support */
.dark .select2-container--default .select2-selection--single {
@apply bg-slate-900 ring-slate-600 text-white;
}
.dark .select2-container--default .select2-selection--single .select2-selection__rendered {
@apply text-white;
}
.dark .select2-dropdown {
@apply bg-slate-800 ring-slate-700;
}
.dark .select2-search--dropdown {
@apply bg-slate-800 border-slate-700;
}
.dark .select2-search--dropdown .select2-search__field {
@apply bg-slate-900 ring-slate-700 text-white focus:ring-sky-500;
}
.dark .select2-results__option {
@apply text-slate-300;
}
.dark .select2-container--default .select2-results__option--highlighted[aria-selected] {
@apply bg-slate-700 text-white;
}
.dark .select2-container--default .select2-results__option[aria-selected=true] {
@apply bg-slate-900 text-white;
}
</style>
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/js/select2.min.js"></script>
<script>
$(document).ready(function() {
// Initialize existing selects
$('.searchable-select').select2({
width: '100%',
matcher: function(params, data) {
// Custom matcher for better search (ignores spaces etc if needed)
if ($.trim(params.term) === '') {
return data;
}
if (typeof data.text === 'undefined') {
return null;
}
var q = params.term.toLowerCase();
if (data.text.toLowerCase().indexOf(q) > -1 || (data.id && data.id.toLowerCase().indexOf(q) > -1)) {
return $.extend({}, data, true);
}
return null;
}
});
});
</script>
<?php require_once APP_ROOT . '/app/Views/layouts/footer.php'; ?>