Upload 2 files
Browse files
app.js
CHANGED
|
@@ -67,6 +67,7 @@ const copyAllButton = document.getElementById("copyAllButton");
|
|
| 67 |
const loadMoreWrap = document.getElementById("loadMoreWrap");
|
| 68 |
const loadMoreButton = document.getElementById("loadMoreButton");
|
| 69 |
const loadMoreMeta = document.getElementById("loadMoreMeta");
|
|
|
|
| 70 |
const toast = document.getElementById("toast");
|
| 71 |
|
| 72 |
let allRows = [];
|
|
@@ -224,6 +225,8 @@ function createDetail(key, label, isContact, value) {
|
|
| 224 |
labelElement.className = "detail-label";
|
| 225 |
labelElement.textContent = label;
|
| 226 |
|
|
|
|
|
|
|
| 227 |
const valueElement = document.createElement("span");
|
| 228 |
valueElement.className = "detail-value";
|
| 229 |
valueElement.textContent = String(value);
|
|
@@ -232,7 +235,26 @@ function createDetail(key, label, isContact, value) {
|
|
| 232 |
valueElement.style.textAlign = "right";
|
| 233 |
}
|
| 234 |
|
| 235 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 236 |
return wrapper;
|
| 237 |
}
|
| 238 |
|
|
@@ -443,6 +465,14 @@ function performLogout(message = "") {
|
|
| 443 |
if (message) showToast(message);
|
| 444 |
}
|
| 445 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 446 |
function handleActivity() {
|
| 447 |
if (!dashboardView.hidden) startInactivityTimer();
|
| 448 |
}
|
|
@@ -541,6 +571,7 @@ researcherSelect.addEventListener("change", () => {
|
|
| 541 |
statusSelect.addEventListener("change", applyFilters);
|
| 542 |
searchInput.addEventListener("input", applyFilters);
|
| 543 |
loadMoreButton.addEventListener("click", () => renderVisibleRows());
|
|
|
|
| 544 |
ACTIVITY_EVENTS.forEach((eventName) =>
|
| 545 |
document.addEventListener(eventName, handleActivity, { passive: true }),
|
| 546 |
);
|
|
|
|
| 67 |
const loadMoreWrap = document.getElementById("loadMoreWrap");
|
| 68 |
const loadMoreButton = document.getElementById("loadMoreButton");
|
| 69 |
const loadMoreMeta = document.getElementById("loadMoreMeta");
|
| 70 |
+
const clearFiltersButton = document.getElementById("clearFiltersButton");
|
| 71 |
const toast = document.getElementById("toast");
|
| 72 |
|
| 73 |
let allRows = [];
|
|
|
|
| 225 |
labelElement.className = "detail-label";
|
| 226 |
labelElement.textContent = label;
|
| 227 |
|
| 228 |
+
const valueRow = document.createElement("div");
|
| 229 |
+
valueRow.className = "detail-value-row";
|
| 230 |
const valueElement = document.createElement("span");
|
| 231 |
valueElement.className = "detail-value";
|
| 232 |
valueElement.textContent = String(value);
|
|
|
|
| 235 |
valueElement.style.textAlign = "right";
|
| 236 |
}
|
| 237 |
|
| 238 |
+
valueRow.append(valueElement);
|
| 239 |
+
if (key === "phone" || key === "email") {
|
| 240 |
+
const copyFieldButton = document.createElement("button");
|
| 241 |
+
copyFieldButton.type = "button";
|
| 242 |
+
copyFieldButton.className = "copy-field-button";
|
| 243 |
+
copyFieldButton.setAttribute("aria-label", key === "phone" ? "نسخ رقم التواصل" : "نسخ البريد الإلكتروني");
|
| 244 |
+
copyFieldButton.title = key === "phone" ? "نسخ رقم التواصل" : "نسخ البريد الإلكتروني";
|
| 245 |
+
copyFieldButton.innerHTML = `
|
| 246 |
+
<svg viewBox="0 0 24 24" aria-hidden="true">
|
| 247 |
+
<rect x="8" y="8" width="11" height="11" rx="2"></rect>
|
| 248 |
+
<path d="M16 8V6a2 2 0 0 0-2-2H6a2 2 0 0 0-2 2v8a2 2 0 0 0 2 2h2"></path>
|
| 249 |
+
</svg>
|
| 250 |
+
`;
|
| 251 |
+
copyFieldButton.addEventListener("click", () =>
|
| 252 |
+
copyText(String(value), key === "phone" ? "تم نسخ رقم التواصل" : "تم نسخ البريد الإلكتروني"),
|
| 253 |
+
);
|
| 254 |
+
valueRow.append(copyFieldButton);
|
| 255 |
+
}
|
| 256 |
+
|
| 257 |
+
wrapper.append(labelElement, valueRow);
|
| 258 |
return wrapper;
|
| 259 |
}
|
| 260 |
|
|
|
|
| 465 |
if (message) showToast(message);
|
| 466 |
}
|
| 467 |
|
| 468 |
+
function clearFilters() {
|
| 469 |
+
supervisorSelect.value = "";
|
| 470 |
+
searchInput.value = "";
|
| 471 |
+
resetResearcherControls();
|
| 472 |
+
window.scrollTo({ top: 0, behavior: "smooth" });
|
| 473 |
+
showToast("تم مسح جميع الفلاتر");
|
| 474 |
+
}
|
| 475 |
+
|
| 476 |
function handleActivity() {
|
| 477 |
if (!dashboardView.hidden) startInactivityTimer();
|
| 478 |
}
|
|
|
|
| 571 |
statusSelect.addEventListener("change", applyFilters);
|
| 572 |
searchInput.addEventListener("input", applyFilters);
|
| 573 |
loadMoreButton.addEventListener("click", () => renderVisibleRows());
|
| 574 |
+
clearFiltersButton.addEventListener("click", clearFilters);
|
| 575 |
ACTIVITY_EVENTS.forEach((eventName) =>
|
| 576 |
document.addEventListener(eventName, handleActivity, { passive: true }),
|
| 577 |
);
|
style.css
CHANGED
|
@@ -403,12 +403,16 @@ svg {
|
|
| 403 |
}
|
| 404 |
|
| 405 |
.controls-card {
|
|
|
|
|
|
|
|
|
|
| 406 |
margin-top: 18px;
|
| 407 |
padding: 22px;
|
| 408 |
-
background:
|
| 409 |
border: 1px solid var(--line);
|
| 410 |
border-radius: 20px;
|
| 411 |
box-shadow: 0 14px 34px rgba(24, 66, 91, 0.08);
|
|
|
|
| 412 |
}
|
| 413 |
|
| 414 |
.filters-grid {
|
|
@@ -417,6 +421,38 @@ svg {
|
|
| 417 |
gap: 16px;
|
| 418 |
}
|
| 419 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 420 |
.select-wrap select {
|
| 421 |
padding: 0 15px 0 42px;
|
| 422 |
appearance: none;
|
|
@@ -691,6 +727,37 @@ input:disabled {
|
|
| 691 |
line-height: 1.6;
|
| 692 |
}
|
| 693 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 694 |
.contact-detail .detail-value {
|
| 695 |
color: var(--blue);
|
| 696 |
}
|
|
@@ -826,11 +893,27 @@ footer {
|
|
| 826 |
border-radius: 17px;
|
| 827 |
}
|
| 828 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 829 |
.filters-grid {
|
| 830 |
grid-template-columns: 1fr;
|
| 831 |
gap: 13px;
|
| 832 |
}
|
| 833 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 834 |
.status-chips {
|
| 835 |
flex-wrap: nowrap;
|
| 836 |
overflow-x: auto;
|
|
|
|
| 403 |
}
|
| 404 |
|
| 405 |
.controls-card {
|
| 406 |
+
position: sticky;
|
| 407 |
+
z-index: 12;
|
| 408 |
+
top: 10px;
|
| 409 |
margin-top: 18px;
|
| 410 |
padding: 22px;
|
| 411 |
+
background: rgba(255, 255, 255, 0.96);
|
| 412 |
border: 1px solid var(--line);
|
| 413 |
border-radius: 20px;
|
| 414 |
box-shadow: 0 14px 34px rgba(24, 66, 91, 0.08);
|
| 415 |
+
backdrop-filter: blur(16px);
|
| 416 |
}
|
| 417 |
|
| 418 |
.filters-grid {
|
|
|
|
| 421 |
gap: 16px;
|
| 422 |
}
|
| 423 |
|
| 424 |
+
.filters-actions {
|
| 425 |
+
display: flex;
|
| 426 |
+
justify-content: flex-start;
|
| 427 |
+
margin-top: 14px;
|
| 428 |
+
}
|
| 429 |
+
|
| 430 |
+
.clear-filters-button {
|
| 431 |
+
display: inline-flex;
|
| 432 |
+
align-items: center;
|
| 433 |
+
justify-content: center;
|
| 434 |
+
gap: 7px;
|
| 435 |
+
min-height: 38px;
|
| 436 |
+
padding: 0 13px;
|
| 437 |
+
color: #607583;
|
| 438 |
+
font-size: 13px;
|
| 439 |
+
font-weight: 700;
|
| 440 |
+
background: #f7fafb;
|
| 441 |
+
border: 1px solid var(--line);
|
| 442 |
+
border-radius: 11px;
|
| 443 |
+
}
|
| 444 |
+
|
| 445 |
+
.clear-filters-button:hover {
|
| 446 |
+
color: var(--danger);
|
| 447 |
+
background: #fff7f8;
|
| 448 |
+
border-color: #ecc9cf;
|
| 449 |
+
}
|
| 450 |
+
|
| 451 |
+
.clear-filters-button svg {
|
| 452 |
+
width: 17px;
|
| 453 |
+
height: 17px;
|
| 454 |
+
}
|
| 455 |
+
|
| 456 |
.select-wrap select {
|
| 457 |
padding: 0 15px 0 42px;
|
| 458 |
appearance: none;
|
|
|
|
| 727 |
line-height: 1.6;
|
| 728 |
}
|
| 729 |
|
| 730 |
+
.detail-value-row {
|
| 731 |
+
display: flex;
|
| 732 |
+
align-items: center;
|
| 733 |
+
justify-content: space-between;
|
| 734 |
+
gap: 8px;
|
| 735 |
+
}
|
| 736 |
+
|
| 737 |
+
.copy-field-button {
|
| 738 |
+
flex: 0 0 auto;
|
| 739 |
+
width: 34px;
|
| 740 |
+
height: 34px;
|
| 741 |
+
display: grid;
|
| 742 |
+
place-items: center;
|
| 743 |
+
padding: 0;
|
| 744 |
+
color: var(--blue);
|
| 745 |
+
background: var(--sky);
|
| 746 |
+
border: 1px solid #cee3ef;
|
| 747 |
+
border-radius: 9px;
|
| 748 |
+
}
|
| 749 |
+
|
| 750 |
+
.copy-field-button:hover {
|
| 751 |
+
color: white;
|
| 752 |
+
background: var(--blue);
|
| 753 |
+
border-color: var(--blue);
|
| 754 |
+
}
|
| 755 |
+
|
| 756 |
+
.copy-field-button svg {
|
| 757 |
+
width: 17px;
|
| 758 |
+
height: 17px;
|
| 759 |
+
}
|
| 760 |
+
|
| 761 |
.contact-detail .detail-value {
|
| 762 |
color: var(--blue);
|
| 763 |
}
|
|
|
|
| 893 |
border-radius: 17px;
|
| 894 |
}
|
| 895 |
|
| 896 |
+
.controls-card {
|
| 897 |
+
top: 6px;
|
| 898 |
+
max-height: calc(100vh - 12px);
|
| 899 |
+
overflow-y: auto;
|
| 900 |
+
}
|
| 901 |
+
|
| 902 |
.filters-grid {
|
| 903 |
grid-template-columns: 1fr;
|
| 904 |
gap: 13px;
|
| 905 |
}
|
| 906 |
|
| 907 |
+
.filters-actions {
|
| 908 |
+
margin-top: 12px;
|
| 909 |
+
}
|
| 910 |
+
|
| 911 |
+
.clear-filters-button {
|
| 912 |
+
width: 100%;
|
| 913 |
+
min-height: 44px;
|
| 914 |
+
font-size: 14px;
|
| 915 |
+
}
|
| 916 |
+
|
| 917 |
.status-chips {
|
| 918 |
flex-wrap: nowrap;
|
| 919 |
overflow-x: auto;
|