// SearchView.jsx — محرك البحث القانوني (Frontend-only, ready for backend) /* ========================================================= STATIC CATALOGS ========================================================= */ const SEARCH_TIERS = [ { v: 1, label: 'الأنظمة الأساسية', desc: 'الأقوى قانونياً', color: '#2d7a4f' }, { v: 2, label: 'مراسيم/قرارات وزارية', desc: 'تنفيذية عليا', color: '#a84f32' }, { v: 3, label: 'قرارات هيئات تنظيمية', desc: 'متخصصة', color: '#1e5d9c' }, { v: 4, label: 'وثائق مرجعية', desc: 'إرشادية', color: '#5e5d59' }, { v: 5, label: 'اتفاقيات', desc: 'دولية وثنائية', color: '#87867f' }, ]; const SEARCH_AREAS = [ ['تجاري', 1033], ['عمل', 421], ['مدني', 856], ['جنائي', 234], ['أحوال شخصية', 312], ['عقاري', 567], ['ضرائب', 189], ['بنوك ومالية', 245], ['تأمين', 134], ['ملكية فكرية', 98], ['تحكيم', 76], ['إداري', 412], ['دستوري', 145], ['طبي', 89], ['بيئي', 67], ['طاقة', 123], ['اتصالات', 156], ['نقل', 98], ['زراعة', 76], ['تعليم', 145], ['ثقافي', 67], ['رياضي', 45], ['بلدي', 234], ['تأشيرات', 178], ['حماية مستهلك', 134], ['أمن سيبراني', 89], ['بيانات', 123], ['أوقاف', 67], ['زكاة', 45], ['تخطيط مدن', 78], ['اقتصاد رقمي', 156], ['استثمار', 234], ['شركات', 412], ]; const SEARCH_INSTRUMENTS = [ ['نظام', 1245], ['مرسوم ملكي', 567], ['قرار وزاري', 1834], ['لائحة تنفيذية', 892], ['تعميم', 423], ['أمر سامي', 234], ['اتفاقية', 167], ['وثيقة مرجعية', 312], ]; const SEARCH_ISSUERS = [ 'وزارة العدل', 'وزارة الموارد البشرية', 'هيئة السوق المالية', 'البنك المركزي', 'الهيئة العامة للزكاة والضريبة', 'وزارة التجارة', 'وزارة الصحة', 'وزارة الاستثمار', 'وزارة الداخلية', 'وزارة الخارجية', 'هيئة الاتصالات', 'هيئة المحامين', ]; const SEARCH_SUGGESTIONS = ['نظام العمل', 'الفصل التعسفي', 'الشركات', 'الأحوال الشخصية', 'التنفيذ', 'حماية البيانات', 'العمل المرن', 'التأشيرات']; const SEARCH_TOP = ['نظام العمل 2026', 'الفصل التعسفي', 'مكافأة نهاية الخدمة', 'نقل الكفالة', 'الإيجار التجاري', 'الإفلاس']; const SEARCH_DOCS = [ { doc_id: 'labor-law-1426', title_ar: 'نظام العمل', full_text: `## الباب الأول: التعاريف والأحكام العامة ### الفصل الأول: التعاريف #### المادة الأولى يسمى هذا النظام "نظام العمل". #### المادة الثانية يقصد بالألفاظ والعبارات الآتية - أينما وردت في هذا النظام - المعاني المبينة أمامها. **الوزارة:** وزارة الموارد البشرية والتنمية الاجتماعية. **صاحب العمل:** كل شخص طبيعي أو اعتباري يستخدم عاملاً أو أكثر مقابل أجر. **العامل:** كل شخص طبيعي يعمل لمصلحة صاحب عمل وتحت إدارته أو إشرافه مقابل أجر. ## الباب الثاني: تنظيم عمليات التوظيف #### المادة الرابعة والسبعون ينتهي عقد العمل في الحالات الآتية: إذا اتفق الطرفان على إنهائه على أن تكون موافقة العامل كتابة. إذا انتهت المدة المحددة في العقد ما لم يكن العقد قد جُدِّد صراحة. #### المادة الثمانون لا يستحق العامل مكافأة نهاية الخدمة في الحالات التالية: إذا ترك العمل باختياره قبل إتمام سنتين في خدمة صاحب العمل.`, toc: [ { level: 2, title: 'الباب الأول: التعاريف والأحكام العامة', id: 'bab-1' }, { level: 4, title: 'المادة الأولى', id: 'mada-1' }, { level: 4, title: 'المادة الثانية', id: 'mada-2' }, { level: 2, title: 'الباب الثاني: تنظيم التوظيف', id: 'bab-2' }, { level: 4, title: 'المادة الرابعة والسبعون', id: 'mada-74' }, { level: 4, title: 'المادة الثمانون', id: 'mada-80' }, ], tier: 1, role: 'موضوعي', legal_area: 'عمل', instrument: 'نظام', instrument_number: 'م/51', hijri_year: 1426, issuer_ar: 'وزارة الموارد البشرية', is_repealed: false, text_source: 'full', pdf_original_url: '#', uqn_url: '#', relations: { versions: 3, amends: 0, amended_by: 12, implements: 0, implemented_by: 4, related: 18, cited_by: 247, cites: 6 }, summary: 'ينظم علاقات العمل بين أصحاب العمل والعمال، ويحدد حقوق الطرفين والتزاماتهم، ويغطي شروط العقد والأجور والإجازات وإنهاء الخدمة وحماية العاملين.', }, { doc_id: 'companies-law-1437', title_ar: 'نظام الشركات', full_text: `## الباب الأول: أحكام عامة\n\n#### المادة الأولى\nيسمى هذا النظام "نظام الشركات".\n\n#### المادة الثانية\nالشركة عقد يلتزم بمقتضاه شخصان أو أكثر بأن يساهم كل منهم في مشروع يستهدف الربح.\n\n## الباب الثاني: أنواع الشركات\n\n#### المادة الثالثة\nأنواع الشركات: شركة تضامن، شركة توصية بسيطة، شركة محاصة، شركة مساهمة، شركة توصية بالأسهم، شركة ذات مسؤولية محدودة.`, toc: [ { level: 2, title: 'الباب الأول: أحكام عامة', id: 'bab-1' }, { level: 4, title: 'المادة الأولى', id: 'mada-1' }, { level: 2, title: 'الباب الثاني: أنواع الشركات', id: 'bab-2' }, ], tier: 1, role: 'موضوعي', legal_area: 'تجاري', instrument: 'نظام', instrument_number: 'م/3', hijri_year: 1437, issuer_ar: 'وزارة التجارة', is_repealed: false, text_source: 'full', pdf_original_url: '#', uqn_url: '#', relations: { versions: 2, amends: 0, amended_by: 8, implements: 0, implemented_by: 6, related: 24, cited_by: 412, cites: 4 }, summary: 'يحدد القواعد القانونية لتأسيس وإدارة وتصفية الشركات في المملكة، ويغطي 6 أنواع رئيسية من الشركات بكل خصائصها وأحكامها.', }, { doc_id: 'data-protection-1443', title_ar: 'نظام حماية البيانات الشخصية', full_text: `## الباب الأول: أحكام عامة\n\n#### المادة الأولى\nيهدف هذا النظام إلى حماية البيانات الشخصية وضمان معالجتها بأسلوب آمن ومسؤول.\n\n#### المادة الثانية\nيطبق هذا النظام على كل جهة تعالج بيانات شخصية لأشخاص مقيمين في المملكة العربية السعودية.`, toc: [{ level: 2, title: 'أحكام عامة', id: 'bab-1' }, { level: 4, title: 'المادة الأولى', id: 'mada-1' }], tier: 1, role: 'موضوعي', legal_area: 'بيانات', instrument: 'نظام', instrument_number: 'م/19', hijri_year: 1443, issuer_ar: 'هيئة البيانات والذكاء الاصطناعي', is_repealed: false, text_source: 'full', pdf_original_url: '#', relations: { versions: 1, amends: 0, amended_by: 2, implements: 0, implemented_by: 3, related: 14, cited_by: 89, cites: 8 }, summary: 'ينظم جمع ومعالجة البيانات الشخصية، ويحدد حقوق أصحاب البيانات والتزامات المتحكمين والمعالجين، مع عقوبات للمخالفات.', }, { doc_id: 'arbitration-1433', title_ar: 'نظام التحكيم', full_text: `## الباب الأول: أحكام عامة\n\n#### المادة الأولى\nيطبق هذا النظام على كل تحكيم، أياً كانت طبيعة العلاقة القانونية التي يدور حولها النزاع.`, toc: [{ level: 4, title: 'المادة الأولى', id: 'mada-1' }], tier: 1, role: 'إجرائي', legal_area: 'تحكيم', instrument: 'نظام', instrument_number: 'م/34', hijri_year: 1433, issuer_ar: 'وزارة العدل', is_repealed: false, text_source: 'full', relations: { versions: 1, amends: 0, amended_by: 3, implements: 0, implemented_by: 2, related: 12, cited_by: 156, cites: 4 }, summary: 'ينظم التحكيم التجاري والمدني داخل المملكة، ويحدد إجراءات التحكيم وسلطات المحكمين وتنفيذ أحكام التحكيم.', }, { doc_id: 'rent-decree-1442', title_ar: 'نظام الإيجار التجاري', full_text: `## أحكام عامة\n\n#### المادة الأولى\nينظم هذا النظام العلاقة بين المؤجر والمستأجر للعقارات التجارية في المملكة.`, toc: [{ level: 4, title: 'المادة الأولى', id: 'mada-1' }], tier: 2, role: 'موضوعي', legal_area: 'عقاري', instrument: 'مرسوم ملكي', instrument_number: 'م/76', hijri_year: 1442, issuer_ar: 'مجلس الوزراء', is_repealed: false, text_source: 'full', relations: { versions: 1, amends: 0, amended_by: 1, implements: 0, implemented_by: 1, related: 8, cited_by: 67, cites: 3 }, summary: 'ينظم العلاقة الإيجارية للعقارات التجارية، ويحدد حقوق المؤجر والمستأجر وطرق إنهاء العقد ومعالجة النزاعات.', }, { doc_id: 'consumer-protection-1442', title_ar: 'نظام حماية المستهلك', full_text: `## أحكام عامة\n\n#### المادة الأولى\nيهدف هذا النظام إلى حماية حقوق المستهلك وضمان جودة المنتجات والخدمات.`, toc: [{ level: 4, title: 'المادة الأولى', id: 'mada-1' }], tier: 2, role: 'موضوعي', legal_area: 'حماية مستهلك', instrument: 'مرسوم ملكي', instrument_number: 'م/93', hijri_year: 1442, issuer_ar: 'وزارة التجارة', is_repealed: false, text_source: 'full', relations: { versions: 1, amends: 0, amended_by: 4, implements: 0, implemented_by: 2, related: 10, cited_by: 78, cites: 5 }, summary: 'يحمي حقوق المستهلكين في المعاملات التجارية، ويلزم التجار بمعايير الإفصاح والجودة، ويحدد طرق التعويض عند المخالفة.', }, ]; /* ========================================================= HELPERS ========================================================= */ function searchTierBadgeStyle(tier) { const map = { 1: { bg: 'rgba(45,122,79,0.12)', color: '#2d7a4f' }, 2: { bg: '#f2e5df', color: '#a84f32' }, 3: { bg: 'rgba(30,93,156,0.12)', color: '#1e5d9c' }, 4: { bg: '#e8e6dc', color: '#5e5d59' }, 5: { bg: '#e8e6dc', color: '#87867f' }, }; return map[tier] || map[4]; } function searchStatusInfo(d) { if (d.is_repealed) return { label: 'ملغى', bg: '#f7e5e5', color: '#b53333' }; if ((d.relations?.amended_by || 0) > 0) return { label: 'مُعدَّل', bg: '#fef3e2', color: '#a05e1a' }; return { label: 'ساري', bg: '#e0f2ea', color: '#2d7a4f' }; } function highlightText(text, q) { if (!q || !text) return text; const re = new RegExp(`(${q.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')})`, 'gi'); return text.replace(re, '$1'); } function renderMarkdownToHtml(md) { if (!md) return ''; let html = md; html = html.replace(/^#### (.+)$/gm, '

