Mhdeusi commited on
Commit
5346687
·
verified ·
1 Parent(s): 871f652

Create app.js

Browse files
Files changed (1) hide show
  1. js/app.js +605 -0
js/app.js ADDED
@@ -0,0 +1,605 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ class LearningPlatform {
2
+ constructor() {
3
+ this.currentDay = 1;
4
+ this.maxDays = 3;
5
+ this.isInitialized = false;
6
+ this.components = {};
7
+ }
8
+
9
+ async initialize() {
10
+ try {
11
+ console.log('🚀 Initializing Learning Platform...');
12
+
13
+ // مقداردهی اولیه سیستم احراز هویت
14
+ this.initializeAuth();
15
+
16
+ // دیباگ اطلاعات احراز هویت
17
+ this.debugAuth();
18
+
19
+ // بارگذاری کامپوننت‌ها
20
+ this.loadComponents();
21
+
22
+ // راه‌اندازی event listeners
23
+ this.setupEventListeners();
24
+
25
+ // بارگذاری محتوای اولیه
26
+ await this.loadInitialContent();
27
+
28
+ // به‌روزرسانی UI
29
+ this.updateUI();
30
+
31
+ this.isInitialized = true;
32
+ console.log('✅ Platform initialized successfully');
33
+
34
+ } catch (error) {
35
+ console.error('❌ Failed to initialize platform:', error);
36
+ this.showError('خطا در بارگذاری برنامه. لطفاً صفحه را رفرش کنید.');
37
+ }
38
+ }
39
+
40
+ initializeAuth() {
41
+ console.log('🔐 Initializing authentication system...');
42
+
43
+ // مقداردهی اولیه کاربران پیش‌فرض
44
+ if (typeof authManager !== 'undefined') {
45
+ authManager.initializeDefaultUsers();
46
+ console.log('👥 Default users initialized');
47
+ } else {
48
+ console.error('❌ authManager is not defined');
49
+ }
50
+
51
+ // مقداردهی اولیه میان‌افزار
52
+ if (typeof AuthMiddleware !== 'undefined') {
53
+ AuthMiddleware.initializeApp();
54
+ }
55
+
56
+ // اعمال تم ذخیره شده
57
+ const savedTheme = localStorage.getItem('theme');
58
+ if (savedTheme) {
59
+ document.body.setAttribute('data-theme', savedTheme);
60
+ }
61
+ }
62
+
63
+ debugAuth() {
64
+ console.log('🔍 Auth Debug Info:');
65
+ console.log('- Token:', authManager?.getToken());
66
+ console.log('- Current User:', authManager?.getCurrentUser());
67
+ console.log('- All Users:', authManager?.getUsers());
68
+ console.log('- Is Authenticated:', authManager?.isAuthenticated());
69
+ }
70
+
71
+ loadComponents() {
72
+ console.log('🔧 Loading components...');
73
+
74
+ // بارگذاری کامپوننت‌های اصلی
75
+ this.components = {
76
+ header: typeof HeaderComponent !== 'undefined' ? new HeaderComponent() : null,
77
+ modal: typeof ModalComponent !== 'undefined' ? new ModalComponent() : null,
78
+ navigation: typeof NavigationComponent !== 'undefined' ? new NavigationComponent() : null,
79
+ lessonUI: typeof LessonUI !== 'undefined' ? new LessonUI() : null,
80
+ quizUI: typeof QuizUI !== 'undefined' ? new QuizUI() : null,
81
+ exerciseUI: typeof ExerciseUI !== 'undefined' ? new ExerciseUI() : null
82
+ };
83
+
84
+ console.log('✅ Components loaded:', Object.keys(this.components));
85
+
86
+ // رندر کامپوننت‌ها
87
+ if (this.components.header) {
88
+ this.components.header.render();
89
+ }
90
+
91
+ if (this.components.navigation) {
92
+ this.components.navigation.render();
93
+ }
94
+ }
95
+
96
+ setupEventListeners() {
97
+ console.log('🎯 Setting up event listeners...');
98
+
99
+ // مدیریت تغییر روز
100
+ document.addEventListener('dayChanged', (event) => {
101
+ this.handleDayChange(event.detail.day);
102
+ });
103
+
104
+ // مدیریت وضعیت احراز هویت
105
+ document.addEventListener('authStateChanged', () => {
106
+ this.handleAuthStateChange();
107
+ });
108
+
109
+ // مدیریت تکمیل درس
110
+ document.addEventListener('lessonCompleted', (event) => {
111
+ this.handleLessonCompleted(event.detail);
112
+ });
113
+
114
+ // مدیریت ارسال تمرین
115
+ document.addEventListener('exerciseSubmitted', (event) => {
116
+ this.handleExerciseSubmitted(event.detail);
117
+ });
118
+
119
+ // مدیریت به‌روزرسانی پیشرفت
120
+ document.addEventListener('progressUpdated', () => {
121
+ this.handleProgressUpdate();
122
+ });
123
+
124
+ // مدیریت کلیک روی دکمه‌های ناوبری
125
+ document.addEventListener('click', (e) => {
126
+ if (e.target.matches('[data-day]')) {
127
+ const day = parseInt(e.target.getAttribute('data-day'));
128
+ this.handleDayChange(day);
129
+ }
130
+
131
+ if (e.target.matches('.next-day')) {
132
+ this.nextDay();
133
+ }
134
+
135
+ if (e.target.matches('.prev-day')) {
136
+ this.previousDay();
137
+ }
138
+ });
139
+
140
+ // جلوگیری از ارسال فرم‌ها
141
+ document.addEventListener('submit', (e) => {
142
+ if (e.target.tagName === 'FORM') {
143
+ e.preventDefault();
144
+ }
145
+ });
146
+
147
+ // مدیریت خطاهای全局
148
+ window.addEventListener('error', (event) => {
149
+ console.error('Global error:', event.error);
150
+ });
151
+
152
+ window.addEventListener('unhandledrejection', (event) => {
153
+ console.error('Unhandled promise rejection:', event.reason);
154
+ });
155
+ }
156
+
157
+ async loadInitialContent() {
158
+ console.log('📚 Loading initial content...');
159
+
160
+ // نمایش وضعیت loading
161
+ this.showLoadingState();
162
+
163
+ try {
164
+ // بارگذاری محتوا
165
+ await this.loadLesson();
166
+ await this.loadQuiz();
167
+ await this.loadExercise();
168
+ } catch (error) {
169
+ console.error('Error loading content:', error);
170
+ } finally {
171
+ // پنهان کردن وضعیت loading
172
+ this.hideLoadingState();
173
+ }
174
+ }
175
+
176
+ async loadLesson() {
177
+ try {
178
+ console.log(`📖 Loading lesson for day ${this.currentDay}...`);
179
+
180
+ // شبیه‌سازی بارگذاری داده
181
+ const lessonData = await this.simulateLessonLoad();
182
+
183
+ const lessonContent = document.getElementById('lessonContent');
184
+ if (lessonContent) {
185
+ lessonContent.innerHTML = this.renderLesson(lessonData);
186
+ }
187
+
188
+ } catch (error) {
189
+ console.error('Error loading lesson:', error);
190
+ this.showContentError('lessonContent', 'خطا در بارگذاری درس');
191
+ }
192
+ }
193
+
194
+ async loadQuiz() {
195
+ try {
196
+ console.log(`❓ Loading quiz for day ${this.currentDay}...`);
197
+
198
+ // شبیه‌سازی بارگذاری داده
199
+ const quizData = await this.simulateQuizLoad();
200
+
201
+ const quizForm = document.getElementById('quizForm');
202
+ if (quizForm) {
203
+ quizForm.innerHTML = this.renderQuiz(quizData);
204
+ }
205
+
206
+ } catch (error) {
207
+ console.error('Error loading quiz:', error);
208
+ this.showContentError('quizForm', 'خطا در بارگذاری آزمون');
209
+ }
210
+ }
211
+
212
+ async loadExercise() {
213
+ try {
214
+ console.log(`✏️ Loading exercise for day ${this.currentDay}...`);
215
+
216
+ // شبیه‌سازی بارگذاری داده
217
+ const exerciseData = await this.simulateExerciseLoad();
218
+
219
+ const exerciseContent = document.getElementById('exerciseContent');
220
+ if (exerciseContent) {
221
+ exerciseContent.innerHTML = this.renderExercise(exerciseData);
222
+ }
223
+
224
+ } catch (error) {
225
+ console.error('Error loading exercise:', error);
226
+ this.showContentError('exerciseContent', 'خطا در بارگذاری تمرین');
227
+ }
228
+ }
229
+
230
+ // شبیه‌سازهای بارگذاری داده
231
+ simulateLessonLoad() {
232
+ return new Promise((resolve) => {
233
+ setTimeout(() => {
234
+ resolve({
235
+ title: `درس روز ${this.currentDay}: مقدمات توسعه وب`,
236
+ content: `این محتوای آموزشی برای روز ${this.currentDay} است. در این درس با مفاهیم پایه توسعه وب آشنا می‌شوید.`,
237
+ points: 10
238
+ });
239
+ }, 500);
240
+ });
241
+ }
242
+
243
+ simulateQuizLoad() {
244
+ return new Promise((resolve) => {
245
+ setTimeout(() => {
246
+ resolve({
247
+ question: `سوال روز ${this.currentDay}: HTML چیست؟`,
248
+ options: [
249
+ 'زبان برنامه‌نویسی',
250
+ 'زبان نشانه‌گذاری',
251
+ 'پایگاه داده',
252
+ 'فریمورک CSS'
253
+ ],
254
+ correctAnswer: 1
255
+ });
256
+ }, 500);
257
+ });
258
+ }
259
+
260
+ simulateExerciseLoad() {
261
+ return new Promise((resolve) => {
262
+ setTimeout(() => {
263
+ resolve({
264
+ title: `تمرین روز ${this.currentDay}`,
265
+ description: 'یک صفحه HTML ساده ایجاد کنید.',
266
+ keywords: ['html', 'body', 'title'],
267
+ points: 15
268
+ });
269
+ }, 500);
270
+ });
271
+ }
272
+
273
+ // رندررهای ساده
274
+ renderLesson(data) {
275
+ return `
276
+ <div class="lesson-container">
277
+ <h2>${data.title}</h2>
278
+ <div class="lesson-content">
279
+ <p>${data.content}</p>
280
+ </div>
281
+ <div class="lesson-meta">
282
+ <span class="points">🏆 ${data.points} امتیاز</span>
283
+ </div>
284
+ <button class="btn btn-primary complete-lesson" onclick="app.completeLesson(${this.currentDay})">
285
+ تکمیل درس
286
+ </button>
287
+ </div>
288
+ `;
289
+ }
290
+
291
+ renderQuiz(data) {
292
+ return `
293
+ <div class="quiz-container">
294
+ <h3>آزمون کوتاه</h3>
295
+ <p>${data.question}</p>
296
+ <form id="quizFormElement">
297
+ ${data.options.map((option, index) => `
298
+ <div class="quiz-option">
299
+ <input type="radio" id="option${index}" name="quiz" value="${index}">
300
+ <label for="option${index}">${option}</label>
301
+ </div>
302
+ `).join('')}
303
+ <button type="submit" class="btn btn-primary">ارسال پاسخ</button>
304
+ </form>
305
+ </div>
306
+ `;
307
+ }
308
+
309
+ renderExercise(data) {
310
+ return `
311
+ <div class="exercise-container">
312
+ <h3>${data.title}</h3>
313
+ <p>${data.description}</p>
314
+ <form id="exerciseFormElement">
315
+ <div class="form-group">
316
+ <label for="exerciseAnswer">پاسخ خود را وارد کنید:</label>
317
+ <textarea id="exerciseAnswer" rows="4" placeholder="کد یا پاسخ خود را اینجا بنویسید..."></textarea>
318
+ </div>
319
+ <button type="submit" class="btn btn-primary">ارسال تمرین</button>
320
+ </form>
321
+ <div class="exercise-info">
322
+ <small>کلیدواژه‌های مهم: ${data.keywords.join(', ')}</small>
323
+ <br>
324
+ <small>🏅 ${data.points} امتیاز</small>
325
+ </div>
326
+ </div>
327
+ `;
328
+ }
329
+
330
+ async handleDayChange(newDay) {
331
+ if (newDay < 1 || newDay > this.maxDays) {
332
+ console.warn('Invalid day number:', newDay);
333
+ return;
334
+ }
335
+
336
+ console.log(`📅 Changing to day ${newDay}`);
337
+ this.currentDay = newDay;
338
+
339
+ // نمایش وضعیت loading
340
+ this.showLoadingState();
341
+
342
+ try {
343
+ // بارگذاری محتوای جدید
344
+ await this.loadLesson();
345
+ await this.loadQuiz();
346
+ await this.loadExercise();
347
+
348
+ // به‌روزرسانی navigation
349
+ this.updateNavigation();
350
+
351
+ // اسکرول به بالای صفحه
352
+ window.scrollTo({ top: 0, behavior: 'smooth' });
353
+
354
+ } catch (error) {
355
+ console.error('Error changing day:', error);
356
+ } finally {
357
+ // پنهان کردن وضعیت loading
358
+ this.hideLoadingState();
359
+ }
360
+ }
361
+
362
+ handleAuthStateChange() {
363
+ console.log('🔄 Auth state changed');
364
+ this.updateAuthDisplay();
365
+ this.updateProgressDisplay();
366
+ }
367
+
368
+ handleLessonCompleted(detail) {
369
+ console.log('📚 Lesson completed:', detail);
370
+
371
+ // به‌روزرسانی امتیاز کاربر
372
+ if (authManager.isAuthenticated()) {
373
+ const user = authManager.getCurrentUser();
374
+ userManager.updateUserProgress(detail.points || 10, this.currentDay);
375
+ }
376
+
377
+ this.updateProgressDisplay();
378
+ this.showMessage('🎉 درس تکمیل شد! امتیاز شما به روز شد.', 'success');
379
+ }
380
+
381
+ handleExerciseSubmitted(detail) {
382
+ console.log('✏️ Exercise submitted:', detail);
383
+ this.updateProgressDisplay();
384
+ this.showMessage('✅ تمرین ارسال شد!', 'success');
385
+ }
386
+
387
+ handleProgressUpdate() {
388
+ this.updateProgressDisplay();
389
+ }
390
+
391
+ updateUI() {
392
+ this.updateAuthDisplay();
393
+ this.updateProgressDisplay();
394
+ this.updateNavigation();
395
+ }
396
+
397
+ updateAuthDisplay() {
398
+ const authSection = document.getElementById('authSection');
399
+ if (!authSection) return;
400
+
401
+ const user = authManager.getCurrentUser();
402
+
403
+ if (user) {
404
+ authSection.innerHTML = `
405
+ <div class="user-welcome">
406
+ <div class="user-info">
407
+ <span class="welcome-text">خوش آمدید, ${user.profile.fullName || user.username}!</span>
408
+ <span class="user-role">${this.getRoleText(user.role)}</span>
409
+ </div>
410
+ <button onclick="app.logout()" class="btn btn-outline">خروج</button>
411
+ </div>
412
+ `;
413
+ } else {
414
+ authSection.innerHTML = `
415
+ <div class="auth-actions">
416
+ <p>برای ذخیره پیشرفت وارد شوید</p>
417
+ <div class="auth-buttons">
418
+ <button onclick="app.showLogin()" class="btn btn-primary">ورود</button>
419
+ <button onclick="app.showRegister()" class="btn btn-secondary">ثبت نام</button>
420
+ </div>
421
+ </div>
422
+ `;
423
+ }
424
+ }
425
+
426
+ updateProgressDisplay() {
427
+ const progressContent = document.getElementById('progressContent');
428
+ if (!progressContent) return;
429
+
430
+ const user = authManager.getCurrentUser();
431
+
432
+ if (user) {
433
+ const progress = user.progress || { totalScore: 0, completedLessons: [] };
434
+ const completedCount = progress.completedLessons?.length || 0;
435
+
436
+ progressContent.innerHTML = `
437
+ <div class="progress-stats">
438
+ <div class="stat-card">
439
+ <div class="stat-value">${Math.floor(completedCount / 3 * 100)}%</div>
440
+ <div class="stat-label">پیشرفت کل</div>
441
+ </div>
442
+ <div class="stat-card">
443
+ <div class="stat-value">${progress.totalScore || 0}</div>
444
+ <div class="stat-label">امتیاز کل</div>
445
+ </div>
446
+ <div class="stat-card">
447
+ <div class="stat-value">${completedCount}</div>
448
+ <div class="stat-label">درس تکمیل شده</div>
449
+ </div>
450
+ </div>
451
+ `;
452
+ } else {
453
+ progressContent.innerHTML = `
454
+ <div class="guest-progress">
455
+ <p>👋 برای مشاهده پیشرفت خود وارد شوید</p>
456
+ </div>
457
+ `;
458
+ }
459
+ }
460
+
461
+ updateNavigation() {
462
+ const navigation = document.getElementById('dayNavigation');
463
+ if (navigation) {
464
+ navigation.innerHTML = this.createDayNavigation();
465
+ }
466
+ }
467
+
468
+ createDayNavigation() {
469
+ let navigationHTML = '<div class="day-navigation">';
470
+
471
+ for (let day = 1; day <= this.maxDays; day++) {
472
+ const isActive = day === this.currentDay;
473
+ navigationHTML += `
474
+ <button class="day-btn ${isActive ? 'active' : ''}" data-day="${day}">
475
+ روز ${day}
476
+ </button>
477
+ `;
478
+ }
479
+
480
+ navigationHTML += '</div>';
481
+ return navigationHTML;
482
+ }
483
+
484
+ getRoleText(role) {
485
+ const roles = {
486
+ 'student': 'دانشجو',
487
+ 'instructor': 'مربی',
488
+ 'admin': 'مدیر'
489
+ };
490
+ return roles[role] || role;
491
+ }
492
+
493
+ showLoadingState() {
494
+ const sections = ['lessonContent', 'quizForm', 'exerciseContent'];
495
+ sections.forEach(sectionId => {
496
+ const element = document.getElementById(sectionId);
497
+ if (element) {
498
+ element.style.opacity = '0.6';
499
+ element.style.pointerEvents = 'none';
500
+ }
501
+ });
502
+ }
503
+
504
+ hideLoadingState() {
505
+ const sections = ['lessonContent', 'quizForm', 'exerciseContent'];
506
+ sections.forEach(sectionId => {
507
+ const element = document.getElementById(sectionId);
508
+ if (element) {
509
+ element.style.opacity = '1';
510
+ element.style.pointerEvents = 'auto';
511
+ }
512
+ });
513
+ }
514
+
515
+ showContentError(elementId, message) {
516
+ const element = document.getElementById(elementId);
517
+ if (element) {
518
+ element.innerHTML = `
519
+ <div class="error-state">
520
+ <div class="error-message">${message}</div>
521
+ <button onclick="app.retryLoading()" class="btn btn-outline">
522
+ تلاش مجدد
523
+ </button>
524
+ </div>
525
+ `;
526
+ }
527
+ }
528
+
529
+ showMessage(message, type = 'info') {
530
+ // ایجاد یک نوتیفیکیشن ساده
531
+ const notification = document.createElement('div');
532
+ notification.className = `notification ${type}`;
533
+ notification.innerHTML = `
534
+ <div class="notification-content">
535
+ <span>${message}</span>
536
+ <button onclick="this.parentElement.parentElement.remove()">×</button>
537
+ </div>
538
+ `;
539
+
540
+ document.body.appendChild(notification);
541
+
542
+ // حذف خودکار بعد از 5 ثانیه
543
+ setTimeout(() => {
544
+ if (notification.parentElement) {
545
+ notification.remove();
546
+ }
547
+ }, 5000);
548
+ }
549
+
550
+ // متدهای عمومی
551
+ showLogin() {
552
+ window.location.href = 'login.html';
553
+ }
554
+
555
+ showRegister() {
556
+ window.location.href = 'register.html';
557
+ }
558
+
559
+ logout() {
560
+ authManager.logout();
561
+ this.handleAuthStateChange();
562
+ this.showMessage('با موفقیت از سیستم خارج شدید.', 'info');
563
+ }
564
+
565
+ nextDay() {
566
+ if (this.currentDay < this.maxDays) {
567
+ this.handleDayChange(this.currentDay + 1);
568
+ }
569
+ }
570
+
571
+ previousDay() {
572
+ if (this.currentDay > 1) {
573
+ this.handleDayChange(this.currentDay - 1);
574
+ }
575
+ }
576
+
577
+ completeLesson(day) {
578
+ document.dispatchEvent(new CustomEvent('lessonCompleted', {
579
+ detail: { day: day, points: 10 }
580
+ }));
581
+ }
582
+
583
+ async retryLoading() {
584
+ await this.loadInitialContent();
585
+ }
586
+
587
+ showError(message) {
588
+ this.showMessage(message, 'error');
589
+ }
590
+
591
+ showSuccess(message) {
592
+ this.showMessage(message, 'success');
593
+ }
594
+ }
595
+
596
+ // ایجاد نمونه اصلی برنامه
597
+ const app = new LearningPlatform();
598
+
599
+ // قرار دادن در scope全局 برای دسترسی از HTML
600
+ window.app = app;
601
+
602
+ // راه‌اندازی برنامه هنگام بارگذاری صفحه
603
+ document.addEventListener('DOMContentLoaded', () => {
604
+ app.initialize();
605
+ });