| const input = document.getElementById("searchInput"); |
| const clearBtn = document.getElementById("clearBtn"); |
| const results = document.getElementById("results"); |
| const counter = document.getElementById("counter"); |
| const resultsHeader = document.querySelector(".resultsHeader"); |
|
|
| const COLUMNS = [ |
| { key: "إسم المنشأة", label: "إسم المنشأة" }, |
| { key: "السجل التجاري", label: "السجل التجاري" }, |
| { key: "حالة العينة", label: "حالة العينة" }, |
| { key: "اسم المسح", label: "اسم المسح" }, |
| ]; |
|
|
| function normalize(value){ |
| return String(value ?? "") |
| .toLowerCase() |
| .trim() |
| .replace(/[إأآا]/g,"ا") |
| .replace(/ى/g,"ي") |
| .replace(/ة/g,"ه") |
| .replace(/[^\u0600-\u06FFa-zA-Z0-9 ]/g,"") |
| .replace(/\s+/g," "); |
| } |
|
|
| function esc(value){ |
| return String(value ?? "") |
| .replace(/&/g,"&") |
| .replace(/</g,"<") |
| .replace(/>/g,">") |
| .replace(/"/g,""") |
| .replace(/'/g,"'"); |
| } |
|
|
| function getStatusClass(status){ |
| const s = normalize(status); |
|
|
| if(s.includes("اعطت كامل البيانات")){ |
| return "status success"; |
| } |
|
|
| if(s.includes("اعطت بعض البيانات") || s.includes("استيفاء ذاتي")){ |
| return "status warning"; |
| } |
|
|
| if( |
| s.includes("رفض") || |
| s.includes("مغلق") || |
| s.includes("لم يعثر") || |
| s.includes("انتقلت") || |
| s.includes("تحولت") || |
| s.includes("خارج نطاق") || |
| s.includes("لم تمارس") || |
| s.includes("غير متاح") || |
| s.includes("يطالب") || |
| s.includes("اخري") |
| ){ |
| return "status danger"; |
| } |
|
|
| return "status"; |
| } |
|
|
| function getScore(row, q){ |
| const name = normalize(row["إسم المنشأة"]); |
| const cr = normalize(row["السجل التجاري"]); |
|
|
| if(name === q || cr === q) return 1; |
| if(name.startsWith(q) || cr.startsWith(q)) return 2; |
| if(name.includes(q) || cr.includes(q)) return 3; |
|
|
| return 99; |
| } |
|
|
| function showResultsArea(){ |
| results.classList.add("active"); |
| if(resultsHeader) resultsHeader.classList.add("active"); |
| } |
|
|
| function hideResultsArea(){ |
| results.classList.remove("active"); |
| if(resultsHeader) resultsHeader.classList.remove("active"); |
| } |
|
|
| function render(rows){ |
| showResultsArea(); |
|
|
| counter.textContent = rows.length ? `عدد النتائج: ${rows.length}` : ""; |
|
|
| if(!rows.length){ |
| results.innerHTML = ` |
| <div class="empty"> |
| لم يتم العثور على نتيجة مطابقة. |
| </div> |
| `; |
| return; |
| } |
|
|
| const head = ` |
| <thead> |
| <tr> |
| ${COLUMNS.map(col => `<th>${col.label}</th>`).join("")} |
| </tr> |
| </thead> |
| `; |
|
|
| const body = ` |
| <tbody> |
| ${rows.map(row => ` |
| <tr> |
| <td>${esc(row["إسم المنشأة"] || "—")}</td> |
| <td>${esc(row["السجل التجاري"] || "—")}</td> |
| <td> |
| <span class="${getStatusClass(row["حالة العينة"])}"> |
| ${esc(row["حالة العينة"] || "—")} |
| </span> |
| </td> |
| <td>${esc(row["اسم المسح"] || "—")}</td> |
| </tr> |
| `).join("")} |
| </tbody> |
| `; |
|
|
| const cards = ` |
| <div class="cards"> |
| ${rows.map(row => ` |
| <article class="resultCard"> |
| <div class="cardTop"> |
| <h3>${esc(row["إسم المنشأة"] || "—")}</h3> |
| <span class="${getStatusClass(row["حالة العينة"])}"> |
| ${esc(row["حالة العينة"] || "—")} |
| </span> |
| </div> |
| |
| <div class="cardInfo"> |
| <div> |
| <span>السجل التجاري</span> |
| <strong>${esc(row["السجل التجاري"] || "—")}</strong> |
| </div> |
| <div> |
| <span>اسم المسح</span> |
| <strong>${esc(row["اسم المسح"] || "—")}</strong> |
| </div> |
| </div> |
| </article> |
| `).join("")} |
| </div> |
| `; |
|
|
| results.innerHTML = ` |
| <div class="tableWrap"> |
| <table>${head}${body}</table> |
| </div> |
| ${cards} |
| `; |
| } |
|
|
| function search(){ |
| const q = normalize(input.value); |
|
|
| if(!q){ |
| counter.textContent = ""; |
| hideResultsArea(); |
| return; |
| } |
|
|
| if(q.length < 2){ |
| counter.textContent = ""; |
| showResultsArea(); |
| results.innerHTML = `<div class="empty">اكتب حرفين على الأقل.</div>`; |
| return; |
| } |
|
|
| const filtered = DATA |
| .filter(row => { |
| const name = normalize(row["إسم المنشأة"]); |
| const cr = normalize(row["السجل التجاري"]); |
| const status = normalize(row["حالة العينة"]); |
|
|
| if(status.includes("جديد")) return false; |
|
|
| return name.includes(q) || cr.includes(q); |
| }) |
| .sort((a,b) => getScore(a,q) - getScore(b,q)); |
|
|
| render(filtered); |
| } |
|
|
| function clearSearch(){ |
| input.value = ""; |
| counter.textContent = ""; |
| results.innerHTML = ""; |
| hideResultsArea(); |
| input.focus(); |
| } |
|
|
| let debounceTimer; |
|
|
| input.addEventListener("input", () => { |
| clearTimeout(debounceTimer); |
| debounceTimer = setTimeout(search, 250); |
| }); |
|
|
| clearBtn.addEventListener("click", clearSearch); |
|
|
| if(!Array.isArray(DATA)){ |
| showResultsArea(); |
| counter.textContent = ""; |
| results.innerHTML = `<div class="empty">ملف البيانات غير صحيح.</div>`; |
| } |