198 lines
10 KiB
PHP
198 lines
10 KiB
PHP
{{--
|
|
Ringkasan isian WAJIB (skor) dan PERLU (dashboard) yang belum terisi di tab petani yang sedang dibuka.
|
|
Daftar isiannya ada di App\Services\Produktivitas\KelengkapanPetani.
|
|
Klik isian → halaman menggulir ke kolomnya (dicari lewat atribut name).
|
|
--}}
|
|
@props(['petani', 'lahan' => null])
|
|
|
|
@use('App\Services\Produktivitas\KelengkapanPetani')
|
|
|
|
@php
|
|
$tab = match (true) {
|
|
request()->routeIs('petani.edit') => 'profil',
|
|
request()->routeIs('petani.lahan-tanaman.*') => 'lahan',
|
|
request()->routeIs('petani.praktik-budidaya.*') => 'praktik-budidaya',
|
|
request()->routeIs('petani.sosial-ekonomi.*') => 'sosial-ekonomi',
|
|
request()->routeIs('petani.akses-pasar.*') => 'akses-pasar',
|
|
request()->routeIs('petani.skor.*') => 'semua',
|
|
default => null,
|
|
};
|
|
|
|
$urlTab = fn (string $t) => $t === 'profil'
|
|
? route('petani.edit', $petani->id)
|
|
: route('petani.' . ($t === 'lahan' ? 'lahan-tanaman' : $t) . '.index', $petani->id);
|
|
|
|
$kelengkapan = $tab ? KelengkapanPetani::untuk($petani) : null;
|
|
|
|
if ($tab === 'semua') {
|
|
// Tab Kesiapan Adopsi: rangkuman semua tab, klik → pindah ke tab terkait.
|
|
$kelompok = $kelengkapan->semuaKosong()
|
|
->map(fn ($items, $t) => $items->map(fn ($item) => [
|
|
...$item,
|
|
'url' => ($item['url'] ?? $urlTab($t)) . ($item['input'] ? '#isian=' . $item['input'] : ''),
|
|
]))
|
|
->filter(fn ($items) => $items->isNotEmpty())
|
|
->mapWithKeys(fn ($items, $t) => [KelengkapanPetani::TAB_LABEL[$t] => $items]);
|
|
} elseif ($tab) {
|
|
// Di halaman edit lahan, isian lahan yang sedang dibuka langsung digulir (tanpa pindah halaman).
|
|
$lahanDibukaId = $tab === 'lahan' && request()->routeIs('petani.lahan-tanaman.edit') ? $lahan?->id : null;
|
|
|
|
$kelompok = $kelengkapan->kosong($tab)
|
|
->map(function ($item) use ($lahanDibukaId) {
|
|
$dibuka = $lahanDibukaId && $item['lahan_id'] === $lahanDibukaId;
|
|
|
|
return [
|
|
...$item,
|
|
'grup' => $dibuka ? $item['grup'] . ' (sedang dibuka)' : $item['grup'],
|
|
'url' => ($dibuka || ! $item['url']) ? null : $item['url'] . ($item['input'] ? '#isian=' . $item['input'] : ''),
|
|
];
|
|
})
|
|
->groupBy(fn ($item) => $item['grup'] ?? '');
|
|
}
|
|
|
|
$semuaItem = $tab ? $kelompok->flatten(1) : collect();
|
|
$jumlahWajib = $semuaItem->where('prioritas', KelengkapanPetani::WAJIB)->count();
|
|
$jumlahPerlu = $semuaItem->where('prioritas', KelengkapanPetani::PERLU)->count();
|
|
@endphp
|
|
|
|
@if ($tab)
|
|
@if ($semuaItem->isEmpty())
|
|
<div class="alert alert-success d-flex align-items-center py-2 mb-6" role="alert">
|
|
<i class="icon-base ti tabler-circle-check me-2"></i>
|
|
{{ $tab === 'semua' ? 'Semua isian wajib dan perlu sudah terisi.' : 'Semua isian wajib dan perlu di tab ini sudah terisi.' }}
|
|
</div>
|
|
@else
|
|
{{-- Klik di mana saja pada kartu untuk membuka/menutup detail (kecuali tombol isian). --}}
|
|
<div class="card mb-6 border border-warning kartu-kelengkapan" id="kelengkapan-petani"
|
|
role="button" aria-expanded="false" aria-controls="kelengkapan-petani-detail" title="Klik untuk menampilkan/menyembunyikan detail">
|
|
<div class="card-body py-3">
|
|
<div class="d-flex justify-content-between align-items-center flex-wrap gap-2">
|
|
<div class="d-flex align-items-center">
|
|
<i class="icon-base ti tabler-alert-triangle text-warning me-2"></i>
|
|
<span class="fw-medium">
|
|
Belum terisi{{ $tab === 'semua' ? '' : ' di tab ini' }}:
|
|
@if ($jumlahWajib)
|
|
<span class="badge bg-label-danger ms-1">{{ $jumlahWajib }} wajib</span>
|
|
@endif
|
|
@if ($jumlahPerlu)
|
|
<span class="badge bg-label-warning ms-1">{{ $jumlahPerlu }} perlu</span>
|
|
@endif
|
|
</span>
|
|
</div>
|
|
<span class="btn btn-sm btn-icon btn-text-secondary rounded-pill ikon-toggle-kelengkapan" aria-hidden="true">
|
|
<i class="icon-base ti tabler-chevron-down"></i>
|
|
</span>
|
|
</div>
|
|
|
|
<div class="collapse" id="kelengkapan-petani-detail">
|
|
<small class="text-muted d-block mt-2">
|
|
<span class="badge badge-dot bg-danger me-1"></span>Wajib: dipakai skor Kesiapan Adopsi
|
|
<span class="badge badge-dot bg-warning ms-3 me-1"></span>Perlu: dipakai dashboard.
|
|
Klik isian untuk menuju kolomnya.
|
|
</small>
|
|
|
|
@foreach ($kelompok as $judul => $items)
|
|
<div class="mt-3">
|
|
@if ($judul !== '')
|
|
<div class="small fw-medium mb-1">{{ $judul }}</div>
|
|
@endif
|
|
<div class="d-flex flex-wrap gap-2">
|
|
@foreach ($items->sortBy(fn ($i) => $i['prioritas'] === KelengkapanPetani::WAJIB ? 0 : 1) as $item)
|
|
<button type="button"
|
|
class="btn btn-xs btn-isian-kosong {{ $item['prioritas'] === KelengkapanPetani::WAJIB ? 'btn-label-danger' : 'btn-label-warning' }}"
|
|
data-input="{{ $item['input'] }}"
|
|
data-url="{{ $item['url'] }}">
|
|
{{ $item['label'] }}
|
|
</button>
|
|
@endforeach
|
|
</div>
|
|
</div>
|
|
@endforeach
|
|
</div>
|
|
</div>
|
|
</div>
|
|
@endif
|
|
|
|
@once
|
|
@push('style')
|
|
<style>
|
|
.kartu-kelengkapan { cursor: pointer; }
|
|
.kartu-kelengkapan .btn-isian-kosong { cursor: pointer; }
|
|
.ikon-toggle-kelengkapan i { transition: transform .2s; }
|
|
.kartu-kelengkapan.terbuka .ikon-toggle-kelengkapan i { transform: rotate(180deg); }
|
|
.isian-disorot {
|
|
outline: 2px solid var(--bs-warning);
|
|
outline-offset: 4px;
|
|
border-radius: .375rem;
|
|
}
|
|
</style>
|
|
@endpush
|
|
|
|
@push('scripts')
|
|
<script>
|
|
(function () {
|
|
function cariKolom(name) {
|
|
if (!name) return null;
|
|
const el = document.querySelector(`[name="${name}"], [name="${name}[]"], [name^="${name}["]`);
|
|
if (!el) return null;
|
|
|
|
// Kolom tersembunyi (mis. radio custom/select2): sorot pembungkus terdekat yang terlihat.
|
|
let target = el.closest('.col-md-12, .col-md-6, .col-md-4, .col-12, .col, .mb-4, .mb-6') || el;
|
|
while (target && target.offsetParent === null && target.parentElement) {
|
|
target = target.parentElement;
|
|
}
|
|
return { el, target };
|
|
}
|
|
|
|
function sorot(name) {
|
|
const hasil = cariKolom(name);
|
|
if (!hasil) return false;
|
|
|
|
hasil.target.scrollIntoView({ behavior: 'smooth', block: 'center' });
|
|
hasil.target.classList.add('isian-disorot');
|
|
setTimeout(() => hasil.target.classList.remove('isian-disorot'), 2500);
|
|
if (hasil.el.offsetParent !== null && typeof hasil.el.focus === 'function') {
|
|
hasil.el.focus({ preventScroll: true });
|
|
}
|
|
return true;
|
|
}
|
|
|
|
// Buka/tutup detail dengan klik di mana saja pada kartu.
|
|
const kartu = document.getElementById('kelengkapan-petani');
|
|
const detail = document.getElementById('kelengkapan-petani-detail');
|
|
if (kartu && detail) {
|
|
kartu.addEventListener('click', function (e) {
|
|
if (e.target.closest('.btn-isian-kosong')) return;
|
|
if (window.getSelection().toString()) return; // sedang menyeleksi teks
|
|
bootstrap.Collapse.getOrCreateInstance(detail, { toggle: false }).toggle();
|
|
});
|
|
detail.addEventListener('show.bs.collapse', () => { kartu.classList.add('terbuka'); kartu.setAttribute('aria-expanded', 'true'); });
|
|
detail.addEventListener('hide.bs.collapse', () => { kartu.classList.remove('terbuka'); kartu.setAttribute('aria-expanded', 'false'); });
|
|
}
|
|
|
|
document.addEventListener('click', function (e) {
|
|
const btn = e.target.closest('.btn-isian-kosong');
|
|
if (!btn) return;
|
|
|
|
if (btn.dataset.url) {
|
|
window.location.href = btn.dataset.url;
|
|
return;
|
|
}
|
|
|
|
if (!sorot(btn.dataset.input)) {
|
|
const pesan = 'Kolom ini belum tampil di halaman ini. Simpan bagian yang sudah ada terlebih dahulu, atau periksa jawaban pertanyaan sebelumnya.';
|
|
window.Swal ? Swal.fire({ icon: 'info', text: pesan, buttonsStyling: false, customClass: { confirmButton: 'btn btn-primary' } }) : alert(pesan);
|
|
}
|
|
});
|
|
|
|
// Datang dari tab lain dengan #isian=nama_kolom
|
|
window.addEventListener('load', function () {
|
|
const cocok = window.location.hash.match(/^#isian=(.+)$/);
|
|
if (cocok) setTimeout(() => sorot(decodeURIComponent(cocok[1])), 300);
|
|
});
|
|
})();
|
|
</script>
|
|
@endpush
|
|
@endonce
|
|
@endif
|