mohammed2449 commited on
Commit
6245a17
·
verified ·
1 Parent(s): 8162d59

📄 أمر تنفيذي: استكمال الوظائف الناقصة في تطبيق المتاجر الوطني 📌 الهدف: تنفيذ الوظائف التالية لضمان تجربة مستخدم متكاملة تشمل الطلبات، التقييم، الدعم الفني، الإشعارات، لوحة المشرف، وحماية البيانات. 🧩 المهام المطلوبة: 1. نظام الطلبات: - تصميم واجهة "طلب جديد" تشمل اختيار المنتج، الكمية، الدفع، والعنوان. - إنشاء قاعدة بيانات للطلبات (الحالة: pending, confirmed, delivered). - ربط الطلبات بواجهة المستخدم والمتجر عبر API موحد. - عرض سجل الطلبات في صفحة "طلباتي". 2. نظام التقييم والمراجعة: - واجهة تقييم بعد كل طلب (نجوم + تعليق). - حفظ التقييمات وربطها بالمتجر. - عرض متوسط التقييم في بطاقة المتجر. 3. نظام الدعم الفني: - دمج خدمة دردشة فورية (Firebase Chat أو WebSocket). - واجهة "الدعم الفني" تشمل إرسال رسالة، رفع صورة، متابعة الحالة. - لوحة تذاكر للمشرفين للرد على المستخدمين. 4. نظام الإشعارات الديناميكية: - إعداد خدمة إرسال إشعارات (FCM أو OneSignal). - لوحة تحكم لإرسال الإشعارات حسب القسم أو المتجر. - دعم الإشعارات التفاعلية (فتح صفحة معينة عند الضغط). 5. لوحة تحكم للمشرفين: - إدارة المتاجر، الطلبات، التقييمات، والإشعارات. - حماية الدخول بصلاحيات خاصة. - دعم الإحصائيات والرسوم البيانية. 6. حماية البيانات والخصوصية: - صفحة "الخصوصية" تشمل السياسات والموافقة. - دعم حذف الحساب وتصدير البيانات. - تشفير بيانات الجلسات والمفضلة محليًا. 🛠 التقنيات المقترحة: - الطلبات: RESTful API + SQLite أو MongoDB - التقييم: Firebase أو قاعدة بيانات محلية - الدعم الفني: Firebase Chat أو WebSocket - الإشعارات: FCM أو OneSignal - لوحة المشرف: React Admin أو لوحة مخصصة - الحماية: JWT + تشفير محلي 📅 الجدول الزمني المقترح: - الأسبوع 1: الطلبات والتقييم - الأسبوع 2: الدعم الفني والإشعارات - الأسبوع 3: لوحة المشرف والخصوصية - الأسبوع 4: اختبار شامل وتوثيق 📎 ملاحظات: - يجب توثيق كل وظيفة بشكل مستقل. - الالتزام بالتصميم الموحد واللغة العربية. - ضمان قابلية التوسع والتخصيص مستقبلاً. - Initial Deployment

Browse files
Files changed (2) hide show
  1. README.md +7 -5
  2. index.html +817 -19
README.md CHANGED
@@ -1,10 +1,12 @@
1
  ---
2
- title: M
3
- emoji:
4
- colorFrom: pink
5
- colorTo: gray
6
  sdk: static
7
  pinned: false
 
 
8
  ---
9
 
10
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
1
  ---
2
+ title: m
3
+ emoji: 🐳
4
+ colorFrom: yellow
5
+ colorTo: pink
6
  sdk: static
7
  pinned: false
8
+ tags:
9
+ - deepsite
10
  ---
11
 
