stat2025 commited on
Commit
0211fb5
·
verified ·
1 Parent(s): dba6001

Upload 6 files

Browse files
Files changed (3) hide show
  1. README.md +2 -0
  2. app.js +44 -3
  3. style.css +75 -0
README.md CHANGED
@@ -25,6 +25,8 @@ short_description: نظام استعلام المنشآت الصناعية
25
  - إذا كانت الخانة تحتوي على إحداثيات رقمية، يظهر رابط مباشر إلى خرائط Google.
26
  - إذا كانت الخانة فارغة، لا يظهر حقل الإحداثيات.
27
  - إذا كانت الخانة تحتوي على نص تواصل ورقم جوال، تظهر باسم "إفادة مدن" مع أزرار نسخ الرقم وواتساب ونسخ رسالة مقترحة.
 
 
28
 
29
  ## تحديث البيانات
30
 
 
25
  - إذا كانت الخانة تحتوي على إحداثيات رقمية، يظهر رابط مباشر إلى خرائط Google.
26
  - إذا كانت الخانة فارغة، لا يظهر حقل الإحداثيات.
27
  - إذا كانت الخانة تحتوي على نص تواصل ورقم جوال، تظهر باسم "إفادة مدن" مع أزرار نسخ الرقم وواتساب ونسخ رسالة مقترحة.
28
+ - يتم تمييز الإحداثيات وإفادة مدن بصريًا بألوان مختلفة.
29
+ - يحفظ النظام آخر منطقة ومدينة وبحث تم استخدامها على نفس المتصفح.
30
 
31
  ## تحديث البيانات
32
 
app.js CHANGED
@@ -27,6 +27,7 @@ const regionStats = document.getElementById("regionStats");
27
  const toast = document.getElementById("toast");
28
 
29
  const PAGE_SIZE = 24;
 
30
  const CONTACT_MESSAGE = (name) =>
31
  `السلام عليكم ورحمة الله وبركاته\n\nأستاذي الكريم،\nنأمل تزويدنا بموقع منشأة (${name || "العينة"})، وذلك لاستكمال بيانات الزيارة الميدانية.\n\nشاكرين لكم تعاونكم.`;
32
 
@@ -34,6 +35,7 @@ let rows = [];
34
  let visibleRows = [];
35
  let renderedCount = 0;
36
  let toastTimer;
 
37
 
