{{-- ============================================================================ PAGE CONTENT — Direktori Pegawai (Officer Directory) Site : nres · Page slug: officer-directory · Page ID: 28 Sumber: modul content-directory · content_directory_departments → bahagian / unit (hierarki) · content_directory_staff → pegawai Konsep: https://www.nres.gov.my/ms-my/hubungikami/Pages/Direktori-Pegawai.aspx (senarai pegawai mengikut bahagian/unit + carian + nota) Parameter URL: q carian nama / jawatan / e-mel / telefon dept id bahagian — termasuk SEMUA sub-bahagian di bawahnya Nota: · SEMUA logik + markup + CSS ada dalam fail ini — tiada komponen, tiada partial. · Hanya pegawai aktif (directory_staff_status = 1) dipaparkan. · Nama bahagian ikut bahasa semasa ($lang): 'en' guna directory_department_name_en. · Warna guna CSS variable tema (--teal/--green/--fade/--line/--ink) → sokong dark mode. ============================================================================ --}} @php /* -------------------------------------------------------------------- | 1. Parameter & konteks -------------------------------------------------------------------- */ $dirUrl = url()->current(); // URL halaman (tanpa query) $dirQuery = request()->query(); $dirQ = trim((string) ($dirQuery['q'] ?? '')); $dirDept = (int) ($dirQuery['dept'] ?? 0); $dirLang = ($lang ?? session('locale', 'ms')) === 'en' ? 'en' : 'ms'; $dirFiltered = $dirQ !== '' || $dirDept > 0; $dirAduanUrl = url(($siteSlug ?? request()->segment(1)).'/complaints-feedback'); // Nama bahagian ikut bahasa semasa (EN fallback ke BM bila kosong) $dirName = function ($d) use ($dirLang) { $ms = (string) ($d->directory_department_name ?? ''); $en = (string) ($d->directory_department_name_en ?? ''); return ($dirLang === 'en' && $en !== '') ? $en : $ms; }; /* -------------------------------------------------------------------- | 2. Bahagian / unit — hierarki | $dirByParent : parent_id => Collection anak (0 = akar) | $dirOrdered : susunan DFS [ ['dept'=>obj,'level'=>n,'id'=>int] ] | $dirPath : id => [rootName, ..., selfName] (rantai penuh) -------------------------------------------------------------------- */ $dirDepartments = DB::table('content_directory_departments') ->orderBy('directory_department_sort') ->orderBy('directory_department_name') ->get(); $dirByParent = $dirDepartments->groupBy(fn ($d) => (int) ($d->directory_department_parent_id ?? 0)); $dirOrdered = []; $dirPath = []; $dirOrderedId = []; $dirWalk = function (int $parentId, int $level, array $trail) use ( &$dirWalk, &$dirOrdered, &$dirPath, &$dirOrderedId, $dirByParent, $dirName ) { foreach ($dirByParent[$parentId] ?? [] as $d) { $id = (int) $d->directory_department_id; $childTrail = $trail; // salinan — JANGAN kongsi antara adik-beradik $childTrail[$id] = $dirName($d); $dirOrdered[] = ['dept' => $d, 'level' => $level, 'id' => $id]; $dirPath[$id] = $childTrail; $dirOrderedId[] = $id; $dirWalk($id, $level + 1, $childTrail); } }; $dirWalk(0, 0, []); // Kes tepi: bahagian yang parent-nya hilang (data orphan) — tetap dipaparkan foreach ($dirByParent as $dirParentKey => $dirChildren) { if ((int) $dirParentKey !== 0 && ! isset($dirPath[(int) $dirParentKey])) { $dirWalk((int) $dirParentKey, 0, []); } } /* -------------------------------------------------------------------- | 3. Filter bahagian → id terpilih + semua keturunannya -------------------------------------------------------------------- */ $dirDeptIds = []; if ($dirDept > 0) { $dirDeptIds[] = $dirDept; $dirStack = [$dirDept]; while ($dirStack) { $dirCursor = array_pop($dirStack); foreach ($dirByParent[$dirCursor] ?? [] as $dirChild) { $dirChildId = (int) $dirChild->directory_department_id; $dirDeptIds[] = $dirChildId; $dirStack[] = $dirChildId; } } } /* -------------------------------------------------------------------- | 4. Pegawai (aktif sahaja) + kumpulan ikut bahagian -------------------------------------------------------------------- */ $dirStaffQuery = DB::table('content_directory_staff as s') ->where('s.directory_staff_status', 1) ->select('s.*'); if ($dirDeptIds) { $dirStaffQuery->whereIn('s.directory_staff_department_id', $dirDeptIds); } if ($dirQ !== '') { $dirLike = '%'.$dirQ.'%'; $dirStaffQuery->where(function ($w) use ($dirLike) { $w->where('s.directory_staff_name', 'like', $dirLike) ->orWhere('s.directory_staff_position', 'like', $dirLike) ->orWhere('s.directory_staff_email', 'like', $dirLike) ->orWhere('s.directory_staff_phone', 'like', $dirLike); }); } $dirStaff = $dirStaffQuery ->orderBy('s.directory_staff_sort') ->orderBy('s.directory_staff_name') ->get(); $dirByDept = $dirStaff->groupBy(fn ($s) => (int) $s->directory_staff_department_id); // Susun kumpulan ikut hierarki bahagian (bukan ikut abjad) $dirGroups = []; foreach ($dirOrdered as $dirRow) { if (! isset($dirByDept[$dirRow['id']])) { continue; } $dirGroups[] = [ 'name' => $dirName($dirRow['dept']), 'code' => (string) ($dirRow['dept']->directory_department_code ?? ''), 'path' => $dirPath[$dirRow['id']] ?? [], 'staff' => $dirByDept[$dirRow['id']], ]; } // Kes tepi: pegawai yang bahagiannya tidak dikenali foreach ($dirByDept as $dirDeptKey => $dirDeptStaff) { if (! in_array((int) $dirDeptKey, $dirOrderedId, true)) { $dirGroups[] = [ 'name' => 'Bahagian tidak dikenali', 'code' => '', 'path' => [], 'staff' => $dirDeptStaff, ]; } } // Senarai rata untuk jadual (susunan hierarki bahagian) — dipakai oleh tab "Direktori Pegawai" // Nama $dirStaffRows (BUKAN $dirRows) — $dirRows sudah dipakai oleh seksyen gambaran bahagian. $dirStaffRows = []; foreach ($dirGroups as $dirGroup) { foreach ($dirGroup['staff'] as $dirStaffRow) { $dirStaffRows[] = $dirStaffRow; } } $dirTotal = $dirStaff->count(); // sepadan carian $dirTotalAll = DB::table('content_directory_staff')->where('directory_staff_status', 1)->count(); // jumlah keseluruhan /* -------------------------------------------------------------------- | 5. Gambaran bahagian & unit (dikumpul ikut bahagian akar) | + kiraan pegawai aktif (sendiri + keturunan) untuk setiap bahagian -------------------------------------------------------------------- */ $dirDeptDirect = []; foreach (DB::table('content_directory_staff') ->where('directory_staff_status', 1) ->selectRaw('directory_staff_department_id, COUNT(*) as total') ->groupBy('directory_staff_department_id') ->get() as $dirCountRow) { $dirDeptDirect[(int) $dirCountRow->directory_staff_department_id] = (int) $dirCountRow->total; } // Kiraan kumulatif: susunan DFS terbalik → anak diproses sebelum ibu bapa $dirDeptTotal = $dirDeptDirect; foreach (array_reverse($dirOrdered) as $dirCountRow) { $dirCountParent = (int) ($dirCountRow['dept']->directory_department_parent_id ?? 0); if ($dirCountParent) { $dirDeptTotal[$dirCountParent] = ($dirDeptTotal[$dirCountParent] ?? 0) + ($dirDeptTotal[$dirCountRow['id']] ?? 0); } } $dirOrg = []; foreach ($dirByParent[0] ?? [] as $dirRoot) { $dirRootId = (int) $dirRoot->directory_department_id; $dirOrgRows = []; foreach ($dirOrdered as $dirRow) { if ($dirRow['id'] === $dirRootId) { continue; // nama akar sudah jadi tajuk kad } if ((int) array_key_first($dirPath[$dirRow['id']] ?? []) === $dirRootId) { $dirOrgRows[] = [ 'id' => $dirRow['id'], 'name' => $dirName($dirRow['dept']), 'code' => (string) ($dirRow['dept']->directory_department_code ?? ''), 'level' => max(1, (int) $dirRow['level']), 'count' => (int) ($dirDeptTotal[$dirRow['id']] ?? 0), ]; } } $dirOrg[] = [ 'name' => $dirName($dirRoot), 'code' => (string) ($dirRoot->directory_department_code ?? ''), 'count' => (int) ($dirDeptTotal[$dirRootId] ?? 0), 'rows' => $dirOrgRows, ]; } /* -------------------------------------------------------------------- | 6. Helper paparan -------------------------------------------------------------------- */ // Inisial nama → avatar bila tiada foto (cth. "Ahmad Faizal" → "AF") $dirInitials = function ($name) { $name = trim((string) $name); $parts = $name === '' ? [] : preg_split('/\s+/', $name); if (! $parts) { return '?'; } $first = mb_substr($parts[0], 0, 1); $last = count($parts) > 1 ? mb_substr($parts[count($parts) - 1], 0, 1) : ''; return mb_strtoupper($first.$last); }; // Nombor telefon dipaparkan sebagai TEKS BIASA sahaja (tiada pautan tel:) /* -------------------------------------------------------------------- | 7. Peta bahagian (untuk lajur "Bahagian / Unit" dalam jadual) -------------------------------------------------------------------- */ $dirDeptLabel = []; $dirDeptCode = []; foreach ($dirDepartments as $dirDeptRow) { $dirDeptId = (int) $dirDeptRow->directory_department_id; $dirDeptLabel[$dirDeptId] = $dirName($dirDeptRow); $dirDeptCode[$dirDeptId] = (string) ($dirDeptRow->directory_department_code ?? ''); } /* -------------------------------------------------------------------- | 8. E-mel — konsep "Emel [@nres.gov.my]" | Domain dikeluarkan ke TAJUK LAJUR; sel papar nama pengguna sahaja. | Mod: 'local' → nurul.aisyah (lalai — domain pada tajuk lajur) | 'mask' → nur•••@nres.gov.my | 'label' → "E-mel" (pautan sahaja) | 'full' → alamat penuh (tidak disyorkan) -------------------------------------------------------------------- */ $dirEmailMode = 'local'; // Domain paling kerap dalam direktori → dipaparkan pada tajuk lajur $dirDomainCount = []; foreach (DB::table('content_directory_staff')->where('directory_staff_status', 1)->pluck('directory_staff_email') as $dirEmailValue) { $dirEmailValue = trim((string) $dirEmailValue); $dirAtPos = strrpos($dirEmailValue, '@'); if ($dirAtPos === false) { continue; } $dirDomain = strtolower(trim(substr($dirEmailValue, $dirAtPos + 1))); if ($dirDomain !== '') { $dirDomainCount[$dirDomain] = ($dirDomainCount[$dirDomain] ?? 0) + 1; } } $dirEmailDomain = ''; if ($dirDomainCount) { arsort($dirDomainCount); $dirEmailDomain = (string) array_key_first($dirDomainCount); } $dirEmailDomainLabel = $dirEmailDomain !== '' ? '@'.$dirEmailDomain : ''; $dirEmailText = function ($email) use ($dirEmailMode, $dirEmailDomain) { $email = trim((string) $email); if ($email === '') { return ''; } if ($dirEmailMode === 'label') { return 'E-mel'; } if ($dirEmailMode === 'full') { return $email; } $parts = explode('@', $email, 2); if (count($parts) < 2) { return $dirEmailMode === 'mask' ? '•••' : $email; } $local = (string) $parts[0]; $domain = strtolower((string) $parts[1]); if ($dirEmailMode === 'mask') { return mb_substr($local, 0, min(3, mb_strlen($local))).'•••@'.$domain; } // 'local' — papar nama pengguna sahaja; domain berbeza → papar alamat penuh if ($dirEmailDomain !== '' && $domain !== $dirEmailDomain) { return $email; } return $local; }; /* -------------------------------------------------------------------- | 9. Tab: Direktori Pegawai | Pegawai Perhubungan Awam | Bahagian & Unit | (konsep tab seperti laman NRES Direktori Pegawai) -------------------------------------------------------------------- */ $dirTab = (string) ($dirQuery['tab'] ?? 'pegawai'); if (! in_array($dirTab, ['pegawai', 'perhubungan', 'bahagian'], true)) { $dirTab = 'pegawai'; } $dirTabs = [ 'pegawai' => 'Direktori Pegawai', 'perhubungan' => 'Pegawai Perhubungan Awam', 'bahagian' => 'Bahagian & Unit', ]; $dirTabUrl = fn (string $key) => url()->current().'?tab='.$key; $dirDeptUrl = fn (int $deptId) => url()->current().'?tab=pegawai&dept='.$deptId; // Unit "Perhubungan Awam" — padanan kod bahagian atau nama (Unit Komunikasi Korporat) $dirPrCodes = ['UKK']; $dirPrDeptIds = []; foreach ($dirDepartments as $dirDeptRow) { $dirRowCode = strtoupper((string) ($dirDeptRow->directory_department_code ?? '')); $dirRowName = mb_strtolower((string) ($dirDeptRow->directory_department_name ?? '')); if (in_array($dirRowCode, $dirPrCodes, true) || str_contains($dirRowName, 'komunikasi korporat') || str_contains($dirRowName, 'perhubungan awam')) { $dirPrDeptIds[] = (int) $dirDeptRow->directory_department_id; } } $dirPrStaff = DB::table('content_directory_staff') ->where('directory_staff_status', 1) ->whereIn('directory_staff_department_id', $dirPrDeptIds ?: [0]) ->orderBy('directory_staff_sort') ->orderBy('directory_staff_name') ->get(); @endphp
{{-- ---------- BREADCRUMB ---------- --}} {{-- ---------- TAJUK ---------- --}}
Mengenai Kami

Direktori Pegawai

Senarai pegawai Kementerian Sumber Asli dan Kelestarian Alam mengikut bahagian dan unit. Gunakan tab di bawah untuk melihat pegawai perhubungan awam atau senarai bahagian dan unit.

{{-- ---------- TAB ---------- --}} @if ($dirTab === 'pegawai') {{-- ---------- BAR CARIAN ---------- --}} {{-- ---------- RINGKASAN ---------- --}}

@if ($dirFiltered) Menunjukkan {{ $dirTotal }} daripada {{ $dirTotalAll }} pegawai @if ($dirQ !== '') carian: {{ $dirQ }} @endif @if ($dirDept > 0 && isset($dirPath[$dirDept])) {{ implode(' › ', $dirPath[$dirDept]) }} @endif @else {{ $dirTotal }} pegawai aktif dalam {{ count($dirGroups) }} bahagian / unit @endif

@elseif ($dirTab === 'perhubungan') {{-- ---------- TAB: PEGAWAI PERHUBUNGAN AWAM ---------- --}}

{{ $dirPrStaff->count() }} pegawai perhubungan awam @forelse ($dirPrDeptIds as $dirPrDeptId) {{ $dirDeptLabel[$dirPrDeptId] ?? '' }} @empty bahagian perhubungan awam belum didaftarkan @endforelse

@endif @if ($dirTab !== 'bahagian') {{-- ---------- JADUAL PEGAWAI ---------- --}} @php $dirTableRows = $dirTab === 'perhubungan' ? $dirPrStaff : $dirStaffRows; @endphp

Leret jadual ke kiri atau kanan untuk melihat semua lajur.

@forelse ($dirTableRows as $dirRowItem) @php $dirRowDeptId = (int) $dirRowItem->directory_staff_department_id; $dirRowEmail = (string) ($dirRowItem->directory_staff_email ?? ''); $dirRowPhone = (string) ($dirRowItem->directory_staff_phone ?? ''); @endphp @empty @endforelse
# Nama Pegawai Jawatan Bahagian / Unit E-mel @if ($dirEmailMode === 'local' && $dirEmailDomainLabel !== '') [{{ $dirEmailDomainLabel }}] @endif Telefon
{{ $loop->iteration }}
@if (filled($dirRowItem->directory_staff_photo)) Foto {{ $dirRowItem->directory_staff_name }} @else {{ $dirInitials($dirRowItem->directory_staff_name) }} @endif {{ $dirRowItem->directory_staff_name }}
{{ filled($dirRowItem->directory_staff_position) ? $dirRowItem->directory_staff_position : '—' }} {{ $dirDeptLabel[$dirRowDeptId] ?? '—' }} @if (filled($dirDeptCode[$dirRowDeptId] ?? '')) {{ $dirDeptCode[$dirRowDeptId] }} @endif @if (filled($dirRowEmail)) @else — @endif @if (filled($dirRowPhone)) {{ $dirRowPhone }} @else — @endif
@if ($dirTab === 'perhubungan') Tiada pegawai perhubungan awam didaftarkan. @elseif ($dirTotalAll === 0) Direktori pegawai sedang dikemaskini — rekod pegawai belum dimasukkan. Sementara itu, buka tab Bahagian & Unit. @else Tiada pegawai sepadan dengan carian atau bahagian yang dipilih. Set semula tapisan @endif
@else {{-- ---------- TAB: BAHAGIAN & UNIT ---------- --}} @if (count($dirOrg))

{{ count($dirOrdered) }} bahagian dan unit dalam struktur organisasi @if ($dirTotalAll > 0) {{ $dirTotalAll }} pegawai aktif @endif

@foreach ($dirOrg as $dirOrgGroup)

{{ $dirOrgGroup['name'] }} @if ($dirOrgGroup['count'] > 0) {{ $dirOrgGroup['count'] }} @endif

@if (count($dirOrgGroup['rows']))
    @foreach ($dirOrgGroup['rows'] as $dirOrgRow)
  • {{ $dirOrgRow['name'] }} @if ($dirOrgRow['code'] !== '') {{ $dirOrgRow['code'] }} @endif @if ($dirOrgRow['count'] > 0) {{ $dirOrgRow['count'] }} @endif
  • @endforeach
@else

Tiada unit di bawah bahagian ini.

@endif
@endforeach
@endif @endif {{-- ---------- NOTA ---------- --}}