12
+ Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
index.html CHANGED
@@ -1,19 +1,817 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
19
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="ar" dir="rtl">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>مسار المستهلك</title>
7
+ <script src="https://cdn.tailwindcss.com"></script>
8
+ <script>
9
+ tailwind.config = {
10
+ theme: {
11
+ extend: {
12
+ fontSize: {
13
+ 'xxs': '0.6rem',
14
+ }
15
+ }
16
+ }
17
+ }
18
+ </script>
19
+ <link href="https://fonts.googleapis.com/css2?family=Tajawal:wght@400;500;700&display=swap" rel="stylesheet">
20
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
21
+ <!-- Rating Stars Template -->
22
+ <template id="ratingStarsTemplate">
23
+ <div class="flex items-center">
24
+ <div class="flex">
25
+ <i class="fas fa-star text-yellow-400"></i>
26
+ <i class="fas fa-star text-yellow-400"></i>
27
+ <i class="fas fa-star text-yellow-400"></i>
28
+ <i class="fas fa-star text-yellow-400"></i>
29
+ <i class="fas fa-star text-yellow-400"></i>
30
+ </div>
31
+ <span class="text-xs text-gray-500 mr-1">(0)</span>
32
+ </div>
33
+ </template>
34
+
35
+ <style>
36
+ body {
37
+ font-family: 'Tajawal', sans-serif;
38
+ transition: all 0.3s ease;
39
+ }
40
+
41
+ .slide-in {
42
+ animation: slideIn 0.3s forwards;
43
+ }
44
+
45
+ .slide-out {
46
+ animation: slideOut 0.3s forwards;
47
+ }
48
+
49
+ @keyframes slideIn {
50
+ from { transform: translateX(100%); }
51
+ to { transform: translateX(0); }
52
+ }
53
+
54
+ @keyframes slideOut {
55
+ from { transform: translateX(0); }
56
+ to { transform: translateX(100%); }
57
+ }
58
+
59
+ .ticker {
60
+ animation: ticker 20s linear infinite;
61
+ }
62
+
63
+ @keyframes ticker {
64
+ 0% { transform: translateX(100%); }
65
+ 100% { transform: translateX(-100%); }
66
+ }
67
+
68
+ .dark-mode {
69
+ background-color: #1a202c;
70
+ color: #f7fafc;
71
+ }
72
+
73
+ .dark-mode .sidebar {
74
+ background-color: #2d3748;
75
+ }
76
+
77
+ .dark-mode .card {
78
+ background-color: #2d3748;
79
+ }
80
+
81
+ /* New styles for smaller icons and modern design */
82
+ .icon-sm {
83
+ font-size: 1.1rem;
84
+ }
85
+
86
+ .store-card {
87
+ min-width: 120px;
88
+ height: 120px;
89
+ display: flex;
90
+ flex-direction: column;
91
+ justify-content: center;
92
+ align-items: center;
93
+ transition: all 0.2s ease;
94
+ }
95
+
96
+ .store-card:hover {
97
+ transform: translateY(-5px);
98
+ }
99
+
100
+ /* Bottom nav item animation */
101
+ nav a {
102
+ transition: all 0.2s ease;
103
+ }
104
+
105
+ nav a:hover, nav a.active {
106
+ color: #3b82f6;
107
+ }
108
+ </style>
109
+ </head>
110
+ <body class="bg-gray-100 text-gray-800">
111
+ <!-- Navigation Sidebar -->
112
+ <div class="fixed right-0 top-0 h-full w-64 bg-white shadow-lg z-50 transform translate-x-full sidebar transition-transform duration-300">
113
+ <div class="p-4 border-b border-gray-200 dark:border-gray-700">
114
+ <div class="flex items-center justify-between">
115
+ <h2 class="text-xl font-bold">مسار المستهلك</h2>
116
+ <button id="closeSidebar" class="text-gray-500 hover:text-gray-700 dark:text-gray-300 dark:hover:text-white">
117
+ <i class="fas fa-times"></i>
118
+ </button>
119
+ </div>
120
+ </div>
121
+ <nav class="p-4">
122
+ <ul class="space-y-4">
123
+ <li>
124
+ <a href="#" class="flex items-center p-2 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-700">
125
+ <i class="fas fa-home ml-2"></i>
126
+ <span>الصفحة الرئيسية</span>
127
+ </a>
128
+ </li>
129
+ <li>
130
+ <button id="categoriesBtn" class="flex items-center justify-between w-full p-2 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-700">
131
+ <div class="flex items-center">
132
+ <i class="fas fa-th-large ml-2"></i>
133
+ <span>الأقسام</span>
134
+ </div>
135
+ <i class="fas fa-chevron-down text-xs"></i>
136
+ </button>
137
+ <ul id="categoriesDropdown" class="hidden pl-4 mt-1 space-y-1">
138
+ <li><a href="#" class="block p-2 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-700">السوبر ماركت والأسواق العامة</a></li>
139
+ <li><a href="#" class="block p-2 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-700">الملابس والأزياء</a></li>
140
+ <li><a href="#" class="block p-2 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-700">الأثاث والمفروشات</a></li>
141
+ <li><a href="#" class="block p-2 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-700">الإلكترونيات والتقنية</a></li>
142
+ <li><a href="#" class="block p-2 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-700">العناية الشخصية والجمال</a></li>
143
+ <li><a href="#" class="block p-2 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-700">المطاعم والمقاهي</a></li>
144
+ <li><a href="#" class="block p-2 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-700">الصيدليات والرعاية الصحية</a></li>
145
+ <li><a href="#" class="block p-2 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-700">الخدمات المنزلية والصيانة</a></li>
146
+ <li><a href="#" class="block p-2 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-700">شركات التوصيل</a></li>
147
+ </ul>
148
+ </li>
149
+ <li>
150
+ <a href="#" class="flex items-center p-2 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-700">
151
+ <i class="fas fa-tags ml-2"></i>
152
+ <span>العروض والخصومات</span>
153
+ </a>
154
+ </li>
155
+ <li>
156
+ <a href="#" class="flex items-center p-2 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-700">
157
+ <i class="fas fa-cog ml-2"></i>
158
+ <span>الإعدادات</span>
159
+ </a>
160
+ </li>
161
+ <li>
162
+ <a href="#" class="flex items-center p-2 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-700">
163
+ <i class="fas fa-question-circle ml-2"></i>
164
+ <span>مركز المساعدة</span>
165
+ </a>
166
+ </li>
167
+ <li>
168
+ <a href="/admin" class="flex items-center p-2 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-700">
169
+ <i class="fas fa-tachometer-alt ml-2"></i>
170
+ <span>لوحة التحكم</span>
171
+ </a>
172
+ </li>
173
+ <li id="authMenuItem">
174
+ <a href="#" id="authBtn" class="flex items-center p-2 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-700 text-blue-600 dark:text-blue-400">
175
+ <i class="fas fa-sign-in-alt ml-2" id="authIcon"></i>
176
+ <span id="authText">تسجيل الدخول</span>
177
+ </a>
178
+ </li>
179
+ <div id="userDropdown" class="hidden p-4 border-t border-gray-200 dark:border-gray-700">
180
+ <div class="flex items-center mb-4">
181
+ <img id="userAvatar" src="https://via.placeholder.com/40" class="rounded-full w-10 h-10 mr-3" alt="User">
182
+ <div>
183
+ <p id="userName" class="font-medium"></p>
184
+ <p id="userEmail" class="text-sm text-gray-500 dark:text-gray-400"></p>
185
+ </div>
186
+ </div>
187
+ <ul class="space-y-2">
188
+ <li><a href="#" class="flex items-center p-2 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-700"><i class="fas fa-cog ml-2"></i> الإعدادات</a></li>
189
+ <li><a href="#" class="flex items-center p-2 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-700"><i class="fas fa-shield-alt ml-2"></i> الأمان</a></li>
190
+ <li><a href="#" id="logoutBtn" class="flex items-center p-2 rounded-lg text-red-500 hover:bg-red-50 dark:hover:bg-red-900"><i class="fas fa-sign-out-alt ml-2"></i> تسجيل الخروج</a></li>
191
+ </ul>
192
+ </div>
193
+ </ul>
194
+ </nav>
195
+ </div>
196
+
197
+ <!-- Notifications Dropdown -->
198
+ <div id="notificationsDropdown" class="fixed right-4 top-16 w-72 bg-white dark:bg-gray-800 rounded-lg shadow-lg z-50 hidden border border-gray-200 dark:border-gray-700">
199
+ <div class="p-3 border-b border-gray-200 dark:border-gray-700 flex justify-between items-center">
200
+ <h3 class="font-bold">الإشعارات</h3>
201
+ <button id="markAllRead" class="text-blue-500 text-sm">تمييز الكل كمقروء</button>
202
+ </div>
203
+ <div class="max-h-96 overflow-y-auto">
204
+ <div id="notificationsList" class="p-2">
205
+ <!-- Notifications will be loaded dynamically -->
206
+ <div class="text-center py-4 text-gray-500">لا توجد إشعارات جديدة</div>
207
+ </div>
208
+ </div>
209
+ <div class="p-2 border-t border-gray-200 dark:border-gray-700 text-center">
210
+ <a href="/notifications" class="text-blue-500 text-sm">عرض جميع الإشعارات</a>
211
+ </div>
212
+ </div>
213
+
214
+ <!-- Main Content -->
215
+ <div class="container mx-auto px-4 pb-16">
216
+ <!-- Header -->
217
+ <header class="flex justify-between items-center py-4 sticky top-0 bg-white dark:bg-gray-800 z-40 shadow-sm">
218
+ <button id="menuBtn" class="text-gray-700 dark:text-gray-300">
219
+ <i class="fas fa-bars text-2xl"></i>
220
+ </button>
221
+ <h1 class="text-2xl font-bold text-blue-600 dark:text-blue-400">مسار المستهلك</h1>
222
+ <div class="flex items-center space-x-4 space-x-reverse">
223
+ <button id="notificationsBtn" class="relative text-gray-700 dark:text-gray-300">
224
+ <i class="fas fa-bell text-xl"></i>
225
+ <span id="notificationBadge" class="absolute -top-1 -right-1 bg-red-500 text-white text-xs rounded-full h-4 w-4 flex items-center justify-center hidden">0</span>
226
+ </button>
227
+ <button id="themeToggle" class="text-gray-700 dark:text-gray-300">
228
+ <i class="fas fa-moon text-xl"></i>
229
+ </button>
230
+ </header>
231
+
232
+ <!-- Ticker Slider -->
233
+ <div class="bg-blue-100 dark:bg-blue-900 p-2 mb-6 rounded-lg overflow-hidden">
234
+ <div class="flex items-center whitespace-nowrap ticker">
235
+ <div class="mx-4 text-blue-800 dark:text-blue-200">
236
+ <span class="font-bold">عرض خاص:</span> خصم ٣٠٪ على جميع المنتجات في سوق الجمال حتى نهاية الشهر
237
+ </div>
238
+ <div class="mx-4 text-blue-800 dark:text-blue-200">
239
+ <span class="font-bold">عرض جديد:</span> هاتف سامسونج جالكسي S23 مع هدية مجانية
240
+ </div>
241
+ <div class="mx-4 text-blue-800 dark:text-blue-200">
242
+ <span class="font-bold">عرض خاص:</span> توصيل مجاني لجميع الطلبات فوق ١٠٠ ريال
243
+ </div>
244
+ </div>
245
+ </div>
246
+
247
+ <!-- Quick Access Cards -->
248
+ <h2 class="text-xl font-bold mb-4">الإمكانيات السريعة</h2>
249
+ <div class="relative mb-8">
250
+ <div class="overflow-x-auto scrollbar-hide">
251
+ <div class="flex space-x-4 pb-4" id="cardsContainer">
252
+ <!-- Cards will be added dynamically -->
253
+ </div>
254
+ </div>
255
+ <button id="showMore" class="absolute left-0 bottom-0 bg-blue-600 text-white px-4 py-2 rounded-lg hover:bg-blue-700 transition">
256
+ عرض المزيد <i class="fas fa-chevron-left mr-2"></i>
257
+ </button>
258
+ </div>
259
+
260
+ <!-- Favorite Stores -->
261
+ <h2 class="text-xl font-bold mb-4">متاجري المفضلة</h2>
262
+ <div class="relative mb-8">
263
+ <div class="overflow-x-auto scrollbar-hide">
264
+ <div class="flex space-x-4 pb-4" id="favoritesContainer">
265
+ <!-- Favorite stores will be added dynamically -->
266
+ </div>
267
+ </div>
268
+ <button id="addFavorite" class="absolute left-0 bottom-0 bg-blue-600 text-white px-4 py-2 rounded-lg hover:bg-blue-700 transition">
269
+ إضافة متجر جديد <i class="fas fa-plus mr-2"></i>
270
+ </button>
271
+ </div>
272
+
273
+ <!-- Stores Section (hidden by default) -->
274
+ <div id="storesSection" class="hidden mb-8">
275
+ <div class="flex justify-between items-center mb-4">
276
+ <h2 class="text-xl font-bold" id="storeSectionTitle">المتاجر</h2>
277
+ <button id="backToCategories" class="text-blue-600 dark:text-blue-400">
278
+ <i class="fas fa-arrow-left mr-2"></i> الرجوع للأقسام
279
+ </button>
280
+ </div>
281
+
282
+ <!-- Search Bar -->
283
+ <div class="mb-4 relative">
284
+ <input type="text" id="storeSearch" placeholder="ابحث عن متجر..."
285
+ class="w-full p-3 rounded-lg border border-gray-300 dark:border-gray-600 dark:bg-gray-700">
286
+ <i class="fas fa-search absolute left-3 top-3.5 text-gray-400"></i>
287
+ </div>
288
+
289
+ <!-- Stores Grid -->
290
+ <div class="grid grid-cols-2 md:grid-cols-4 gap-4" id="storesGrid">
291
+ <!-- Stores will be loaded dynamically -->
292
+ </div>
293
+ </div>
294
+
295
+ <!-- Store View Container (hidden by default) -->
296
+ <div id="storeViewContainer" class="hidden fixed inset-0 bg-white dark:bg-gray-800 z-50 overflow-y-auto">
297
+ <div class="container mx-auto px-4 py-4">
298
+ <div class="flex justify-between items-center mb-4 sticky top-0 bg-white dark:bg-gray-800 py-2 z-10">
299
+ <h2 class="text-xl font-bold" id="storeNameHeader"></h2>
300
+ <button id="closeStoreView" class="text-red-500">
301
+ <i class="fas fa-times text-xl"></i>
302
+ </button>
303
+ </div>
304
+
305
+ <!-- WebView Container -->
306
+ <div id="storeWebView" class="w-full h-screen">
307
+ <!-- Store content will be loaded here via WebView/API -->
308
+ </div>
309
+ </div>
310
+ </div>
311
+
312
+ <!-- Offers Section -->
313
+ <h2 class="text-xl font-bold mb-4">عروض اليوم</h2>
314
+ <div class="grid md:grid-cols-2 gap-4 mb-8">
315
+ <div class="bg-gradient-to-r from-blue-500 to-blue-700 text-white p-6 rounded-lg">
316
+ <h3 class="text-xl font-bold mb-2">خصم يصل إلى ٤٠٪</h3>
317
+ <p class="mb-4">على جميع الأجهزة المنزلية في سوق الإلكترونيات</p>
318
+ <button class="bg-white text-blue-600 px-4 py-2 rounded-lg font-bold">عرض التفاصيل</button>
319
+ </div>
320
+ <div class="bg-gradient-to-r from-green-500 to-green-700 text-white p-6 rounded-lg">
321
+ <h3 class="text-xl font-bold mb-2">٢+١ مجانًا</h3>
322
+ <p class="mb-4">على منتجات العناية بالبشرة في صيدليات النهدي</p>
323
+ <button class="bg-white text-green-600 px-4 py-2 rounded-lg font-bold">عرض التفاصيل</button>
324
+ </div>
325
+ </div>
326
+ </div>
327
+
328
+ <script>
329
+ // Sample data for quick access cards
330
+ const quickAccessItems = [
331
+ { icon: 'fa-search', title: 'بحث سريع', color: 'bg-blue-100', textColor: 'text-blue-600' },
332
+ { icon: 'fa-history', title: 'آخر العروض', color: 'bg-green-100', textColor: 'text-green-600' },
333
+ { icon: 'fa-star', title: 'المفضلة', color: 'bg-yellow-100', textColor: 'text-yellow-600' },
334
+ { icon: 'fa-map-marker-alt', title: 'أقرب متجر', color: 'bg-red-100', textColor: 'text-red-600' },
335
+ { icon: 'fa-bell', title: 'التنبيهات', color: 'bg-purple-100', textColor: 'text-purple-600' },
336
+ { icon: 'fa-wallet', title: 'المحفظة', color: 'bg-indigo-100', textColor: 'text-indigo-600' },
337
+ ];
338
+
339
+ // DOM Elements
340
+ const menuBtn = document.getElementById('menuBtn');
341
+ const closeSidebar = document.getElementById('closeSidebar');
342
+ const sidebar = document.querySelector('.sidebar');
343
+ const themeToggle = document.getElementById('themeToggle');
344
+ const cardsContainer = document.getElementById('cardsContainer');
345
+ const showMore = document.getElementById('showMore');
346
+ const body = document.body;
347
+
348
+ // Initialize cards
349
+ function initCards() {
350
+ quickAccessItems.forEach(item => {
351
+ const card = document.createElement('div');
352
+ card.className = `flex-shrink-0 w-24 h-24 ${item.color} ${item.textColor} rounded-lg p-3 shadow-md flex flex-col items-center justify-center`;
353
+ card.innerHTML = `
354
+ <i class="fas ${item.icon} text-base mb-1"></i>
355
+ <span class="font-bold text-xxs">${item.title}</span>
356
+ `;
357
+ cardsContainer.appendChild(card);
358
+ });
359
+ }
360
+
361
+ // Toggle categories dropdown
362
+ document.getElementById('categoriesBtn').addEventListener('click', function(e) {
363
+ e.preventDefault();
364
+ document.getElementById('categoriesDropdown').classList.toggle('hidden');
365
+ this.querySelector('.fa-chevron-down').classList.toggle('fa-rotate-180');
366
+ });
367
+
368
+ // Close dropdown when clicking outside
369
+ document.addEventListener('click', function(e) {
370
+ if (!e.target.closest('#categoriesBtn') && !e.target.closest('#categoriesDropdown')) {
371
+ document.getElementById('categoriesDropdown').classList.add('hidden');
372
+ document.querySelector('#categoriesBtn .fa-chevron-down').classList.remove('fa-rotate-180');
373
+ }
374
+ });
375
+
376
+ // Toggle sidebar
377
+ menuBtn.addEventListener('click', () => {
378
+ sidebar.classList.remove('translate-x-full');
379
+ sidebar.classList.add('slide-in');
380
+ });
381
+
382
+ closeSidebar.addEventListener('click', () => {
383
+ sidebar.classList.add('translate-x-full');
384
+ sidebar.classList.add('slide-out');
385
+ });
386
+
387
+ // Toggle theme
388
+ themeToggle.addEventListener('click', () => {
389
+ body.classList.toggle('dark-mode');
390
+ const icon = themeToggle.querySelector('i');
391
+ if (body.classList.contains('dark-mode')) {
392
+ icon.classList.replace('fa-moon', 'fa-sun');
393
+ localStorage.setItem('theme', 'dark');
394
+ } else {
395
+ icon.classList.replace('fa-sun', 'fa-moon');
396
+ localStorage.setItem('theme', 'light');
397
+ }
398
+ });
399
+
400
+ // Check for saved theme preference
401
+ if (localStorage.getItem('theme') === 'dark') {
402
+ body.classList.add('dark-mode');
403
+ themeToggle.querySelector('i').classList.replace('fa-moon', 'fa-sun');
404
+ }
405
+
406
+ // Show more button
407
+ showMore.addEventListener('click', () => {
408
+ alert('سيتم عرض جميع البطاقات في صفحة منفصلة');
409
+ });
410
+
411
+ // Store data (mock - should be replaced with API calls)
412
+ const storesData = {
413
+ 'supermarkets': [
414
+ { id: 'market1', name: 'سوق الرياض', logo: 'fa-store', apiUrl: 'https://api.example.com/markets/1' },
415
+ { id: 'market2', name: 'هايبر بنده', logo: 'fa-shopping-basket', apiUrl: 'https://api.example.com/markets/2' }
416
+ ],
417
+ 'fashion': [
418
+ { id: 'fashion1', name: 'زد', logo: 'fa-tshirt', apiUrl: 'https://api.example.com/fashion/1' }
419
+ ],
420
+ 'furniture': [
421
+ { id: 'furniture1', name: 'إيكيا', logo: 'fa-couch', apiUrl: 'https://api.example.com/furniture/1' }
422
+ ],
423
+ 'electronics': [
424
+ { id: 'electronics1', name: 'إكسترا', logo: 'fa-laptop', apiUrl: 'https://api.example.com/electronics/1' }
425
+ ],
426
+ 'beauty': [
427
+ { id: 'beauty1', name: 'سيفورا', logo: 'fa-spa', apiUrl: 'https://api.example.com/beauty/1' }
428
+ ],
429
+ 'restaurants': [
430
+ { id: 'restaurant1', name: 'مطاعم هرفي', logo: 'fa-utensils', apiUrl: 'https://api.example.com/restaurants/1' }
431
+ ],
432
+ 'pharmacies': [
433
+ { id: 'pharmacy1', name: 'صيدليات النهدي', logo: 'fa-prescription-bottle-alt', apiUrl: 'https://api.example.com/pharmacies/1' }
434
+ ],
435
+ 'services': [
436
+ { id: 'service1', name: 'نجارون', logo: 'fa-tools', apiUrl: 'https://api.example.com/services/1' }
437
+ ],
438
+ 'delivery': [
439
+ { id: 'delivery1', name: 'هنقرستيشن', logo: 'fa-motorcycle', apiUrl: 'https://api.example.com/delivery/1' }
440
+ ]
441
+ };
442
+
443
+ // Current session state
444
+ const appState = {
445
+ currentCategory: null,
446
+ currentStore: null,
447
+ storeSessions: JSON.parse(localStorage.getItem('storeSessions')) || {}
448
+ };
449
+
450
+ // Auth State
451
+ const authState = {
452
+ isAuthenticated: false,
453
+ accessToken: null,
454
+ refreshToken: null,
455
+ userInfo: null,
456
+ tokenExpiry: null
457
+ };
458
+
459
+ // Sample favorite stores data
460
+ const favoriteStores = [
461
+ { id: 'fav1', name: 'سوق الرياض', icon: 'fa-store' },
462
+ { id: 'fav2', name: 'النهدي', icon: 'fa-prescription-bottle-alt' },
463
+ { id: 'fav3', name: 'إلكترونيات', icon: 'fa-laptop' }
464
+ ];
465
+
466
+ // Initialize favorite stores
467
+ function initFavorites() {
468
+ const container = document.getElementById('favoritesContainer');
469
+ favoriteStores.forEach(store => {
470
+ const element = document.createElement('div');
471
+ element.className = 'store-card bg-white dark:bg-gray-700 p-4 rounded-lg shadow-md flex-shrink-0';
472
+ element.innerHTML = `
473
+ <i class="fas ${store.icon} text-base text-blue-500 mb-2"></i>
474
+ <span class="text-sm font-medium">${store.name}</span>
475
+ `;
476
+ container.appendChild(element);
477
+ });
478
+ }
479
+
480
+ // Initialize the app
481
+ document.addEventListener('DOMContentLoaded', () => {
482
+ initCards();
483
+ initFavorites();
484
+ setupStoreView();
485
+ loadSavedSessions();
486
+ initAuth();
487
+
488
+ // Set first nav item as active
489
+ document.querySelector('nav a').classList.add('active');
490
+ });
491
+
492
+ // Auth Functions
493
+ function initAuth() {
494
+ // Check for existing auth in localStorage
495
+ const savedAuth = localStorage.getItem('unifiedAuth');
496
+ if (savedAuth) {
497
+ const authData = JSON.parse(savedAuth);
498
+ if (new Date(authData.tokenExpiry) > new Date()) {
499
+ authState.isAuthenticated = true;
500
+ authState.accessToken = authData.accessToken;
501
+ authState.refreshToken = authData.refreshToken;
502
+ authState.userInfo = authData.userInfo;
503
+ authState.tokenExpiry = new Date(authData.tokenExpiry);
504
+ updateAuthUI();
505
+ } else {
506
+ // Token expired, try refresh
507
+ refreshToken(authData.refreshToken);
508
+ }
509
+ }
510
+
511
+ // Setup auth button handlers
512
+ document.getElementById('authBtn').addEventListener('click', toggleAuthModal);
513
+ document.getElementById('closeLoginModal').addEventListener('click', () => {
514
+ document.getElementById('loginModal').classList.add('hidden');
515
+ });
516
+ document.getElementById('loginBtn').addEventListener('click', handleLogin);
517
+ document.getElementById('sendOtpBtn').addEventListener('click', sendOTP);
518
+ document.getElementById('verifyOtpBtn').addEventListener('click', verifyOTP);
519
+ document.getElementById('logoutBtn').addEventListener('click', handleLogout);
520
+ }
521
+
522
+ function toggleAuthModal() {
523
+ if (authState.isAuthenticated) {
524
+ document.getElementById('userDropdown').classList.toggle('hidden');
525
+ } else {
526
+ document.getElementById('loginModal').classList.remove('hidden');
527
+ }
528
+ }
529
+
530
+ async function handleLogin() {
531
+ const email = document.getElementById('emailInput').value;
532
+ const password = document.getElementById('passwordInput').value;
533
+
534
+ try {
535
+ // In real app, this would call your OAuth 2.0/OpenID Connect endpoint
536
+ const response = await mockLogin(email, password);
537
+
538
+ authState.isAuthenticated = true;
539
+ authState.accessToken = response.access_token;
540
+ authState.refreshToken = response.refresh_token;
541
+ authState.userInfo = response.user_info;
542
+ authState.tokenExpiry = new Date(new Date().getTime() + (response.expires_in * 1000));
543
+
544
+ localStorage.setItem('unifiedAuth', JSON.stringify(authState));
545
+ updateAuthUI();
546
+
547
+ document.getElementById('loginModal').classList.add('hidden');
548
+
549
+ // Check if 2FA is required
550
+ if (response.requires_2fa) {
551
+ document.getElementById('twoFAModal').classList.remove('hidden');
552
+ }
553
+
554
+ } catch (error) {
555
+ alert('فشل تسجيل الدخول: ' + error.message);
556
+ }
557
+ }
558
+
559
+ function mockLogin(email, password) {
560
+ return new Promise((resolve, reject) => {
561
+ // Simulate API call
562
+ setTimeout(() => {
563
+ if (email && password) {
564
+ resolve({
565
+ access_token: 'mock_access_token_' + Math.random().toString(36).substr(2, 9),
566
+ refresh_token: 'mock_refresh_token_' + Math.random().toString(36).substr(2, 9),
567
+ expires_in: 3600,
568
+ token_type: 'Bearer',
569
+ user_info: {
570
+ name: 'محمد أحمد',
571
+ email: email,
572
+ phone: '0501234567',
573
+ avatar: 'https://via.placeholder.com/150'
574
+ },
575
+ requires_2fa: false
576
+ });
577
+ } else {
578
+ reject(new Error('البريد الإلكتروني أو كلمة المرور غير صحيحة'));
579
+ }
580
+ }, 1000);
581
+ });
582
+ }
583
+
584
+ function updateAuthUI() {
585
+ if (authState.isAuthenticated) {
586
+ document.getElementById('authIcon').classList.replace('fa-sign-in-alt', 'fa-user-circle');
587
+ document.getElementById('authText').textContent = authState.userInfo.name.split(' ')[0];
588
+ document.getElementById('userName').textContent = authState.userInfo.name;
589
+ document.getElementById('userEmail').textContent = authState.userInfo.email;
590
+ document.getElementById('userAvatar').src = authState.userInfo.avatar;
591
+ } else {
592
+ document.getElementById('authIcon').classList.replace('fa-user-circle', 'fa-sign-in-alt');
593
+ document.getElementById('authText').textContent = 'تسجيل الدخول';
594
+ document.getElementById('userDropdown').classList.add('hidden');
595
+ }
596
+ }
597
+
598
+ function handleLogout() {
599
+ // Call logout endpoint
600
+ fetch('/auth/logout', {
601
+ method: 'POST',
602
+ headers: {
603
+ 'Authorization': `Bearer ${authState.accessToken}`
604
+ }
605
+ });
606
+
607
+ // Clear auth state
608
+ authState.isAuthenticated = false;
609
+ authState.accessToken = null;
610
+ authState.refreshToken = null;
611
+ authState.userInfo = null;
612
+ authState.tokenExpiry = null;
613
+
614
+ localStorage.removeItem('unifiedAuth');
615
+ updateAuthUI();
616
+ }
617
+
618
+ function refreshToken(refreshToken) {
619
+ // Implement token refresh logic
620
+ console.log('Refreshing token...');
621
+ }
622
+
623
+ function sendOTP() {
624
+ const mobile = document.getElementById('mobileInput').value;
625
+ if (!mobile) {
626
+ alert('من فضلك أدخل رقم الجوال');
627
+ return;
628
+ }
629
+
630
+ // Simulate sending OTP
631
+ document.getElementById('otpMobileNumber').textContent = '+966' + mobile;
632
+ document.getElementById('loginBtn').classList.add('hidden');
633
+ document.getElementById('otpSection').classList.remove('hidden');
634
+ document.getElementById('sendOtpBtn').style.display = 'none';
635
+ }
636
+
637
+ function verifyOTP() {
638
+ // Verify OTP logic would go here
639
+ alert('تم التحقق بنجاح');
640
+ document.getElementById('loginModal').classList.add('hidden');
641
+ }
642
+
643
+ // Handle category navigation
644
+ function setupCategoryNavigation() {
645
+ // Set up category links in dropdown
646
+ document.querySelectorAll('#categoriesDropdown a').forEach(link => {
647
+ link.addEventListener('click', (e) => {
648
+ e.preventDefault();
649
+ const categoryName = link.textContent.trim();
650
+ // Map readable category names to data keys
651
+ const categoryMap = {
652
+ 'السوبر ماركت والأسواق العامة': 'supermarkets',
653
+ 'الملابس والأزياء': 'fashion',
654
+ 'الأثاث والمفروشات': 'furniture',
655
+ 'الإلكترونيات والتقنية': 'electronics',
656
+ 'العناية الشخصية والجمال': 'beauty',
657
+ 'المطاعم والمقاهي': 'restaurants',
658
+ 'الصيدليات والرعاية الصحية': 'pharmacies',
659
+ 'الخدمات المنزلية والصيانة': 'services',
660
+ 'شركات التوصيل': 'delivery'
661
+ };
662
+ const category = categoryMap[categoryName];
663
+ if (category) {
664
+ appState.currentCategory = category;
665
+ showStoresForCategory(category);
666
+ sidebar.classList.add('translate-x-full');
667
+ }
668
+ });
669
+ });
670
+
671
+ document.getElementById('backToCategories').addEventListener('click', () => {
672
+ document.getElementById('storesSection').classList.add('hidden');
673
+ document.querySelector('#categoriesContainer').classList.remove('hidden');
674
+ });
675
+ }
676
+
677
+ // Show stores for selected category
678
+ function showStoresForCategory(category) {
679
+ document.querySelector('#categoriesContainer').classList.add('hidden');
680
+ const storesSection = document.getElementById('storesSection');
681
+ storesSection.classList.remove('hidden');
682
+ document.getElementById('storeSectionTitle').textContent = `متاجر ${category}`;
683
+
684
+ const storesGrid = document.getElementById('storesGrid');
685
+ storesGrid.innerHTML = '';
686
+
687
+ // Load stores from API - using mock data here
688
+ const stores = storesData[category] || [];
689
+
690
+ stores.forEach(store => {
691
+ const storeElement = document.createElement('div');
692
+ storeElement.className = 'store-card bg-white dark:bg-gray-700 p-4 rounded-lg shadow-md text-center cursor-pointer hover:shadow-lg transition';
693
+ storeElement.dataset.storeId = store.id;
694
+ storeElement.innerHTML = `
695
+ <i class="fas ${store.logo} text-2xl text-blue-500 mb-2"></i>
696
+ <h3 class="font-bold">${store.name}</h3>
697
+ ${appState.storeSessions[store.id] ?
698
+ '<span class="text-xs text-green-500 block mt-1">لديك جلسة سابقة</span>' : ''}
699
+ `;
700
+
701
+ storeElement.addEventListener('click', () => {
702
+ openStore(store);
703
+ });
704
+
705
+ storesGrid.appendChild(storeElement);
706
+ });
707
+ }
708
+
709
+ // Open store in WebView
710
+ function openStore(store) {
711
+ appState.currentStore = store.id;
712
+ const storeView = document.getElementById('storeViewContainer');
713
+ storeView.classList.remove('hidden');
714
+ document.getElementById('storeNameHeader').textContent = store.name;
715
+
716
+ // Load store content - in a real app this would be a WebView or API call
717
+ const storeContent = document.getElementById('storeWebView');
718
+ storeContent.innerHTML = `
719
+ <iframe src="${store.apiUrl}" class="w-full h-full"
720
+ frameborder="0" allowfullscreen></iframe>
721
+ `;
722
+
723
+ // Restore session if available
724
+ if (appState.storeSessions[store.id]) {
725
+ // In a real app, would restore scroll position and state
726
+ console.log(`Restoring session for ${store.name}`);
727
+ }
728
+ }
729
+
730
+ // Setup store view controls
731
+ function setupStoreView() {
732
+ document.getElementById('closeStoreView').addEventListener('click', () => {
733
+ // Save current session before closing
734
+ if (appState.currentStore) {
735
+ appState.storeSessions[appState.currentStore] = {
736
+ lastVisited: new Date().toISOString(),
737
+ // In a real app, would save scroll position and other state
738
+ url: window.location.href
739
+ };
740
+ localStorage.setItem('storeSessions', JSON.stringify(appState.storeSessions));
741
+ }
742
+
743
+ document.getElementById('storeViewContainer').classList.add('hidden');
744
+ });
745
+ }
746
+
747
+ // Load saved sessions
748
+ function loadSavedSessions() {
749
+ if (Object.keys(appState.storeSessions).length > 0) {
750
+ // Could show a quick access section for stores with saved sessions
751
+ console.log('Loaded saved store sessions:', appState.storeSessions);
752
+ }
753
+ }
754
+
755
+ // Search functionality
756
+ document.getElementById('storeSearch').addEventListener('input', (e) => {
757
+ const searchTerm = e.target.value.toLowerCase();
758
+ const storeCards = document.querySelectorAll('.store-card');
759
+
760
+ storeCards.forEach(card => {
761
+ const storeName = card.querySelector('h3').textContent.toLowerCase();
762
+ card.style.display = storeName.includes(searchTerm) ? 'block' : 'none';
763
+ });
764
+ });
765
+
766
+ // Handle swipe gestures for mobile
767
+ let touchStartX = 0;
768
+ let touchEndX = 0;
769
+
770
+ document.addEventListener('touchstart', e => {
771
+ touchStartX = e.changedTouches[0].screenX;
772
+ }, false);
773
+
774
+ document.addEventListener('touchend', e => {
775
+ touchEndX = e.changedTouches[0].screenX;
776
+ handleSwipe();
777
+ }, false);
778
+
779
+ function handleSwipe() {
780
+ if (touchStartX - touchEndX > 50) {
781
+ // Swipe left - open sidebar
782
+ sidebar.classList.remove('translate-x-full');
783
+ sidebar.classList.add('slide-in');
784
+ }
785
+ if (touchEndX - touchStartX > 50 && !sidebar.classList.contains('translate-x-full')) {
786
+ // Swipe right - close sidebar
787
+ sidebar.classList.add('translate-x-full');
788
+ sidebar.classList.add('slide-out');
789
+ }
790
+ }
791
+ </script>
792
+
793
+ <!-- Bottom Navigation Bar -->
794
+ <nav class="fixed bottom-0 left-0 right-0 bg-white dark:bg-gray-800 border-t border-gray-200 dark:border-gray-700 flex justify-around items-center py-3 z-40">
795
+ <a href="#" class="flex flex-col items-center text-blue-600 dark:text-blue-400">
796
+ <i class="fas fa-home text-xl mb-1"></i>
797
+ <span class="text-xs">الرئيسية</span>
798
+ </a>
799
+ <a href="#" class="flex flex-col items-center text-gray-600 dark:text-gray-400">
800
+ <i class="fas fa-search text-xl mb-1"></i>
801
+ <span class="text-xs">البحث</span>
802
+ </a>
803
+ <a href="#" class="flex flex-col items-center text-gray-600 dark:text-gray-400">
804
+ <i class="fas fa-shopping-bag text-xl mb-1"></i>
805
+ <span class="text-xs">طلباتي</span>
806
+ </a>
807
+ <a href="#" class="flex flex-col items-center text-gray-600 dark:text-gray-400">
808
+ <i class="fas fa-user text-xl mb-1"></i>
809
+ <span class="text-xs">ملفي</span>
810
+ </a>
811
+ <a href="#" id="liveSupportBtn" class="flex flex-col items-center text-gray-600 dark:text-gray-400">
812
+ <i class="fas fa-headset text-xl mb-1"></i>
813
+ <span class="text-xs">المساعدة</span>
814
+ </a>
815
+ </nav>
816
+ <p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=mohammed2449/m" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
817
+ </html>