Advertisement
herizo

Untitled

Nov 4th, 2024
181
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. import { Component, OnInit, OnDestroy } from '@angular/core';
  2. import { SchoolService } from '../../school/services/school.service';
  3. import { TeacherService } from '../../school/services/teacher.service';
  4. import { LoadingController, ToastController } from '@ionic/angular';
  5. import { ClassroomService } from '../../school/services/classroom.service';
  6. import { StudentService } from '../../school/services/student.service';
  7. import { AttendanceService } from '../../attendance/services/attendance.service';
  8. import { Router } from '@angular/router';
  9.  
  10. @Component({
  11.   selector: 'app-syncdata',
  12.   templateUrl: './syncdata.component.html',
  13.   styleUrls: ['./syncdata.component.scss'],
  14. })
  15. export class SyncDataComponent implements OnInit, OnDestroy {
  16.   private readonly DB_NAME = 'attendance';
  17.   private readonly DB_VERSION = 1;
  18.   private db: IDBDatabase | undefined;
  19.  
  20.   constructor(
  21.     private schoolService: SchoolService,
  22.     private teacherService: TeacherService,
  23.     private classroomService: ClassroomService,
  24.     private studentService: StudentService,
  25.     private attendanceService: AttendanceService,
  26.     private loadingController: LoadingController,
  27.     private toastController: ToastController,
  28.     private router: Router
  29.   ) { }
  30.  
  31.   ngOnInit() { }
  32.  
  33.   ngOnDestroy() {
  34.     if (this.db) {
  35.       this.db.close();
  36.       this.db = undefined;
  37.     }
  38.   }
  39.  
  40.   private async closeAllConnections(): Promise<void> {
  41.     return new Promise<void>((resolve) => {
  42.       if (this.db) {
  43.         try {
  44.           // Remove all event listeners
  45.           this.db.onerror = null;
  46.           this.db.onclose = null;
  47.           this.db.onversionchange = null;
  48.  
  49.           // Close the connection
  50.           this.db.close();
  51.  
  52.           // Add a delay before setting db to undefined
  53.           setTimeout(() => {
  54.             this.db = undefined;
  55.             resolve();
  56.           }, 500);
  57.         } catch (error) {
  58.           console.warn('Error while closing database:', error);
  59.           this.db = undefined;
  60.           resolve();
  61.         }
  62.       } else {
  63.         resolve();
  64.       }
  65.     });
  66.   }
  67.  
  68.   private async clearAllStores(): Promise<void> {
  69.     return new Promise(async (resolve, reject) => {
  70.       try {
  71.         if (!this.db) {
  72.           throw new Error('Database not initialized');
  73.         }
  74.  
  75.         const stores = [
  76.           'school',
  77.           'teacher',
  78.           'classroom',
  79.           'student',
  80.           'attendance',
  81.           'attendanceHistory'
  82.         ];
  83.  
  84.         const transaction = this.db.transaction(stores, 'readwrite');
  85.        
  86.         stores.forEach(storeName => {
  87.           const store = transaction.objectStore(storeName);
  88.           const clearRequest = store.clear();
  89.          
  90.           clearRequest.onerror = () => {
  91.             console.error(`Error clearing ${storeName} store:`, clearRequest.error);
  92.             reject(clearRequest.error);
  93.           };
  94.         });
  95.  
  96.         transaction.oncomplete = () => {
  97.           console.log('All stores cleared successfully');
  98.           resolve();
  99.         };
  100.  
  101.         transaction.onerror = () => {
  102.           console.error('Error clearing stores:', transaction.error);
  103.           reject(transaction.error);
  104.         };
  105.  
  106.       } catch (error) {
  107.         console.error('Error in clearAllStores:', error);
  108.         reject(error);
  109.       }
  110.     });
  111.   }
  112.  
  113.   private initDatabase(): Promise<void> {
  114.     return new Promise((resolve, reject) => {
  115.       try {
  116.         if (this.db) {
  117.           this.db.close();
  118.           this.db = undefined;
  119.         }
  120.  
  121.         const request = indexedDB.open(this.DB_NAME, this.DB_VERSION);
  122.  
  123.         request.onerror = () => {
  124.           console.error('Error opening database:', request.error);
  125.           reject(request.error);
  126.         };
  127.  
  128.         request.onupgradeneeded = (event) => {
  129.           const db = (event.target as IDBOpenDBRequest).result;
  130.  
  131.           if (!db.objectStoreNames.contains('school')) {
  132.             db.createObjectStore('school', { keyPath: 'id' });
  133.           }
  134.           if (!db.objectStoreNames.contains('teacher')) {
  135.             db.createObjectStore('teacher', { keyPath: 'id' });
  136.           }
  137.           if (!db.objectStoreNames.contains('classroom')) {
  138.             db.createObjectStore('classroom', { keyPath: 'id' });
  139.           }
  140.           if (!db.objectStoreNames.contains('student')) {
  141.             const studentStore = db.createObjectStore('student', { keyPath: 'id' });
  142.             studentStore.createIndex('classroomId', 'classroomId', { unique: false });
  143.           }
  144.           if (!db.objectStoreNames.contains('attendance')) {
  145.             db.createObjectStore('attendance', { keyPath: 'id' });
  146.           }
  147.           if (!db.objectStoreNames.contains('attendanceHistory')) {
  148.             db.createObjectStore('attendanceHistory', { keyPath: 'id' });
  149.           }
  150.         };
  151.  
  152.         request.onsuccess = () => {
  153.           this.db = request.result;
  154.  
  155.           this.db.onerror = (event) => {
  156.             console.error('Database error:', event);
  157.           };
  158.  
  159.           this.db.onclose = () => {
  160.             console.log('Database connection closed');
  161.           };
  162.  
  163.           console.log('Database opened successfully');
  164.           resolve();
  165.         };
  166.       } catch (error) {
  167.         console.error('Error in initDatabase:', error);
  168.         reject(error);
  169.       }
  170.     });
  171.   }
  172.  
  173.   async onDownload() {
  174.     const loading = await this.loadingController.create({
  175.       message: 'Téléchargement en cours...',
  176.       spinner: 'circles'
  177.     });
  178.  
  179.     try {
  180.       await loading.present();
  181.  
  182.       // Close any existing connections first
  183.       await this.closeAllConnections();
  184.  
  185.       // Validate user data
  186.       const userData = JSON.parse(localStorage.getItem('user') || '{}');
  187.       if (!userData.id) {
  188.         throw new Error('User ID not found');
  189.       }
  190.  
  191.       // Initialize the database if not already initialized
  192.       if (!this.db) {
  193.         try {
  194.           await this.initDatabase();
  195.           console.log('Database initialized');
  196.         } catch (error) {
  197.           console.error('Failed to initialize database:', error);
  198.           throw new Error('Database initialization failed');
  199.         }
  200.       }
  201.  
  202.       // Clear all stores
  203.       try {
  204.         await this.clearAllStores();
  205.         console.log('All stores cleared');
  206.       } catch (error) {
  207.         console.warn('Store clearing failed, proceeding anyway:', error);
  208.       }
  209.  
  210.       // Fetch and store teacher data
  211.       try {
  212.         const teacherData = await this.teacherService.getTeacherById(userData.id).toPromise();
  213.         if (!teacherData) {
  214.           throw new Error('No teacher data received');
  215.         }
  216.         await this.storeTeacherData(teacherData);
  217.         console.log('Teacher data stored');
  218.  
  219.         // Validate school ID
  220.         const schoolId = teacherData.school?.id;
  221.         if (!schoolId) {
  222.           throw new Error('School ID not found in teacher data');
  223.         }
  224.  
  225.         // Fetch and store school data
  226.         const schoolData = await this.schoolService.getSchoolById(schoolId).toPromise();
  227.         if (!schoolData) {
  228.           throw new Error('No school data received');
  229.         }
  230.         await this.storeSchoolData(schoolData);
  231.         console.log('School data stored');
  232.  
  233.         // Fetch and store classroom data
  234.         const classroomData = await this.classroomService.getClassroomsBySchoolId(schoolId).toPromise();
  235.         if (!classroomData || !Array.isArray(classroomData)) {
  236.           throw new Error('Invalid classroom data received');
  237.         }
  238.         await this.storeClassroomData(classroomData);
  239.         console.log('Classroom data stored');
  240.  
  241.         // Fetch and store student data
  242.         try {
  243.           await this.fetchAndStoreStudents(schoolId);
  244.           console.log('Students data stored');
  245.         } catch (error) {
  246.           console.error('Error storing students:', error);
  247.           throw new Error('Failed to store student data');
  248.         }
  249.  
  250.         // Fetch and store attendance data
  251.         const attendanceData = await this.attendanceService.getAttendanceBySchoolById(schoolId).toPromise();
  252.         if (!attendanceData || !Array.isArray(attendanceData)) {
  253.           throw new Error('Invalid attendance data received');
  254.         }
  255.         await this.storeAttendanceData(attendanceData);
  256.         console.log('Attendance data stored');
  257.  
  258.         // Fetch and store attendance history data
  259.         const attendanceHistoryData = await this.attendanceService.getAttendanceHistoryBySchoolById(schoolId).toPromise();
  260.         if (!attendanceHistoryData || !Array.isArray(attendanceHistoryData)) {
  261.           throw new Error('Invalid attendance history data received');
  262.         }
  263.         await this.storeAttendanceHistoryData(attendanceHistoryData);
  264.         console.log('Attendance history data stored');
  265.  
  266.         // Success - show toast and navigate
  267.         await loading.dismiss();
  268.         await this.showToast('Données synchronisées avec succès', 'success');
  269.         this.router.navigate(['/tabs/home']);
  270.  
  271.       } catch (error) {
  272.         console.error('Error during data synchronization:', error);
  273.         throw new Error('Data synchronization failed');
  274.       }
  275.  
  276.     } catch (error: unknown) {
  277.       console.error('Sync error:', error);
  278.       await loading.dismiss();
  279.  
  280.       if (error instanceof Error) {
  281.         await this.showToast(error.message, 'danger');
  282.       } else {
  283.         await this.showToast('Erreur lors de la synchronisation', 'danger');
  284.       }
  285.     } finally {
  286.       try {
  287.         if (loading) {
  288.           await loading.dismiss();
  289.         }
  290.       } catch (cleanupError) {
  291.         console.error('Error in cleanup:', cleanupError);
  292.       }
  293.     }
  294.   }
  295.  
  296.   private async showToast(message: string, color: string = 'primary') {
  297.     try {
  298.       const toast = await this.toastController.create({
  299.         message,
  300.         duration: 3000,
  301.         color,
  302.         position: 'bottom',
  303.         buttons: [{
  304.           text: 'OK',
  305.           role: 'cancel'
  306.         }]
  307.       });
  308.       await toast.present();
  309.     } catch (error) {
  310.       console.error('Error showing toast:', error);
  311.     }
  312.   }
  313.  
  314.   private safeParseResponse(response: any, expectedType: string): any {
  315.     if (!response) {
  316.       throw new Error(`No ${expectedType} data received`);
  317.     }
  318.     if (expectedType === 'array' && !Array.isArray(response)) {
  319.       throw new Error(`Invalid ${expectedType} data format`);
  320.     }
  321.     return response;
  322.   }
  323.  
  324.   private handleApiError(error: any, operation: string): never {
  325.     console.error(`Error during ${operation}:`, error);
  326.     throw new Error(`Failed to ${operation}`);
  327.   }
  328.  
  329.   private storeSchoolData(data: any): Promise<void> {
  330.     return new Promise((resolve, reject) => {
  331.       try {
  332.         if (!this.db) {
  333.           throw new Error('Database not initialized');
  334.         }
  335.  
  336.         const transaction = this.db.transaction('school', 'readwrite');
  337.         const store = transaction.objectStore('school');
  338.  
  339.         const request = store.put({
  340.           ...data,
  341.           sync_status: true,
  342.           last_sync: new Date().toISOString()
  343.         });
  344.  
  345.         transaction.oncomplete = () => resolve();
  346.         transaction.onerror = () => {
  347.           console.error('Error storing school data:', transaction.error);
  348.           reject(transaction.error);
  349.         };
  350.       } catch (error) {
  351.         console.error('Error in storeSchoolData:', error);
  352.         reject(error);
  353.       }
  354.     });
  355.   }
  356.  
  357.   private storeTeacherData(data: any): Promise<void> {
  358.     return new Promise((resolve, reject) => {
  359.       try {
  360.         if (!this.db) {
  361.           throw new Error('Database not initialized');
  362.         }
  363.  
  364.         const transaction = this.db.transaction('teacher', 'readwrite');
  365.         const store = transaction.objectStore('teacher');
  366.  
  367.         const request = store.put({
  368.           ...data,
  369.           sync_status: true,
  370.           last_sync: new Date().toISOString()
  371.         });
  372.  
  373.         transaction.oncomplete = () => resolve();
  374.         transaction.onerror = () => {
  375.           console.error('Error storing teacher data:', transaction.error);
  376.           reject(transaction.error);
  377.         };
  378.       } catch (error) {
  379.         console.error('Error in storeTeacherData:', error);
  380.         reject(error);
  381.       }
  382.     });
  383.   }
  384.  
  385.   private storeClassroomData(classrooms: any[]): Promise<void> {
  386.     return new Promise((resolve, reject) => {
  387.       try {
  388.         if (!this.db) {
  389.           throw new Error('Database not initialized');
  390.         }
  391.  
  392.         const transaction = this.db.transaction('classroom', 'readwrite');
  393.         const store = transaction.objectStore('classroom');
  394.  
  395.         classrooms.forEach(classroom => {
  396.           store.put({
  397.             ...classroom,
  398.             sync_status: true,
  399.             last_sync: new Date().toISOString()
  400.           });
  401.         });
  402.  
  403.         transaction.oncomplete = () => resolve();
  404.         transaction.onerror = () => {
  405.           console.error('Error storing classroom data:', transaction.error);
  406.           reject(transaction.error);
  407.         };
  408.       } catch (error) {
  409.         console.error('Error in storeClassroomData:', error);
  410.         reject(error);
  411.       }
  412.     });
  413.   }
  414.  
  415.   private async fetchAndStoreStudents(schoolId: number): Promise<void> {
  416.     try {
  417.       const students = await this.studentService.getStudentsBySchoolId(schoolId).toPromise();
  418.       await this.storeStudentData(students);
  419.       console.log(`Students stored for school ${schoolId}`);
  420.     } catch (error) {
  421.       console.error(`Error processing students for school ${schoolId}:`, error);
  422.       throw error;
  423.     }
  424.   }
  425.  
  426.   private storeStudentData(students: any[]): Promise<void> {
  427.     return new Promise((resolve, reject) => {
  428.       try {
  429.         if (!this.db) {
  430.           throw new Error('Database not initialized');
  431.         }
  432.  
  433.         const transaction = this.db.transaction('student', 'readwrite');
  434.         const store = transaction.objectStore('student');
  435.  
  436.         students.forEach(student => {
  437.           store.put({
  438.             ...student,
  439.             sync_status: true,
  440.             last_sync: new Date().toISOString()
  441.           });
  442.         });
  443.  
  444.         transaction.oncomplete = () => resolve();
  445.         transaction.onerror = () => {
  446.           console.error('Error storing student data:', transaction.error);
  447.           reject(transaction.error);
  448.         };
  449.       } catch (error) {
  450.         console.error('Error in storeStudentData:', error);
  451.         reject(error);
  452.       }
  453.     });
  454.   }
  455.  
  456.   private storeAttendanceData(attendances: any[]): Promise<void> {
  457.     return new Promise((resolve, reject) => {
  458.       try {
  459.         if (!this.db) {
  460.           throw new Error('Database not initialized');
  461.         }
  462.  
  463.         const transaction = this.db.transaction('attendance', 'readwrite');
  464.         const store = transaction.objectStore('attendance');
  465.  
  466.         attendances.forEach(attendance => {
  467.           store.put({
  468.             ...attendance,
  469.             sync_status: true,
  470.             last_sync: new Date().toISOString()
  471.           });
  472.         });
  473.  
  474.         transaction.oncomplete = () => resolve();
  475.         transaction.onerror = () => {
  476.           console.error('Error storing attendance data:', transaction.error);
  477.           reject(transaction.error);
  478.         };
  479.       } catch (error) {
  480.         console.error('Error in storeAttendanceData:', error);
  481.         reject(error);
  482.       }
  483.     });
  484.   }
  485.  
  486.   private storeAttendanceHistoryData(attendanceHistories: any[]): Promise<void> {
  487.     return new Promise((resolve, reject) => {
  488.       try {
  489.         if (!this.db) {
  490.           throw new Error('Database not initialized');
  491.         }
  492.  
  493.         const transaction = this.db.transaction('attendanceHistory', 'readwrite');
  494.         const store = transaction.objectStore('attendanceHistory');
  495.  
  496.         attendanceHistories.forEach(history => {
  497.           store.put({
  498.             ...history,
  499.             sync_status: true,
  500.             last_sync: new Date().toISOString()
  501.           });
  502.         });
  503.  
  504.         transaction.oncomplete = () => resolve();
  505.         transaction.onerror = () => {
  506.           console.error('Error storing attendance history data:', transaction.error);
  507.           reject(transaction.error);
  508.         };
  509.       } catch (error) {
  510.         console.error('Error in storeAttendanceHistoryData:', error);
  511.         reject(error);
  512.       }
  513.     });
  514.   }
  515. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement