let COLS = [];
const qEl = document.getElementById("q");
const btnSearch = document.getElementById("btnSearch");
const btnClear = document.getElementById("btnClear");
const resultsEl = document.getElementById("results");
const totalChip = document.getElementById("totalChip");
const countPill = document.getElementById("countPill");
const summaryPill = document.getElementById("summaryPill");
const FIELD_MAP = {
researcher: ["اسم الباحث", "اسم الباحث/ة", "الباحث", "الاسم", "K"],
facility: ["اسم المنشأة", "إسم المنشأة", "المنشأة", "اسم المنشاه", "C"],
description: ["الوصف", "الوصف.1", "S"],
completion: ["حالة اكتمال البيانات", "حالة الاكتمال", "U"],
collection: ["حالة الاستيفاء", "T"],
approval: ["الوصف.1", "حالة الاعتماد", "اعتماد", "الوصف"],
};
const DISPLAY_COLUMNS = [
{ key: "researcher", label: "اسم الباحث" },
{ key: "facility", label: "اسم المنشأة" },
{ key: "collection", label: "حالة الاستيفاء" },
{ key: "completion", label: "حالة اكتمال البيانات" },
{ key: "description", label: "الوصف" },
];
const RESOLVED = {
researcher: null,
facility: null,
description: null,
completion: null,
collection: null,
approval: null,
};
function escHtml(value) {
return String(value ?? "")
.replace(/&/g, "&")
.replace(//g, ">")
.replace(/"/g, """)
.replace(/'/g, "'");
}
function cleanHeader(value) {
return String(value ?? "")
.replace(/[\u200E\u200F\u202A-\u202E]/g, "")
.replace(/\u00A0/g, " ")
.replace(/\s+/g, " ")
.trim();
}
function normalizeArabic(value) {
if (value == null) return "";
return String(value)
.toLowerCase()
.trim()
.replace(/[إأآا]/g, "ا")
.replace(/ى/g, "ي")
.replace(/ة/g, "ه")
.replace(/[\u064B-\u065F\u0670]/g, "")
.replace(/\s+/g, " ");
}
function safeGet(obj, key) {
if (!obj || !key) return "";
return Object.prototype.hasOwnProperty.call(obj, key) ? obj[key] : "";
}
function findColumn(cols, wantedList) {
const wanted = Array.isArray(wantedList) ? wantedList : [wantedList];
const cleanedCols = cols.map((col) => ({
original: col,
clean: cleanHeader(col),
norm: normalizeArabic(cleanHeader(col)),
}));
for (const candidate of wanted) {
const cleanCandidate = cleanHeader(candidate);
const normCandidate = normalizeArabic(cleanCandidate);
let hit = cleanedCols.find((c) => c.clean === cleanCandidate);
if (hit) return hit.original;
hit = cleanedCols.find((c) => c.norm === normCandidate);
if (hit) return hit.original;
hit = cleanedCols.find((c) => c.clean.includes(cleanCandidate) || c.norm.includes(normCandidate));
if (hit) return hit.original;
}
return null;
}
function tagClass(value) {
const v = normalizeArabic(value);
if (
v.includes("تم") ||
(v.includes("مكتمل") && !v.includes("غير")) ||
(v.includes("مكتمله") && !v.includes("غير")) ||
(v.includes("مستوفي") && !v.includes("غير"))
) {
return "ok";
}
if (
v.includes("غير") ||
v.includes("ناقص") ||
v.includes("مرفوض") ||
v.includes("تعذر") ||
v.includes("لم يتم")
) {
return "warn";
}
return "info";
}
function renderEmpty(message) {
resultsEl.innerHTML = `
${escHtml(message)}
`;
}
function resolveColumns() {
RESOLVED.researcher = findColumn(COLS, FIELD_MAP.researcher);
RESOLVED.facility = findColumn(COLS, FIELD_MAP.facility);
RESOLVED.description = findColumn(COLS, FIELD_MAP.description);
RESOLVED.completion = findColumn(COLS, FIELD_MAP.completion);
RESOLVED.collection = findColumn(COLS, FIELD_MAP.collection);
RESOLVED.approval = findColumn(COLS, FIELD_MAP.approval);
}
function resolveApprovalStatus(row) {
const direct = normalizeArabic(getDisplayValue(row, "approval"));
if (direct.includes("غير معتمد") || (direct.includes("معتمد") && direct.includes("غير"))) return "غير معتمد";
if (direct === "معتمد" || (direct.includes("معتمد") && !direct.includes("غير"))) return "معتمد";
const description = normalizeArabic(getDisplayValue(row, "description"));
if (description.includes("غير معتمد") || (description.includes("معتمد") && description.includes("غير"))) return "غير معتمد";
if (description === "معتمد" || (description.includes("معتمد") && !description.includes("غير"))) return "معتمد";
return "";
}
function getDisplayValue(row, key) {
const col = RESOLVED[key];
return safeGet(row, col);
}
function renderSummary(rows) {
const approved = rows.filter((row) => resolveApprovalStatus(row) === "معتمد").length;
const notApproved = rows.filter((row) => resolveApprovalStatus(row) === "غير معتمد").length;
summaryPill.innerHTML = [
`إجمالي العينات: ${rows.length}`,
`معتمد: ${approved}`,
`غير معتمد: ${notApproved}`,
].join(" ");
}
function renderTable(rows) {
if (!rows.length) {
renderEmpty("لا توجد نتائج مطابقة.");
countPill.textContent = "النتائج: 0";
summaryPill.textContent = "—";
return;
}
countPill.textContent = `النتائج: ${rows.length}`;
renderSummary(rows);
const thead = `
${DISPLAY_COLUMNS.map((col) => `| ${escHtml(col.label)} | `).join("")}
`;
const tbody = `
${rows.map((row) => `
${DISPLAY_COLUMNS.map((col) => {
const value = getDisplayValue(row, col.key);
if (col.key === "collection" || col.key === "completion") {
return `| ${escHtml(value || "—")} | `;
}
return `${escHtml(value || "—")} | `;
}).join("")}
`).join("")}
`;
resultsEl.innerHTML = ``;
}
function doSearch() {
const q = normalizeArabic(qEl.value);
if (!q) {
renderEmpty("اكتب اسم الباحث ثم اضغط (بحث).");
countPill.textContent = "النتائج: 0";
summaryPill.textContent = "—";
return;
}
if (!RESOLVED.researcher) {
renderEmpty("⚠️ لم يتم التعرف على عمود اسم الباحث.");
countPill.textContent = "النتائج: 0";
summaryPill.textContent = "—";
return;
}
const rows = DATA.filter((row) => normalizeArabic(getDisplayValue(row, "researcher")).includes(q));
renderTable(rows);
}
function clearAll() {
qEl.value = "";
renderEmpty("اكتب اسمك للبحث");
countPill.textContent = "النتائج: 0";
summaryPill.textContent = "—";
qEl.focus();
}
function validateRequiredColumns() {
const missing = DISPLAY_COLUMNS
.filter((col) => !RESOLVED[col.key])
.map((col) => col.label);
return missing;
}
function init() {
if (!Array.isArray(DATA) || !DATA.length) {
totalChip.innerHTML = `إجمالي السجلات: 0`;
renderEmpty("⚠️ لا توجد بيانات داخل ملف data.js");
return;
}
COLS = Object.keys(DATA[0]).map(cleanHeader);
const originalCols = Object.keys(DATA[0]);
COLS = originalCols;
resolveColumns();
totalChip.innerHTML = `إجمالي السجلات: ${DATA.length}`;
const missing = validateRequiredColumns();
if (missing.length) {
renderEmpty(`⚠️ تعذر العثور على الأعمدة التالية في البيانات:\n${missing.join("\n")}`);
return;
}
clearAll();
}
btnSearch.addEventListener("click", doSearch);
btnClear.addEventListener("click", clearAll);
qEl.addEventListener("keydown", (ev) => {
if (ev.key === "Enter") doSearch();
});
qEl.addEventListener("input", () => {
const value = normalizeArabic(qEl.value);
if (value.length >= 2) doSearch();
if (!qEl.value.trim()) clearAll();
});
init();