stat2025 commited on
Commit
fc07d9c
·
verified ·
1 Parent(s): 633e8c5

Upload 2 files

Browse files
Files changed (2) hide show
  1. app.js +32 -1
  2. style.css +84 -1
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
- wrapper.append(labelElement, valueElement);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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: var(--surface);
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;