{{-- ============================================================================ COMPONENT: Sector NRES — Teras Sektor / Bahagian & Unit Kod : sector_nres · Komponen #baru (type=PHP, category=Section) URL : /nres/sector → hub (4 sektor + 16 bahagian/unit) /nres/sector?unit= → paparan bahagian/unit: 5 seksyen bertindan (tiada tab — gaya scroll halaman MCEE) /nres/sector?sektor= → hub ditapis ikut sektor Page : #42 "Sector" (site 2 · nres) → page_content = {!! $sector_nres !!} Sumber data (modul sedia ada — TIADA jadual baru): · ref (cat = NRES_DEPARTMENT) → 16 bahagian/unit: code, descr (BM), descr_en (EN), sort · content_article (+ _translation) → teks boleh sunting staf (kategori SEKTOR) SATU rekod bagi setiap bahagian/unit: article_category = SEKTOR article_code = (cth BIO_FORESTRY — dari ref NRES_DEPARTMENT) article_subcategory = kosong article_image = gambar banner article_translation_content = SATU dokumen Summernote (BM/EN) mengandungi semua seksyen. Ia dipecah kepada pane halaman oleh tajuk: (sebelum

Program

) → Pengenalan (termasuk

Objektif

&

Fungsi Utama

)

Program

/

Programme

nama

+

huraian

→ Program

Halatuju & Sasaran

/

Direction & Targets

→ Halatuju Setiap bahagian dirender TERUS (gaya dari CSS .sec__rich) — tiada transformasi kad/senarai. Borang menyediakan butang "+ Insert standard structure" untuk menjana struktur ini (lihat partial _sector-editor.blade.php). (Model lama masih dibaca sebagai fallback: article_subcategory = · article_code = - · baris -INTRO dsb.) · content_downloads → dasar & perundangan ikut download_category (BP/TUG/MG/PI/AS/URUS) · content_applications → jabatan & agensi (AGENCY_LINKS) · content_application_translations → nama penuh agensi (ms/en) · ref (cat = NRES_SECTOR) → kumpulan sektor (SSA/SKA/SP/KSU) · ref (cat = NRES_UNIT_PUB) → unit → kategori penerbitan (kat) · ref (cat = NRES_UNIT_AGENCY) → unit → kod agensi (parent = kod unit) · ref (cat = NRES_SECTOR_UI) → teks/label antara muka halaman sektor Corak: sama macam PAGE_CONTENT/nres/publication.blade.php — SEMUA logik, markup dan CSS dalam SATU fail (kelas .sec__*), BM/EN guna array (bukan t()). Nota kandungan: SEMUA teks (Pengenalan / Program / Halatuju) datang dari content_article (kategori SEKTOR) — TIADA array fallback dalam kod. Unit yang belum diisi akan papar nota "sedang dikemaskini". Rekod disimpan ACTIVE tetapi kategori SEKTOR dikecualikan daripada senarai awam. Guna pada page lain: assign komponen ini + letak {!! $sector_nres !!}. ============================================================================ --}} @php $secLang = ($lang ?? session('locale', 'ms')) === 'en' ? 'en' : 'ms'; $secIsEn = $secLang === 'en'; $secSite = trim((string) ($siteSlug ?? ''), '/'); $secBase = url(($secSite !== '' ? $secSite.'/' : '').'sector'); $secHome = url($secSite !== '' ? $secSite.'/home' : '/'); $secPub = url(($secSite !== '' ? $secSite.'/' : '').'publication'); $secEserv = url(($secSite !== '' ? $secSite.'/' : '').'e-services'); $secToday = now()->toDateString(); /* -------------------------------------- teks UI dari ref NRES_SECTOR_UI --- */ // Semua label/teks antara muka boleh diubah dari DB tanpa deploy: // code = kunci · descr = BM · descr_en = EN $secUi = []; foreach (DB::table('ref')->where('cat', 'NRES_SECTOR_UI')->whereNull('deleted_at')->get() as $secUiRow) { $secUiKey = strtoupper(trim((string) $secUiRow->code)); if ($secUiKey === '') { continue; } $secUi[$secUiKey] = [ 'ms' => trim((string) $secUiRow->descr), 'en' => trim((string) ($secUiRow->descr_en ?: $secUiRow->descr)), ]; } // Pulangkan ['ms' => …, 'en' => …] — DB diutamakan; fallback kod = jaring keselamatan. $secUiText = function (string $secUiKey, string $secUiMs, string $secUiEn) use ($secUi) { $secUiRow = $secUi[strtoupper($secUiKey)] ?? null; return [ 'ms' => ($secUiRow['ms'] ?? '') !== '' ? $secUiRow['ms'] : $secUiMs, 'en' => ($secUiRow['en'] ?? '') !== '' ? $secUiRow['en'] : $secUiEn, ]; }; // Teks ikut bahasa semasa. $secTx = fn (string $secUiKey, string $secUiMs, string $secUiEn) => $secUiText($secUiKey, $secUiMs, $secUiEn)[$secLang]; /* --------------------------------------------------------------- sektor --- */ // Kumpulan sektor dari ref NRES_SECTOR (code + nama BM/EN + sort). $secGroups = []; foreach (DB::table('ref')->where('cat', 'NRES_SECTOR')->whereNull('deleted_at') ->orderBy('sort')->orderBy('id')->get() as $secGrpRow) { $secGrpCode = strtoupper(trim((string) $secGrpRow->code)); if ($secGrpCode === '') { continue; } $secGroups[$secGrpCode] = [ 'ms' => trim((string) $secGrpRow->descr), 'en' => trim((string) ($secGrpRow->descr_en ?: $secGrpRow->descr)), ]; } /* ------------------------------------------ peta unit → sektor/kat/agensi --- */ // Semua pemetaan dari DB (TIADA array hardcoded lagi): // sektor → ref NRES_DEPARTMENT.parent (kod NRES_SECTOR, cth SSA) // kategori → ref NRES_UNIT_PUB (code = kod unit → descr = BP/TUG/…) // agensi → ref NRES_UNIT_AGENCY (parent = kod unit → code = kod agensi) $secPubCats = DB::table('ref')->where('cat', 'NRES_UNIT_PUB')->whereNull('deleted_at') ->pluck('descr', 'code') ->mapWithKeys(fn ($secCat, $secUnitK) => [strtoupper(trim((string) $secUnitK)) => strtoupper(trim((string) $secCat))]) ->all(); $secUnitAgns = []; foreach (DB::table('ref')->where('cat', 'NRES_UNIT_AGENCY')->whereNull('deleted_at') ->orderBy('sort')->orderBy('id')->get(['parent', 'code']) as $secAgnMapRow) { $secAgnUnitK = strtoupper(trim((string) $secAgnMapRow->parent)); $secAgnCodeK = strtoupper(trim((string) $secAgnMapRow->code)); if ($secAgnUnitK !== '' && $secAgnCodeK !== '') { $secUnitAgns[$secAgnUnitK][] = $secAgnCodeK; } } /* ----------------------- bersihkan nama: buang sisa "(Agensi: …)" --- */ // ref.descr / descr_en dipakai juga oleh borang lain (ContentFormExport), // jadi di sini kita papar nama bersih SAHAJA. Hanya kurungan yang SEMUA // tokennya kod agensi sah dibuang — cth "(CDO)" dikekalkan. $secAgnCodes = DB::table('content_applications') ->where('application_cat', 'AGENCY_LINKS') ->pluck('application_code') ->map(fn ($c) => strtoupper(trim((string) $c))) ->filter() ->values() ->all(); $secClean = function ($name) use ($secAgnCodes) { $name = trim((string) $name); if (! preg_match('/^(.*?)\s*\(([^()]*)\)\s*$/u', $name, $secMatch)) { return $name; } $secInner = preg_replace('/^\s*(agensi|agency)\s*:\s*/iu', '', $secMatch[2]); $secParts = array_values(array_filter(array_map(fn ($p) => strtoupper(trim($p)), explode(',', (string) $secInner)))); return ($secParts && ! array_diff($secParts, $secAgnCodes)) ? trim($secMatch[1]) : $name; }; /* ------------------------------------------- senarai unit (ref NRES_*) --- */ // Unit = baris ref NRES_DEPARTMENT yang mempunyai `parent` = kod NRES_SECTOR. $secUnits = []; foreach (DB::table('ref')->where('cat', 'NRES_DEPARTMENT')->whereNull('deleted_at') ->orderBy('sort')->orderBy('id')->get() as $secRef) { $secCode = strtoupper(trim((string) $secRef->code)); $secGrpCode = strtoupper(trim((string) $secRef->parent)); // Cth EXHIBITION (parent NULL) dikecualikan — bukan bahagian/unit sektor. if ($secCode === '' || ! isset($secGroups[$secGrpCode])) { continue; } $secUnits[] = [ 'code' => $secCode, 'name' => $secClean($secRef->descr), 'name_en' => $secClean($secRef->descr_en) ?: $secClean($secRef->descr), 'grp' => $secGrpCode, 'kat' => $secPubCats[$secCode] ?? '', 'agn' => $secUnitAgns[$secCode] ?? [], ]; } $secLabel = fn (array $u) => $secIsEn ? $u['name_en'] : $u['name']; $secGroupUnits = []; foreach ($secUnits as $secU) { $secGroupUnits[$secU['grp']][] = $secU; } /* ------------------------------------------------------- unit terpilih --- */ $secUnitCode = strtoupper(trim((string) request()->query('unit', ''))); $secUnit = null; foreach ($secUnits as $secU) { if ($secU['code'] === $secUnitCode) { $secUnit = $secU; break; } } if ($secUnit === null) { $secUnitCode = ''; } $secGroupKey = strtoupper(trim((string) request()->query('sektor', ''))); $secGroupKey = isset($secGroups[$secGroupKey]) ? $secGroupKey : ''; /* ---------------- 5 seksyen bertindan (TIADA tab — gaya halaman MCEE) --- */ // Setiap seksyen dipaparkan berturutan (scroll panjang). id 'sec-pane-' // dan 'sec-tab-' dikekalkan supaya pautan dalam (#sec-pane-program) dan // jangkar tajuk masih berfungsi. // Tajuk seksyen — boleh diubah dari ref NRES_SECTOR_UI (SEC_*). $secSectionTitles = [ 'pengenalan' => $secUiText('SEC_PENGENALAN', 'Pengenalan', 'Introduction'), 'dasar' => $secUiText('SEC_DASAR', 'Dasar & Perundangan', 'Policy & Legislation'), 'program' => $secUiText('SEC_PROGRAM', 'Program', 'Programme'), 'halatuju' => $secUiText('SEC_HALATUJU', 'Halatuju & Sasaran', 'Direction & Targets'), 'agensi' => $secUiText('SEC_AGENSI', 'Jabatan & Agensi', 'Departments & Agencies'), ]; /* -------------------------------- TEKS SEKTOR DARI DB (content_article) --- */ // Teks boleh disunting staf melalui Admin → Artikel (kategori SEKTOR). // // MODEL SEMASA — SATU rekod bagi setiap bahagian/unit: // article_code = (cth BIO_FORESTRY) · article_subcategory = kod // unit · article_image = gambar banner · SELURUH teks dalam SATU dokumen // Summernote (article_translation_content) ikut konvensyen tajuk: // // perenggan sebelum tajuk pertama → Pengenalan (HTML) //

Objektif

+