38
  function base64ToBytes(value) {
39
  const binary = atob(value);
@@ -89,6 +91,26 @@ function setOptions(select, values, placeholder) {
89
  values.forEach((value) => select.add(new Option(value, value)));
90
  }
91
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
92
  function updateRegionButtonState() {
93
  regionButtons.querySelectorAll(".region-choice").forEach((button) => {
94
  const isActive = button.dataset.region === regionSelect.value;
@@ -190,13 +212,14 @@ function createCoordinatesBlock(row) {
190
  if (!value) return null;
191
 
192
  const item = document.createElement("div");
193
- item.className = "detail-item coordinates-detail";
 
194
  const label = document.createElement("span");
195
  label.className = "detail-label";
196
- label.textContent = isCoordinate(value) ? "الإحداثيات" : "إفادة مدن";
197
  item.append(label);
198
 
199
- if (isCoordinate(value)) {
200
  item.append(
201
  createActionLink(
202
  "اضغط هنا للذهاب بخرائط Google",
@@ -321,6 +344,7 @@ function applyFilters() {
321
  resultsTitle.textContent = city || region || "نتائج البحث";
322
  resultsMeta.textContent = `${visibleRows.length} من أصل ${scopedRows.length} منشأة`;
323
  renderVisibleRows(true);
 
324
  }
325
 
326
  function initializeDashboard(data) {
@@ -359,6 +383,22 @@ function initializeDashboard(data) {
359
  );
360
  setOptions(citySelect, [], "اختر المدينة الصناعية");
361
  citySelect.disabled = true;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
362
  applyFilters();
363
  }
364
 
@@ -411,6 +451,7 @@ searchInput.addEventListener("input", applyFilters);
411
  loadMoreButton.addEventListener("click", () => renderVisibleRows());
412
  clearFiltersButton.addEventListener("click", () => {
413
  searchInput.value = "";
 
414
  setRegion("");
415
  showToast("تم مسح الاختيارات");
416
  });
 
27
  const toast = document.getElementById("toast");
28
 
29
  const PAGE_SIZE = 24;
30
+ const STATE_KEY = "icsInquiryFilters";
31
  const CONTACT_MESSAGE = (name) =>
32
  `السلام عليكم ورحمة الله وبركاته\n\nأستاذي الكريم،\nنأمل تزويدنا بموقع منشأة (${name || "العينة"})، وذلك لاستكمال بيانات الزيارة الميدانية.\n\nشاكرين لكم تعاونكم.`;
33
 
 
35
  let visibleRows = [];
36
  let renderedCount = 0;
37
  let toastTimer;
38
+ let isRestoringState = false;
39
 
40
  function base64ToBytes(value) {
41
  const binary = atob(value);
 
91
  values.forEach((value) => select.add(new Option(value, value)));
92
  }
93
 
94
+ function saveFilterState() {
95
+ if (isRestoringState) return;
96
+ localStorage.setItem(
97
+ STATE_KEY,
98
+ JSON.stringify({
99
+ region: regionSelect.value,
100
+ city: citySelect.value,
101
+ search: searchInput.value,
102
+ }),
103
+ );
104
+ }
105
+
106
+ function getSavedFilterState() {
107
+ try {
108
+ return JSON.parse(localStorage.getItem(STATE_KEY) || "{}");
109
+ } catch {
110
+ return {};
111
+ }
112
+ }
113
+
114
  function updateRegionButtonState() {
115
  regionButtons.querySelectorAll(".region-choice").forEach((button) => {
116
  const isActive = button.dataset.region === regionSelect.value;
 
212
  if (!value) return null;
213
 
214
  const item = document.createElement("div");
215
+ const hasCoordinates = isCoordinate(value);
216
+ item.className = `detail-item coordinates-detail ${hasCoordinates ? "map-detail" : "statement-detail"}`;
217
  const label = document.createElement("span");
218
  label.className = "detail-label";
219
+ label.textContent = hasCoordinates ? "الإحداثيات" : "إفادة مدن";
220
  item.append(label);
221
 
222
+ if (hasCoordinates) {
223
  item.append(
224
  createActionLink(
225
  "اضغط هنا للذهاب بخرائط Google",
 
344
  resultsTitle.textContent = city || region || "نتائج البحث";
345
  resultsMeta.textContent = `${visibleRows.length} من أصل ${scopedRows.length} منشأة`;
346
  renderVisibleRows(true);
347
+ saveFilterState();
348
  }
349
 
350
  function initializeDashboard(data) {
 
383
  );
384
  setOptions(citySelect, [], "اختر المدينة الصناعية");
385
  citySelect.disabled = true;
386
+ restoreFilterState();
387
+ }
388
+
389
+ function restoreFilterState() {
390
+ const saved = getSavedFilterState();
391
+ isRestoringState = true;
392
+ searchInput.value = saved.search || "";
393
+ if (saved.region && [...regionSelect.options].some((option) => option.value === saved.region)) {
394
+ setRegion(saved.region);
395
+ if (saved.city && [...citySelect.options].some((option) => option.value === saved.city)) {
396
+ citySelect.value = saved.city;
397
+ }
398
+ } else {
399
+ setRegion("");
400
+ }
401
+ isRestoringState = false;
402
  applyFilters();
403
  }
404
 
 
451
  loadMoreButton.addEventListener("click", () => renderVisibleRows());
452
  clearFiltersButton.addEventListener("click", () => {
453
  searchInput.value = "";
454
+ localStorage.removeItem(STATE_KEY);
455
  setRegion("");
456
  showToast("تم مسح الاختيارات");
457
  });
style.css CHANGED
@@ -516,6 +516,81 @@ select:disabled {
516
  border-left: 0 !important;
517
  }
518
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
519
  .ltr-value .detail-value {
520
  direction: ltr;
521
  text-align: right;
 
516
  border-left: 0 !important;
517
  }
518
 
519
+ .coordinates-detail {
520
+ position: relative;
521
+ margin-top: 10px;
522
+ padding: 13px 14px !important;
523
+ border: 1px solid transparent !important;
524
+ border-radius: 8px;
525
+ }
526
+
527
+ .coordinates-detail::before {
528
+ content: "";
529
+ position: absolute;
530
+ top: 12px;
531
+ right: 0;
532
+ bottom: 12px;
533
+ width: 4px;
534
+ border-radius: 8px 0 0 8px;
535
+ }
536
+
537
+ .map-detail {
538
+ background: #edf9f3;
539
+ border-color: #bfead2 !important;
540
+ }
541
+
542
+ .map-detail::before {
543
+ background: #168a5b;
544
+ }
545
+
546
+ .statement-detail {
547
+ background: #eef7fb;
548
+ border-color: #c7e1ec !important;
549
+ }
550
+
551
+ .statement-detail::before {
552
+ background: #227997;
553
+ }
554
+
555
+ .map-detail .detail-label,
556
+ .statement-detail .detail-label {
557
+ display: inline-flex;
558
+ align-items: center;
559
+ gap: 6px;
560
+ min-height: 24px;
561
+ padding: 3px 8px;
562
+ border-radius: 8px;
563
+ }
564
+
565
+ .map-detail .detail-label {
566
+ color: #116343;
567
+ background: #dff4e9;
568
+ }
569
+
570
+ .statement-detail .detail-label {
571
+ color: #17647d;
572
+ background: #dff0f6;
573
+ }
574
+
575
+ .map-detail .action-link {
576
+ color: #116343;
577
+ background: #ffffff;
578
+ border-color: #b7e3ca;
579
+ }
580
+
581
+ .statement-detail .action-link {
582
+ color: #17647d;
583
+ background: #ffffff;
584
+ border-color: #bddce8;
585
+ }
586
+
587
+ .map-detail .action-link:hover,
588
+ .statement-detail .action-link:hover {
589
+ color: #fff;
590
+ background: var(--primary);
591
+ border-color: var(--primary);
592
+ }
593
+
594
  .ltr-value .detail-value {
595
  direction: ltr;
596
  text-align: right;