$1

'); html = html.replace(/^### (.+)$/gm, '

$1

'); html = html.replace(/^## (.+)$/gm, '

$1

'); html = html.replace(/\*\*(.+?)\*\*/g, '$1'); html = html.split('\n\n').map(p => { const t = p.trim(); if (!t) return ''; if (t.startsWith('<')) return t; return `

${t}

`; }).join('\n'); return html; } /* ========================================================= FILTER SIDEBAR ========================================================= */ function SearchFilterSidebar({ filters, onChange, facets }) { const [issuerSearch, setIssuerSearch] = React.useState(''); const [showAllAreas, setShowAllAreas] = React.useState(false); const update = (patch) => onChange({ ...filters, ...patch }); const toggleSet = (key, val) => { const next = new Set(filters[key]); if (next.has(val)) next.delete(val); else next.add(val); update({ [key]: next }); }; const filteredIssuers = SEARCH_ISSUERS.filter(i => i.toLowerCase().includes(issuerSearch.toLowerCase())).slice(0, 8); const areaList = showAllAreas ? SEARCH_AREAS : SEARCH_AREAS.slice(0, 12); const sectionTitle = { fontSize: 11, fontWeight: 700, color: sanadColors.textMuted, letterSpacing: '0.04em', marginBottom: 8, display: 'flex', alignItems: 'center', gap: 5 }; const optionStyle = { display: 'flex', alignItems: 'center', gap: 7, padding: '4px 0', cursor: 'pointer', fontSize: 12.5, color: sanadColors.textSecondary }; const countStyle = { marginRight: 'auto', fontSize: 11, color: sanadColors.textMuted }; return ( ); } /* ========================================================= ACTIVE FILTERS BAR ========================================================= */ function SearchActiveFilters({ filters, onChange }) { const update = (patch) => onChange({ ...filters, ...patch }); const removeSet = (key, val) => { const next = new Set(filters[key]); next.delete(val); update({ [key]: next }); }; const chips = []; if (filters.tier) chips.push({ label: SEARCH_TIERS.find(t=>t.v===filters.tier).label, clear: () => update({ tier: null }) }); filters.areas.forEach(a => chips.push({ label: a, clear: () => removeSet('areas', a) })); filters.instruments.forEach(i => chips.push({ label: i, clear: () => removeSet('instruments', i) })); if (filters.issuer) chips.push({ label: filters.issuer, clear: () => update({ issuer: '' }) }); if (filters.yearFrom || filters.yearTo) chips.push({ label: `${filters.yearFrom || '...'} - ${filters.yearTo || '...'}هـ`, clear: () => update({ yearFrom: null, yearTo: null }) }); if (filters.status !== 'all') chips.push({ label: filters.status === 'active' ? 'ساري' : 'ملغى', clear: () => update({ status: 'all' }) }); if (filters.fullText) chips.push({ label: 'نص كامل', clear: () => update({ fullText: false }) }); filters.relations.forEach(r => { const map = { amendments:'به تعديلات', regulations:'به لوائح', precedents:'به سوابق' }; chips.push({ label: map[r], clear: () => removeSet('relations', r) }); }); if (chips.length === 0) return null; return (
{chips.map((c, i) => ( {c.label} ))}
); } /* ========================================================= RESULT CARD ========================================================= */ function SearchResultCard({ doc, query, onOpen, onSave }) { const tierStyle = searchTierBadgeStyle(doc.tier); const status = searchStatusInfo(doc); const counters = doc.relations || {}; return (
onOpen(doc)} style={{ background: sanadColors.bgElevated, border: `1px solid ${sanadColors.border}`, borderRadius: 12, padding: 16, cursor:'pointer', display:'flex', flexDirection:'column', gap:10, transition:'all 160ms', }} onMouseEnter={e => { e.currentTarget.style.borderColor = sanadColors.brand; e.currentTarget.style.boxShadow = '0 4px 12px rgba(20,20,19,0.06)'; }} onMouseLeave={e => { e.currentTarget.style.borderColor = sanadColors.border; e.currentTarget.style.boxShadow = 'none'; }} > {/* Header */}

📊 {SEARCH_TIERS.find(t=>t.v===doc.tier)?.label} {status.label} {doc.role && {doc.role}}

{/* Meta */}
{doc.instrument || ''}{doc.instrument_number ? ' '+doc.instrument_number : ''} {doc.hijri_year}هـ 🏛️ {doc.issuer_ar}
{/* Summary */} {doc.summary && (

)} {/* Footer */}

{counters.versions ? 📅 {counters.versions} إصدار : null} {counters.amended_by ? ✏️ {counters.amended_by} تعديل : null} {counters.implemented_by ? 📋 {counters.implemented_by} لائحة : null} {counters.related ? 🔗 {counters.related} ذات صلة : null} {counters.cited_by ? 📎 {counters.cited_by} مرجع : null}
{doc.text_source === 'full' ? '📄 نص كامل' : '📑 PDF فقط'}
); } /* ========================================================= DETAIL MODAL (3 cols: side / main / quick) ========================================================= */ function SearchDetailModal({ doc, onClose, onSave, onCrossSection, allDocs }) { const [tab, setTab] = React.useState('text'); if (!doc) return null; const tierStyle = searchTierBadgeStyle(doc.tier); const status = searchStatusInfo(doc); return (
e.stopPropagation()} style={{ background: sanadColors.bgElevated, borderRadius: 16, boxShadow: '0 24px 64px rgba(20,20,19,0.22)', width: '95%', maxWidth: 1280, height: '90vh', display: 'grid', gridTemplateColumns: '260px 1fr 240px', overflow: 'hidden', direction: 'rtl', fontFamily: sanadFonts.arabic, position: 'relative', }}> {/* ─── Side: Timeline / Amendments / Refs / Cross-section ─── */} {/* ─── Main ─── */}
{/* Header */}

{doc.title_ar}

📊 {SEARCH_TIERS.find(t=>t.v===doc.tier)?.label} {status.label} {doc.instrument} {doc.instrument_number||''} · {doc.hijri_year}هـ · 🏛️ {doc.issuer_ar}
{/* Tabs */}
{[ ['text','📜 النص الكامل'], ['timeline','⏱ الجدول الزمني'], ['relations','🔗 الروابط'], ['details','ℹ️ التفاصيل'], ].map(([id, label]) => ( ))}
{/* Content */}
{tab === 'text' && ( <> {doc.toc && doc.toc.length > 0 && (
📑 جدول المحتويات
{doc.toc.map((t, i) => (
{ const el = document.getElementById(`mada-target-${i}`); if (el) el.scrollIntoView({ behavior:'smooth', block:'start' }); }} style={{ padding:'3px 0', paddingRight:`${(t.level-2)*12}px`, fontSize:11.5, color: sanadColors.textSecondary, cursor:'pointer' }} onMouseEnter={e => e.currentTarget.style.color = sanadColors.brand} onMouseLeave={e => e.currentTarget.style.color = sanadColors.textSecondary} >{t.title}
))}
)}
)} {tab === 'timeline' && (

الجدول الزمني

{[ { y: doc.hijri_year, label: 'الإصدار الأصلي' }, ...((doc.relations?.amended_by||0) > 0 ? Array.from({length: Math.min(5, doc.relations.amended_by)}).map((_,i) => ({ y: doc.hijri_year+i+1, label: `تعديل ${i+1}` })) : []), ].map((t, i) => (
{t.y}هـ
{t.label}
))}
)} {tab === 'relations' && (

الروابط والعلاقات

{Object.entries({ cited_by: 'مراجع إليه', cites: 'يستشهد بـ', amended_by: 'تعديلات لاحقة', implemented_by: 'لوائح تنفيذية', related: 'وثائق ذات صلة', versions: 'إصدارات', }).map(([k, label]) => doc.relations?.[k] ? (
{label} ({doc.relations[k]})
{doc.relations[k]} وثيقة مرتبطة
) : null)}
)} {tab === 'details' && (

تفاصيل الوثيقة

{[ ['المعرّف', doc.doc_id], ['نوع الوثيقة', doc.instrument], ['الرقم', doc.instrument_number||'—'], ['السنة', `${doc.hijri_year}هـ`], ['الجهة', doc.issuer_ar], ['المجال', doc.legal_area], ['الدور', doc.role||'—'], ['الحالة', searchStatusInfo(doc).label], ['المستوى', SEARCH_TIERS.find(t=>t.v===doc.tier)?.label], ['مصدر النص', doc.text_source==='full'?'نص كامل':'PDF فقط'], ].map(([k,v]) => (
{k}
{v}
))}
)}
{/* ─── Quick info ─── */}
); } /* ========================================================= MAIN VIEW ========================================================= */ function SearchView() { const [query, setQuery] = React.useState(''); const [section, setSection] = React.useState('laws'); // laws | precedents | articles | books const [searchAll, setSearchAll] = React.useState(false); const [searched, setSearched] = React.useState(false); const [view, setView] = React.useState('list'); // list | grid | grouped const [sort, setSort] = React.useState('relevance'); const [selected, setSelected] = React.useState(null); const [showSaveModal, setShowSaveModal] = React.useState(null); const [filters, setFilters] = React.useState({ tier: null, areas: new Set(), instruments: new Set(), issuer: '', yearFrom: null, yearTo: null, status: 'all', fullText: false, hasUqn: false, hasEn: false, relations: new Set(), source: 'all', }); const debounceRef = React.useRef(null); React.useEffect(() => { clearTimeout(debounceRef.current); debounceRef.current = setTimeout(() => { if (query.trim() || hasActiveFilters()) setSearched(true); }, 250); return () => clearTimeout(debounceRef.current); }, [query]); const hasActiveFilters = () => { const f = filters; return f.tier || f.areas.size || f.instruments.size || f.issuer || f.yearFrom || f.yearTo || f.status !== 'all' || f.fullText || f.hasUqn || f.hasEn || f.relations.size || f.source !== 'all'; }; React.useEffect(() => { if (hasActiveFilters()) setSearched(true); }, [filters]); // Filter + sort const results = React.useMemo(() => { let list = SEARCH_DOCS; const q = query.trim().toLowerCase(); if (q) { list = list.filter(d => d.title_ar.toLowerCase().includes(q) || (d.summary && d.summary.toLowerCase().includes(q)) || (d.full_text && d.full_text.toLowerCase().includes(q)) || (d.legal_area && d.legal_area.includes(q)) ); } if (filters.tier) list = list.filter(d => d.tier === filters.tier); if (filters.areas.size) list = list.filter(d => filters.areas.has(d.legal_area)); if (filters.instruments.size) list = list.filter(d => filters.instruments.has(d.instrument)); if (filters.issuer) list = list.filter(d => d.issuer_ar === filters.issuer); if (filters.yearFrom) list = list.filter(d => d.hijri_year >= filters.yearFrom); if (filters.yearTo) list = list.filter(d => d.hijri_year <= filters.yearTo); if (filters.status === 'active') list = list.filter(d => !d.is_repealed); if (filters.status === 'repealed') list = list.filter(d => d.is_repealed); if (filters.fullText) list = list.filter(d => d.text_source === 'full'); if (sort === 'newest') list = [...list].sort((a,b) => b.hijri_year - a.hijri_year); else if (sort === 'oldest') list = [...list].sort((a,b) => a.hijri_year - b.hijri_year); else if (sort === 'amendments') list = [...list].sort((a,b) => (b.relations?.amended_by||0) - (a.relations?.amended_by||0)); else if (sort === 'relations') list = [...list].sort((a,b) => (b.relations?.cited_by||0) - (a.relations?.cited_by||0)); else if (sort === 'tier') list = [...list].sort((a,b) => a.tier - b.tier); return list; }, [query, filters, sort]); const isLanding = !searched && !query.trim() && !hasActiveFilters(); return (
{/* Section tabs */}
{[ ['laws', '📜 الأنظمة', searchAll ? null : 9654], ['precedents', '⚖️ السوابق', null, 'قريباً'], ['articles', '📝 المقالات', null, 'قريباً'], ['books', '📚 الكتب', null, 'قريباً'], ].map(([id, label, count, chip]) => ( ))}
{/* Hero (landing) */} {isLanding && (

ابحث في القانون السعودي بسرعة

9,654 نظام ولائحة وقرار · مفهرسة بدقة · تبحث وتفهم في ثانية

)} {/* Search bar */}
e.currentTarget.style.borderColor = sanadColors.brand} > setQuery(e.target.value)} onKeyDown={e => { if (e.key === 'Escape') setQuery(''); }} placeholder="ابحث بالكلمة، رقم المادة، اسم النظام…" style={{ flex:1, border:'none', background:'transparent', outline:'none', fontSize:15, color: sanadColors.textPrimary, fontFamily: sanadFonts.arabic, direction:'rtl' }} /> {query && ( )} ⌘K
{/* Landing extras */} {isLanding && (
🔥 اقتراحات شائعة
{SEARCH_SUGGESTIONS.map(s => ( ))}
📂 المجالات القانونية
{SEARCH_AREAS.slice(0, 8).map(([n, c]) => ( ))}
{[ { icon:'📅', title:'أنظمة 1446هـ', meta:'الصادرة هذا العام', filter: { yearFrom: 1446 } }, { icon:'🏛️', title:'الأنظمة الأساسية', meta:'الـ 5 الأقوى قانونياً', filter: { tier: 1 } }, { icon:'✏️', title:'آخر التعديلات', meta:'مرتبة حسب التحديث', sort: 'newest' }, { icon:'🔥', title:'الأكثر بحثاً', meta:'هذا الأسبوع', q: 'نظام العمل' }, ].map((s, i) => ( ))}
)} {/* Search layout */} {!isLanding && section === 'laws' && (
{/* Results column */}
{/* Toolbar */}
{results.length.toLocaleString('ar-SA')} نتيجة{query ? <> لـ "{query}" : ''}
{[ ['list', ], ['grid', ], ['grouped', ], ].map(([id, icon]) => ( ))}
{/* Results */} {results.length === 0 ? (
🔍
لا توجد نتائج
جرّب تغيير كلمات البحث أو تخفيف الفلاتر.
) : view === 'grouped' ? (
{Object.entries(results.reduce((acc, d) => { (acc[d.legal_area] = acc[d.legal_area] || []).push(d); return acc; }, {})).map(([k, items]) => (
{k} {items.length} نتيجة
{items.map(d => (
setShowSaveModal({ item:d })}/>
))}
))}
) : (
{results.map(d => ( setShowSaveModal({ item:d })}/> ))}
)}
{/* Right info col */}
)} {/* Empty section state */} {!isLanding && section !== 'laws' && !searchAll && (
{section==='precedents'?'⚖️':section==='articles'?'📝':'📚'}
قسم {section==='precedents'?'السوابق القضائية':section==='articles'?'المقالات':'الكتب'} قيد البناء
نعمل حالياً على فهرسة هذا القسم. سيكون متاحاً قريباً مع بحث متكامل وروابط بالأنظمة ذات الصلة.
)} {/* Detail modal */} {selected && ( setSelected(null)} onSave={(d) => { setShowSaveModal({ item: d }); }} onCrossSection={(docId) => { const next = SEARCH_DOCS.find(d => d.doc_id === docId); if (next) setSelected(next); }} /> )} {/* Save modal */} {showSaveModal && typeof SaveToFilesModal !== 'undefined' && ( setShowSaveModal(null)} onSave={() => setShowSaveModal(null)}/> )}
); } Object.assign(window, { SearchView });