cloud-ide-academics 0.0.1 → 0.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (20) hide show
  1. package/fesm2022/cloud-ide-academics-class-program-term-create.component-B5sVQbaC.mjs +578 -0
  2. package/fesm2022/cloud-ide-academics-class-program-term-create.component-B5sVQbaC.mjs.map +1 -0
  3. package/fesm2022/cloud-ide-academics-class-program-term-list.component-Cpbyavgd.mjs +404 -0
  4. package/fesm2022/cloud-ide-academics-class-program-term-list.component-Cpbyavgd.mjs.map +1 -0
  5. package/fesm2022/cloud-ide-academics-class-program-term.service-BW4PJQEM.mjs +111 -0
  6. package/fesm2022/cloud-ide-academics-class-program-term.service-BW4PJQEM.mjs.map +1 -0
  7. package/fesm2022/cloud-ide-academics-cloud-ide-academics-Czexp3pk.mjs +2791 -0
  8. package/fesm2022/cloud-ide-academics-cloud-ide-academics-Czexp3pk.mjs.map +1 -0
  9. package/fesm2022/cloud-ide-academics-program-class-create.component-DR31TP1Z.mjs +391 -0
  10. package/fesm2022/cloud-ide-academics-program-class-create.component-DR31TP1Z.mjs.map +1 -0
  11. package/fesm2022/cloud-ide-academics-program-class-list.component-C1iTyuQ4.mjs +433 -0
  12. package/fesm2022/cloud-ide-academics-program-class-list.component-C1iTyuQ4.mjs.map +1 -0
  13. package/fesm2022/cloud-ide-academics-program-term-section-create.component-Dg9Pjwj5.mjs +211 -0
  14. package/fesm2022/cloud-ide-academics-program-term-section-create.component-Dg9Pjwj5.mjs.map +1 -0
  15. package/fesm2022/cloud-ide-academics-program-term-section-list.component-xVeeeGDV.mjs +478 -0
  16. package/fesm2022/cloud-ide-academics-program-term-section-list.component-xVeeeGDV.mjs.map +1 -0
  17. package/fesm2022/cloud-ide-academics.mjs +1 -1535
  18. package/fesm2022/cloud-ide-academics.mjs.map +1 -1
  19. package/index.d.ts +239 -3
  20. package/package.json +1 -1
@@ -0,0 +1,2791 @@
1
+ import { authGuard } from 'cloud-ide-auth';
2
+ import * as i0 from '@angular/core';
3
+ import { inject, Injectable, DestroyRef, signal, Component, viewChild, computed } from '@angular/core';
4
+ import * as i1$1 from '@angular/common';
5
+ import { CommonModule, Location } from '@angular/common';
6
+ import * as i1 from '@angular/forms';
7
+ import { FormBuilder, Validators, ReactiveFormsModule, FormsModule } from '@angular/forms';
8
+ import { Router, ActivatedRoute } from '@angular/router';
9
+ import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
10
+ import { of, forkJoin } from 'rxjs';
11
+ import { switchMap, catchError, map } from 'rxjs/operators';
12
+ import { CideInputComponent, CideTextareaComponent, CideEleButtonComponent, CideEleTabComponent, CideIconComponent, CideSelectComponent, CideFormFieldErrorComponent, ConfirmationService, NotificationService, CideEleDataGridComponent, CideEleDropdownComponent } from 'cloud-ide-element';
13
+ import { HttpClient } from '@angular/common/http';
14
+ import { generateStringFromObject, cidePath, hostManagerRoutesUrl, academicsRoutesUrl, generateObjectFromString } from 'cloud-ide-lms-model';
15
+ import { ENTITY_SERVICE_TOKEN } from 'cloud-ide-shared';
16
+ import { AppStateHelperService } from 'cloud-ide-layout';
17
+
18
+ const academicsRoutes = [
19
+ // Academic Year Management Routes
20
+ {
21
+ path: 'academic_year',
22
+ loadComponent: () => Promise.resolve().then(function () { return academicYearList_component; }).then(c => c.AcademicYearListComponent),
23
+ title: 'Academic Year Management',
24
+ canActivate: [authGuard],
25
+ data: {
26
+ reuseTab: true,
27
+ sypg_page_code: "academic_year_list"
28
+ }
29
+ },
30
+ {
31
+ path: 'academic_year/create',
32
+ loadComponent: () => Promise.resolve().then(function () { return academicYearCreate_component; }).then(c => c.AcademicYearCreateComponent),
33
+ title: 'Create Academic Year',
34
+ canActivate: [authGuard],
35
+ data: {
36
+ reuseTab: true,
37
+ sypg_page_code: "academic_year_list"
38
+ }
39
+ },
40
+ {
41
+ path: 'academic_year/edit/:query',
42
+ loadComponent: () => Promise.resolve().then(function () { return academicYearCreate_component; }).then(c => c.AcademicYearCreateComponent),
43
+ title: 'Edit Academic Year',
44
+ canActivate: [authGuard],
45
+ data: {
46
+ reuseTab: true,
47
+ sypg_page_code: "academic_year_list"
48
+ }
49
+ },
50
+ {
51
+ path: 'academic_year/view/:query',
52
+ loadComponent: () => Promise.resolve().then(function () { return academicYearCreate_component; }).then(c => c.AcademicYearCreateComponent),
53
+ title: 'View Academic Year',
54
+ canActivate: [authGuard],
55
+ data: {
56
+ reuseTab: true,
57
+ sypg_page_code: "academic_year_list"
58
+ }
59
+ },
60
+ {
61
+ path: 'program-class-management',
62
+ loadComponent: () => import('./cloud-ide-academics-program-class-list.component-C1iTyuQ4.mjs').then(c => c.ProgramClassListComponent),
63
+ title: 'Program Class Management',
64
+ canActivate: [authGuard],
65
+ data: {
66
+ reuseTab: false,
67
+ sypg_page_code: "program_class"
68
+ }
69
+ },
70
+ {
71
+ path: 'program-class-management/create',
72
+ loadComponent: () => import('./cloud-ide-academics-program-class-create.component-DR31TP1Z.mjs').then(c => c.ProgramClassCreateComponent),
73
+ title: 'Create Program Class',
74
+ canActivate: [authGuard],
75
+ data: {
76
+ reuseTab: false,
77
+ sypg_page_code: "program_class"
78
+ }
79
+ },
80
+ {
81
+ path: 'program-class-management/edit/:query',
82
+ loadComponent: () => import('./cloud-ide-academics-program-class-create.component-DR31TP1Z.mjs').then(c => c.ProgramClassCreateComponent),
83
+ title: 'Edit Program Class',
84
+ canActivate: [authGuard],
85
+ data: {
86
+ reuseTab: false,
87
+ sypg_page_code: "program_class"
88
+ }
89
+ },
90
+ {
91
+ path: 'program-class-management/view/:query',
92
+ loadComponent: () => import('./cloud-ide-academics-program-class-create.component-DR31TP1Z.mjs').then(c => c.ProgramClassCreateComponent),
93
+ title: 'View Program Class',
94
+ canActivate: [authGuard],
95
+ data: {
96
+ reuseTab: false,
97
+ sypg_page_code: "program_class"
98
+ }
99
+ },
100
+ {
101
+ path: 'program-term-management/create',
102
+ loadComponent: () => import('./cloud-ide-academics-class-program-term-create.component-B5sVQbaC.mjs').then(c => c.ClassProgramTermCreateComponent),
103
+ title: 'Create Class Program Term',
104
+ canActivate: [authGuard],
105
+ data: {
106
+ reuseTab: true,
107
+ sypg_page_code: "class_program_term_list"
108
+ }
109
+ },
110
+ {
111
+ path: 'program-term-management/edit/:query',
112
+ loadComponent: () => import('./cloud-ide-academics-class-program-term-create.component-B5sVQbaC.mjs').then(c => c.ClassProgramTermCreateComponent),
113
+ title: 'Edit Class Program Term',
114
+ canActivate: [authGuard],
115
+ data: {
116
+ reuseTab: true,
117
+ sypg_page_code: "class_program_term_list"
118
+ }
119
+ },
120
+ {
121
+ path: 'program-term-management/view/:query',
122
+ loadComponent: () => import('./cloud-ide-academics-class-program-term-create.component-B5sVQbaC.mjs').then(c => c.ClassProgramTermCreateComponent),
123
+ title: 'View Class Program Term',
124
+ canActivate: [authGuard],
125
+ data: {
126
+ reuseTab: true,
127
+ sypg_page_code: "class_program_term_list"
128
+ }
129
+ },
130
+ {
131
+ path: 'program-term-management/:query',
132
+ loadComponent: () => import('./cloud-ide-academics-class-program-term-list.component-Cpbyavgd.mjs').then(c => c.ClassProgramTermListComponent),
133
+ title: 'Class Program Term Management',
134
+ canActivate: [authGuard],
135
+ data: {
136
+ reuseTab: true,
137
+ sypg_page_code: "class_program_term_list"
138
+ }
139
+ },
140
+ {
141
+ path: 'class-program-term/:query',
142
+ loadComponent: () => import('./cloud-ide-academics-program-term-section-list.component-xVeeeGDV.mjs').then(c => c.ProgramTermSectionListComponent),
143
+ title: 'Program Term Section Management',
144
+ canActivate: [authGuard],
145
+ data: {
146
+ reuseTab: true,
147
+ sypg_page_code: "program_term_section_list"
148
+ }
149
+ },
150
+ {
151
+ path: 'class-program-term/create',
152
+ loadComponent: () => import('./cloud-ide-academics-program-term-section-create.component-Dg9Pjwj5.mjs').then(c => c.ProgramTermSectionCreateComponent),
153
+ title: 'Create Program Term Section',
154
+ canActivate: [authGuard],
155
+ data: {
156
+ reuseTab: true,
157
+ sypg_page_code: "program_term_section_list"
158
+ }
159
+ },
160
+ {
161
+ path: 'class-program-term/edit/:query',
162
+ loadComponent: () => import('./cloud-ide-academics-program-term-section-create.component-Dg9Pjwj5.mjs').then(c => c.ProgramTermSectionCreateComponent),
163
+ title: 'Edit Program Term Section',
164
+ canActivate: [authGuard],
165
+ data: {
166
+ reuseTab: true,
167
+ sypg_page_code: "program_term_section_list"
168
+ }
169
+ },
170
+ {
171
+ path: 'class-program-term/view/:query',
172
+ loadComponent: () => import('./cloud-ide-academics-program-term-section-create.component-Dg9Pjwj5.mjs').then(c => c.ProgramTermSectionCreateComponent),
173
+ title: 'View Program Term Section',
174
+ canActivate: [authGuard],
175
+ data: {
176
+ reuseTab: true,
177
+ sypg_page_code: "program_term_section_list"
178
+ }
179
+ },
180
+ // Class Program Branch Management Routes
181
+ {
182
+ path: 'program_specialization/:query',
183
+ loadComponent: () => Promise.resolve().then(function () { return classProgramBranchList_component; }).then(c => c.CideLytClassProgramBranchListComponent),
184
+ title: 'Class Program Branch Management',
185
+ canActivate: [authGuard],
186
+ data: {
187
+ reuseTab: true,
188
+ sypg_page_code: "class_program_branch"
189
+ }
190
+ },
191
+ {
192
+ path: 'program_specialization',
193
+ loadComponent: () => Promise.resolve().then(function () { return classProgramBranchList_component; }).then(c => c.CideLytClassProgramBranchListComponent),
194
+ title: 'Class Program Branch Management',
195
+ canActivate: [authGuard],
196
+ data: {
197
+ reuseTab: true,
198
+ sypg_page_code: "class_program_branch"
199
+ }
200
+ },
201
+ {
202
+ path: 'program_specialization/create/:query?',
203
+ loadComponent: () => Promise.resolve().then(function () { return classProgramBranchForm_component; }).then(c => c.CideLytClassProgramBranchFormComponent),
204
+ title: 'Create Class Program Branch',
205
+ canActivate: [authGuard],
206
+ data: {
207
+ reuseTab: true,
208
+ sypg_page_code: "class_program_branch"
209
+ }
210
+ },
211
+ {
212
+ path: 'program_specialization/edit/:query',
213
+ loadComponent: () => Promise.resolve().then(function () { return classProgramBranchForm_component; }).then(c => c.CideLytClassProgramBranchFormComponent),
214
+ title: 'Edit Class Program Branch',
215
+ canActivate: [authGuard],
216
+ data: {
217
+ reuseTab: true,
218
+ sypg_page_code: "class_program_branch"
219
+ }
220
+ },
221
+ {
222
+ path: 'program_specialization/view/:query',
223
+ loadComponent: () => Promise.resolve().then(function () { return classProgramBranchForm_component; }).then(c => c.CideLytClassProgramBranchFormComponent),
224
+ title: 'View Class Program Branch',
225
+ canActivate: [authGuard],
226
+ data: {
227
+ reuseTab: true,
228
+ sypg_page_code: "class_program_branch"
229
+ }
230
+ }
231
+ ];
232
+
233
+ class CideLytAcademicYearService {
234
+ http = inject(HttpClient);
235
+ /**
236
+ * Get list of academic years
237
+ * @param payload - Query parameters for filtering/pagination
238
+ * @returns Observable of academic year list response
239
+ */
240
+ getAcademicYearList(payload) {
241
+ console.log("payload", payload);
242
+ const query = generateStringFromObject(payload);
243
+ const url = cidePath.join([
244
+ hostManagerRoutesUrl.cideSuiteHost,
245
+ academicsRoutesUrl.module,
246
+ academicsRoutesUrl.academicYear,
247
+ query
248
+ ]);
249
+ return this.http.get(url);
250
+ }
251
+ /**
252
+ * Get academic year by ID
253
+ * @param payload - Academic year ID payload
254
+ * @returns Observable of academic year data
255
+ */
256
+ getAcademicYearById(payload) {
257
+ const query = generateStringFromObject(payload);
258
+ const url = cidePath.join([
259
+ hostManagerRoutesUrl.cideSuiteHost,
260
+ academicsRoutesUrl.module,
261
+ academicsRoutesUrl.academicYear,
262
+ 'byId',
263
+ query
264
+ ]);
265
+ return this.http.get(url);
266
+ }
267
+ /**
268
+ * Create or update academic year
269
+ * @param data - Academic year data to save
270
+ * @returns Observable of the save response
271
+ */
272
+ saveUpdateAcademicYear(data) {
273
+ const url = cidePath.join([
274
+ hostManagerRoutesUrl.cideSuiteHost,
275
+ academicsRoutesUrl.module,
276
+ academicsRoutesUrl.academicYear
277
+ ]);
278
+ return this.http.post(url, data);
279
+ }
280
+ /**
281
+ * Create or update academic year with mappings
282
+ * @param data - Academic year data with mappings
283
+ * @returns Observable of the save response
284
+ */
285
+ saveUpdateAcademicYearWithMappings(data) {
286
+ // Extract mappings from the data
287
+ const mappings = data.acayr_academic_year_mappings || [];
288
+ const academicYearData = { ...data };
289
+ delete academicYearData.acayr_academic_year_mappings;
290
+ // First save/update the academic year
291
+ return this.saveUpdateAcademicYear(academicYearData).pipe(switchMap((academicYearResponse) => {
292
+ if (!academicYearResponse.success || !academicYearResponse.data) {
293
+ return of(academicYearResponse);
294
+ }
295
+ const academicYearId = academicYearResponse.data._id;
296
+ // If no mappings, return the academic year response
297
+ if (mappings.length === 0) {
298
+ return of(academicYearResponse);
299
+ }
300
+ // Process mappings
301
+ const mappingObservables = mappings.map((mapping) => {
302
+ const mappingPayload = {
303
+ _id: mapping._id && !mapping._id.startsWith('temp_') ? mapping._id : undefined,
304
+ acayrmp_academic_year_id_acayr: academicYearId,
305
+ acayrmp_entity_id_syen: mapping.acayrmp_entity_id_syen,
306
+ acayrmp_islocked: mapping.acayrmp_islocked || false,
307
+ acayrmp_iscurrent: mapping.acayrmp_iscurrent || false
308
+ };
309
+ const mappingUrl = cidePath.join([
310
+ hostManagerRoutesUrl.cideSuiteHost,
311
+ academicsRoutesUrl.module,
312
+ academicsRoutesUrl.academicYearMapping
313
+ ]);
314
+ return this.http.post(mappingUrl, mappingPayload).pipe(catchError((error) => {
315
+ console.error('Error saving mapping:', error);
316
+ return of({ success: false, error });
317
+ }));
318
+ });
319
+ // Execute all mapping operations
320
+ return forkJoin(mappingObservables).pipe(map((mappingResponses) => {
321
+ // Check if all mappings were successful
322
+ const allMappingsSuccessful = mappingResponses.every((response) => response.success);
323
+ if (allMappingsSuccessful) {
324
+ return {
325
+ ...academicYearResponse,
326
+ message: 'Academic year and mappings saved successfully'
327
+ };
328
+ }
329
+ else {
330
+ return {
331
+ ...academicYearResponse,
332
+ message: 'Academic year saved but some mappings failed',
333
+ mappingErrors: mappingResponses.filter((response) => !response.success)
334
+ };
335
+ }
336
+ }));
337
+ }), catchError((error) => {
338
+ console.error('Error in saveUpdateAcademicYearWithMappings:', error);
339
+ return of({
340
+ success: false,
341
+ code: 500,
342
+ message: 'Error saving academic year with mappings',
343
+ error
344
+ });
345
+ }));
346
+ }
347
+ /**
348
+ * Delete academic year
349
+ * @param payload - Academic year ID payload
350
+ * @returns Observable of the delete response
351
+ */
352
+ deleteAcademicYear(payload) {
353
+ const query = generateStringFromObject(payload);
354
+ const url = cidePath.join([
355
+ hostManagerRoutesUrl.cideSuiteHost,
356
+ academicsRoutesUrl.module,
357
+ academicsRoutesUrl.academicYear,
358
+ 'delete',
359
+ query
360
+ ]);
361
+ return this.http.delete(url);
362
+ }
363
+ /**
364
+ * Toggle academic year status
365
+ * @param payload - Academic year ID payload
366
+ * @returns Observable of the toggle response
367
+ */
368
+ toggleAcademicYearStatus(payload) {
369
+ const url = cidePath.join([
370
+ hostManagerRoutesUrl.cideSuiteHost,
371
+ academicsRoutesUrl.module,
372
+ academicsRoutesUrl.academicYear,
373
+ 'toggle-status'
374
+ ]);
375
+ console.log('🔄 Making PATCH request to toggle academic year status:', { url, payload });
376
+ return this.http.patch(url, payload);
377
+ }
378
+ /**
379
+ * Delete academic year mapping
380
+ * @param payload - Academic year mapping ID payload
381
+ * @returns Observable of the delete response
382
+ */
383
+ deleteAcademicYearMapping(payload) {
384
+ const url = cidePath.join([
385
+ hostManagerRoutesUrl.cideSuiteHost,
386
+ academicsRoutesUrl.module,
387
+ academicsRoutesUrl.academicYearMapping
388
+ ]);
389
+ return this.http.delete(url, { body: payload });
390
+ }
391
+ /**
392
+ * Toggle academic year mapping status
393
+ * @param payload - Academic year mapping ID payload
394
+ * @returns Observable of the toggle response
395
+ */
396
+ toggleAcademicYearMappingStatus(payload) {
397
+ const url = cidePath.join([
398
+ hostManagerRoutesUrl.cideSuiteHost,
399
+ academicsRoutesUrl.module,
400
+ academicsRoutesUrl.academicYearMapping,
401
+ 'toggle-status'
402
+ ]);
403
+ console.log('🔄 Making PATCH request to toggle academic year mapping status:', { url, payload });
404
+ return this.http.patch(url, payload);
405
+ }
406
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: CideLytAcademicYearService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
407
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: CideLytAcademicYearService, providedIn: 'root' });
408
+ }
409
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: CideLytAcademicYearService, decorators: [{
410
+ type: Injectable,
411
+ args: [{
412
+ providedIn: 'root'
413
+ }]
414
+ }] });
415
+
416
+ class CideLytAcademicYearMappingService {
417
+ http = inject(HttpClient);
418
+ /**
419
+ * Get list of academic year mappings
420
+ * @param payload - Query parameters for filtering/pagination
421
+ * @returns Observable of academic year mapping list response
422
+ */
423
+ getAcademicYearMappingList(payload) {
424
+ const query = generateStringFromObject(payload);
425
+ const url = cidePath.join([
426
+ hostManagerRoutesUrl.cideSuiteHost,
427
+ academicsRoutesUrl.module,
428
+ academicsRoutesUrl.academicYearMapping,
429
+ query
430
+ ]);
431
+ return this.http.get(url);
432
+ }
433
+ /**
434
+ * Get academic year mapping by ID
435
+ * @param payload - Academic year mapping ID payload
436
+ * @returns Observable of academic year mapping data
437
+ */
438
+ getAcademicYearMappingById(payload) {
439
+ const query = generateStringFromObject(payload);
440
+ const url = cidePath.join([
441
+ hostManagerRoutesUrl.cideSuiteHost,
442
+ academicsRoutesUrl.module,
443
+ academicsRoutesUrl.academicYearMapping,
444
+ 'byId',
445
+ query
446
+ ]);
447
+ return this.http.get(url);
448
+ }
449
+ /**
450
+ * Create or update academic year mapping
451
+ * @param data - Academic year mapping data to save
452
+ * @returns Observable of the save response
453
+ */
454
+ saveUpdateAcademicYearMapping(data) {
455
+ const url = cidePath.join([
456
+ hostManagerRoutesUrl.cideSuiteHost,
457
+ academicsRoutesUrl.module,
458
+ academicsRoutesUrl.academicYearMapping
459
+ ]);
460
+ return this.http.post(url, data);
461
+ }
462
+ /**
463
+ * Delete academic year mapping
464
+ * @param payload - Academic year mapping ID payload
465
+ * @returns Observable of the delete response
466
+ */
467
+ deleteAcademicYearMapping(payload) {
468
+ const query = generateStringFromObject(payload);
469
+ const url = cidePath.join([
470
+ hostManagerRoutesUrl.cideSuiteHost,
471
+ academicsRoutesUrl.module,
472
+ academicsRoutesUrl.academicYearMapping,
473
+ 'delete',
474
+ query
475
+ ]);
476
+ return this.http.delete(url);
477
+ }
478
+ /**
479
+ * Toggle academic year mapping status
480
+ * @param payload - Academic year mapping ID payload
481
+ * @returns Observable of the toggle response
482
+ */
483
+ toggleAcademicYearMappingStatus(payload) {
484
+ const url = cidePath.join([
485
+ hostManagerRoutesUrl.cideSuiteHost,
486
+ academicsRoutesUrl.module,
487
+ academicsRoutesUrl.academicYearMapping,
488
+ 'toggle-status'
489
+ ]);
490
+ return this.http.post(url, payload);
491
+ }
492
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: CideLytAcademicYearMappingService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
493
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: CideLytAcademicYearMappingService, providedIn: 'root' });
494
+ }
495
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: CideLytAcademicYearMappingService, decorators: [{
496
+ type: Injectable,
497
+ args: [{
498
+ providedIn: 'root'
499
+ }]
500
+ }] });
501
+
502
+ class AcademicYearCreateComponent {
503
+ // Modern Angular 20+ dependency injection
504
+ destroyRef = inject(DestroyRef);
505
+ fb = inject(FormBuilder);
506
+ academicYearService = inject(CideLytAcademicYearService);
507
+ academicYearMappingService = inject(CideLytAcademicYearMappingService);
508
+ entityService = inject(ENTITY_SERVICE_TOKEN);
509
+ router = inject(Router);
510
+ route = inject(ActivatedRoute);
511
+ // Form and state management with proper typing
512
+ academicYearForm;
513
+ activeTab = signal('basic', ...(ngDevMode ? [{ debugName: "activeTab" }] : []));
514
+ loading = signal(false, ...(ngDevMode ? [{ debugName: "loading" }] : []));
515
+ // Academic year information from route
516
+ academicYearId = signal('', ...(ngDevMode ? [{ debugName: "academicYearId" }] : []));
517
+ isEditMode = signal(false, ...(ngDevMode ? [{ debugName: "isEditMode" }] : []));
518
+ originalMappings = signal([], ...(ngDevMode ? [{ debugName: "originalMappings" }] : [])); // Track original mappings for deletion
519
+ // Entity options for dropdown
520
+ entityOptions = signal([], ...(ngDevMode ? [{ debugName: "entityOptions" }] : []));
521
+ constructor() {
522
+ this.academicYearForm = this.fb.group({
523
+ // Basic Academic Year Information
524
+ acayr_code: ['', [Validators.required]],
525
+ acayr_name: ['', [Validators.required]],
526
+ acayr_description: [''],
527
+ acayr_from_date: ['', [Validators.required]],
528
+ acayr_to_date: ['', [Validators.required]],
529
+ acayr_isactive: [true],
530
+ acayr_iscurrent: [false],
531
+ acayr_islocked: [false],
532
+ // Academic Year Mapping Information
533
+ acayr_academic_year_mappings: this.fb.array([])
534
+ });
535
+ }
536
+ ngOnInit() {
537
+ this.initializeComponent();
538
+ }
539
+ /**
540
+ * Initialize component
541
+ */
542
+ initializeComponent() {
543
+ // Get academic year information from route (for edit mode)
544
+ this.route.params.pipe(takeUntilDestroyed(this.destroyRef)).subscribe(params => {
545
+ const queryParams = params['query'];
546
+ console.log(queryParams, 'queryParams');
547
+ if (queryParams) {
548
+ // Query parameters passed (following page-controls pattern)
549
+ const queryData = generateObjectFromString(queryParams);
550
+ if (queryData?.acayr_id) {
551
+ this.academicYearId.set(queryData.acayr_id);
552
+ this.isEditMode.set(true);
553
+ this.loadAcademicYearData(queryData.acayr_id);
554
+ }
555
+ }
556
+ else {
557
+ // Create mode
558
+ this.isEditMode.set(false);
559
+ }
560
+ // Always load dropdown options
561
+ this.loadDropdownOptions();
562
+ });
563
+ }
564
+ /**
565
+ * Load dropdown options
566
+ */
567
+ loadDropdownOptions() {
568
+ console.log('🏢 Loading dropdown options');
569
+ // Load entity options
570
+ this.entityService.getEntityList({}).subscribe({
571
+ next: (response) => {
572
+ if (response?.success) {
573
+ console.log(`🏢 entities:`, response.data);
574
+ this.entityOptions.set(response.data || []);
575
+ }
576
+ },
577
+ error: (error) => console.error('Error loading entities:', error)
578
+ });
579
+ }
580
+ /**
581
+ * Load academic year data for edit mode
582
+ */
583
+ loadAcademicYearData(academicYearId) {
584
+ this.loading.set(true);
585
+ const payload = {
586
+ acayr_id: academicYearId
587
+ };
588
+ // Load academic year data
589
+ this.academicYearService.getAcademicYearById(payload).subscribe({
590
+ next: (response) => {
591
+ if (response?.success && response.data) {
592
+ console.log('📚 Academic year data loaded:', response.data);
593
+ this.populateFormWithAcademicYearData(response.data);
594
+ // Load existing mappings for this academic year
595
+ this.loadAcademicYearMappings(academicYearId);
596
+ }
597
+ else {
598
+ console.error('❌ Failed to load academic year data');
599
+ this.loading.set(false);
600
+ }
601
+ },
602
+ error: (error) => {
603
+ console.error('❌ Error loading academic year data:', error);
604
+ this.loading.set(false);
605
+ }
606
+ });
607
+ }
608
+ /**
609
+ * Load academic year mappings for edit mode
610
+ */
611
+ loadAcademicYearMappings(academicYearId) {
612
+ const mappingPayload = {
613
+ acayrmp_academic_year_id_acayr: academicYearId
614
+ };
615
+ this.academicYearMappingService.getAcademicYearMappingList(mappingPayload).subscribe({
616
+ next: (response) => {
617
+ if (response?.success && response.data) {
618
+ console.log('🔗 Academic year mappings loaded:', response.data);
619
+ this.populateFormWithMappingsData(response.data);
620
+ }
621
+ else {
622
+ console.warn('⚠️ No mappings found for this academic year');
623
+ }
624
+ this.loading.set(false);
625
+ },
626
+ error: (error) => {
627
+ console.error('❌ Error loading academic year mappings:', error);
628
+ this.loading.set(false);
629
+ }
630
+ });
631
+ }
632
+ /**
633
+ * Populate form with academic year data
634
+ */
635
+ populateFormWithAcademicYearData(data) {
636
+ if (data) {
637
+ this.academicYearForm.patchValue({
638
+ acayr_code: data.acayr_code || '',
639
+ acayr_name: data.acayr_name || '',
640
+ acayr_description: data.acayr_description || '',
641
+ acayr_from_date: data.acayr_from_date ? new Date(data.acayr_from_date).toISOString().split('T')[0] : '',
642
+ acayr_to_date: data.acayr_to_date ? new Date(data.acayr_to_date).toISOString().split('T')[0] : '',
643
+ acayr_isactive: data.acayr_isactive ?? true,
644
+ acayr_iscurrent: data.acayr_iscurrent ?? false,
645
+ acayr_islocked: data.acayr_islocked ?? false
646
+ });
647
+ }
648
+ }
649
+ /**
650
+ * Populate form with mappings data
651
+ */
652
+ populateFormWithMappingsData(mappings) {
653
+ if (mappings && Array.isArray(mappings)) {
654
+ // Store original mappings for deletion tracking
655
+ this.originalMappings.set([...mappings]);
656
+ // Clear existing mappings
657
+ while (this.academicYearMappingsArray.length !== 0) {
658
+ this.academicYearMappingsArray.removeAt(0);
659
+ }
660
+ // Add existing mappings
661
+ mappings.forEach((mapping) => {
662
+ const mappingGroup = this.fb.group({
663
+ _id: [mapping._id || ''],
664
+ acayrmp_academic_year_id_acayr: [mapping.acayrmp_academic_year_id_acayr || this.academicYearId() || '', [Validators.required]],
665
+ acayrmp_entity_id_syen: [mapping.acayrmp_entity_id_syen || '', [Validators.required]],
666
+ acayrmp_islocked: [mapping.acayrmp_islocked ?? false],
667
+ acayrmp_iscurrent: [mapping.acayrmp_iscurrent ?? false]
668
+ });
669
+ this.academicYearMappingsArray.push(mappingGroup);
670
+ });
671
+ }
672
+ }
673
+ /**
674
+ * Tab configuration
675
+ */
676
+ academicYearTabs() {
677
+ return [
678
+ { id: 'basic', label: 'Academic Year Details', icon: 'school' },
679
+ { id: 'mapping', label: 'Mapping Configuration', icon: 'link' }
680
+ ];
681
+ }
682
+ onTabChange(tab) {
683
+ this.activeTab.set(tab.id);
684
+ }
685
+ onSubmit() {
686
+ if (this.academicYearForm.valid && this.validateMappings()) {
687
+ this.loading.set(true);
688
+ const formData = this.academicYearForm.value;
689
+ // Prepare payload with mappings
690
+ const payload = {
691
+ ...formData,
692
+ _id: this.isEditMode() ? this.academicYearId() : undefined,
693
+ acayr_academic_year_mappings: this.getAcademicYearMappingsValue()
694
+ };
695
+ console.log('📤 Submitting academic year with mappings:', payload);
696
+ // First delete removed mappings, then save/update academic year
697
+ this.deleteRemovedMappings().pipe(switchMap(() => {
698
+ // After deleting removed mappings, save/update the academic year
699
+ return this.academicYearService.saveUpdateAcademicYearWithMappings(payload);
700
+ })).subscribe({
701
+ next: (response) => {
702
+ if (response?.success) {
703
+ console.log('✅ Academic year and mappings saved successfully:', response.data);
704
+ // Check if there were any mapping errors
705
+ if (response.mappingErrors && response.mappingErrors.length > 0) {
706
+ console.warn('⚠️ Some mappings failed:', response.mappingErrors);
707
+ }
708
+ else {
709
+ this.goBackToAcademicYearList();
710
+ }
711
+ }
712
+ else {
713
+ console.error('❌ Failed to save academic year');
714
+ }
715
+ this.loading.set(false);
716
+ },
717
+ error: (error) => {
718
+ console.error('❌ Error saving academic year:', error);
719
+ this.loading.set(false);
720
+ }
721
+ });
722
+ }
723
+ else {
724
+ console.warn('Form is invalid');
725
+ this.markFormGroupTouched();
726
+ }
727
+ }
728
+ /**
729
+ * Mark all form controls as touched to trigger validation display
730
+ */
731
+ markFormGroupTouched() {
732
+ Object.keys(this.academicYearForm.controls).forEach(key => {
733
+ const control = this.academicYearForm.get(key);
734
+ control?.markAsTouched();
735
+ });
736
+ }
737
+ resetForm() {
738
+ this.academicYearForm.reset({
739
+ acayr_isactive: true,
740
+ acayr_iscurrent: false,
741
+ acayr_islocked: false
742
+ });
743
+ // Clear the mappings array
744
+ while (this.academicYearMappingsArray.length !== 0) {
745
+ this.academicYearMappingsArray.removeAt(0);
746
+ }
747
+ // Reset academic year ID
748
+ this.academicYearId.set('');
749
+ this.isEditMode.set(false);
750
+ this.originalMappings.set([]);
751
+ // Reset entity options to show all entities again
752
+ this.updateEntityOptionsForMappings();
753
+ }
754
+ /**
755
+ * Go back to academic year list
756
+ */
757
+ goBackToAcademicYearList() {
758
+ this.router.navigate(['/control-panel/academic-year']);
759
+ }
760
+ /**
761
+ * Cancel form and optionally navigate back
762
+ */
763
+ cancelForm() {
764
+ if (this.isEditMode()) {
765
+ this.goBackToAcademicYearList();
766
+ }
767
+ else {
768
+ this.resetForm();
769
+ }
770
+ }
771
+ /**
772
+ * Get page title based on mode
773
+ */
774
+ getPageTitle() {
775
+ return this.isEditMode() ? 'Edit Academic Year' : 'Create New Academic Year';
776
+ }
777
+ /**
778
+ * Getter methods for form arrays
779
+ */
780
+ get academicYearMappingsArray() {
781
+ return this.academicYearForm.get('acayr_academic_year_mappings');
782
+ }
783
+ /**
784
+ * Add new academic year mapping
785
+ */
786
+ addAcademicYearMapping() {
787
+ // Check if there are any available entities to map
788
+ const availableEntities = this.getAvailableEntityCount(this.academicYearMappingsArray.length);
789
+ if (availableEntities === 0) {
790
+ console.warn('No available entities to map');
791
+ return;
792
+ }
793
+ // Generate a temporary ID for new mappings
794
+ const tempId = 'temp_' + Date.now() + '_' + Math.random().toString(36).substr(2, 9);
795
+ const academicYearMapping = this.fb.group({
796
+ _id: [tempId],
797
+ acayrmp_academic_year_id_acayr: [this.academicYearId() || '', [Validators.required]],
798
+ acayrmp_entity_id_syen: ['', [Validators.required]],
799
+ acayrmp_islocked: [false],
800
+ acayrmp_iscurrent: [false]
801
+ });
802
+ this.academicYearMappingsArray.push(academicYearMapping);
803
+ }
804
+ /**
805
+ * Update academic year ID in all existing mappings when academic year ID changes
806
+ */
807
+ updateMappingsAcademicYearId(newAcademicYearId) {
808
+ const mappingsArray = this.academicYearMappingsArray;
809
+ mappingsArray.controls.forEach((control) => {
810
+ if (control.get('acayrmp_academic_year_id_acayr')) {
811
+ control.get('acayrmp_academic_year_id_acayr').setValue(newAcademicYearId);
812
+ }
813
+ });
814
+ }
815
+ /**
816
+ * Get form array value for validation or submission
817
+ */
818
+ getAcademicYearMappingsValue() {
819
+ return this.academicYearMappingsArray.value;
820
+ }
821
+ /**
822
+ * Check if mappings array has any invalid controls
823
+ */
824
+ isMappingsArrayValid() {
825
+ return this.academicYearMappingsArray.valid;
826
+ }
827
+ /**
828
+ * Set academic year ID for all existing mappings
829
+ * This is useful when the academic year ID is generated after creation
830
+ */
831
+ setAcademicYearIdForMappings(academicYearId) {
832
+ this.academicYearId.set(academicYearId);
833
+ this.updateMappingsAcademicYearId(academicYearId);
834
+ }
835
+ /**
836
+ * Validate that all mappings have required fields
837
+ */
838
+ validateMappings() {
839
+ const mappings = this.academicYearMappingsArray.controls;
840
+ // Check if there are any mappings
841
+ if (mappings.length === 0) {
842
+ return true; // No mappings is valid
843
+ }
844
+ // Validate each mapping
845
+ for (let i = 0; i < mappings.length; i++) {
846
+ const mapping = mappings[i];
847
+ // Check required fields
848
+ if (!mapping.get('acayrmp_entity_id_syen')?.value) {
849
+ console.warn(`Mapping ${i + 1} is missing entity selection`);
850
+ return false;
851
+ }
852
+ // Check for duplicate entity selections
853
+ const currentEntityId = mapping.get('acayrmp_entity_id_syen')?.value;
854
+ const duplicateIndex = this.findDuplicateEntitySelection(currentEntityId, i);
855
+ if (duplicateIndex !== -1) {
856
+ console.warn(`Mapping ${i + 1} has duplicate entity selection with mapping ${duplicateIndex + 1}`);
857
+ return false;
858
+ }
859
+ }
860
+ return true;
861
+ }
862
+ /**
863
+ * Find duplicate entity selection in mappings
864
+ */
865
+ findDuplicateEntitySelection(entityId, currentIndex) {
866
+ const mappings = this.academicYearMappingsArray.controls;
867
+ for (let i = 0; i < mappings.length; i++) {
868
+ if (i !== currentIndex) {
869
+ const mapping = mappings[i];
870
+ if (mapping.get('acayrmp_entity_id_syen')?.value === entityId) {
871
+ return i;
872
+ }
873
+ }
874
+ }
875
+ return -1;
876
+ }
877
+ /**
878
+ * Remove academic year mapping
879
+ */
880
+ removeAcademicYearMapping(index) {
881
+ this.academicYearMappingsArray.removeAt(index);
882
+ // Update entity options after removal to re-enable previously selected entities
883
+ this.updateEntityOptionsForMappings();
884
+ }
885
+ /**
886
+ * Handle entity selection change for a specific mapping
887
+ */
888
+ onMappingEntityChange(event, mappingIndex) {
889
+ const selectedEntityId = event?.value || event;
890
+ if (selectedEntityId) {
891
+ console.log(`🏢 Entity selected for mapping ${mappingIndex}:`, selectedEntityId);
892
+ // Trigger change detection to update other mappings' entity options
893
+ this.updateEntityOptionsForMappings();
894
+ }
895
+ }
896
+ /**
897
+ * Get filtered entity options excluding already selected entities in other mappings
898
+ * @param currentMappingIndex The index of the current mapping being edited
899
+ * @returns Entity options excluding already selected entities
900
+ */
901
+ getFilteredEntityOptions(currentMappingIndex) {
902
+ const allEntities = this.entityOptions();
903
+ if (!allEntities || allEntities.length === 0) {
904
+ return [];
905
+ }
906
+ // Get all currently selected entity IDs from other mappings (excluding current mapping)
907
+ const selectedEntityIds = this.getSelectedEntityIds(currentMappingIndex);
908
+ console.log(`🔍 Filtering entities for mapping ${currentMappingIndex}:`, {
909
+ totalEntities: allEntities.length,
910
+ selectedEntityIds,
911
+ availableEntities: allEntities.length - selectedEntityIds.length
912
+ });
913
+ // Return only entities that are not already selected in other mappings
914
+ return allEntities.filter((entity) => {
915
+ const entityId = entity._id;
916
+ const isAlreadySelected = selectedEntityIds.includes(entityId);
917
+ if (isAlreadySelected) {
918
+ console.log(`🚫 Entity "${entity.syen_name}" (${entityId}) is already selected in another mapping - excluding from options`);
919
+ }
920
+ return !isAlreadySelected;
921
+ });
922
+ }
923
+ /**
924
+ * Get all currently selected entity IDs from other mappings
925
+ */
926
+ getSelectedEntityIds(excludeMappingIndex) {
927
+ const mappingsArray = this.academicYearMappingsArray;
928
+ const selectedIds = [];
929
+ mappingsArray.controls.forEach((control, index) => {
930
+ if (index !== excludeMappingIndex) {
931
+ const entityId = control.get('acayrmp_entity_id_syen')?.value;
932
+ if (entityId) {
933
+ selectedIds.push(entityId);
934
+ }
935
+ }
936
+ });
937
+ return selectedIds;
938
+ }
939
+ /**
940
+ * Update entity options for all mappings to prevent duplicates
941
+ */
942
+ updateEntityOptionsForMappings() {
943
+ // This method triggers change detection to update the UI
944
+ // The actual filtering is done in getEntityOptionsForMapping method
945
+ console.log('🔄 Updating entity options for all mappings');
946
+ }
947
+ /**
948
+ * Check if an entity is disabled for a specific mapping
949
+ */
950
+ isEntityDisabled(entityId, mappingIndex) {
951
+ const selectedEntityIds = this.getSelectedEntityIds(mappingIndex);
952
+ return selectedEntityIds.includes(entityId);
953
+ }
954
+ /**
955
+ * Get the count of available entities for a specific mapping
956
+ */
957
+ getAvailableEntityCount(mappingIndex) {
958
+ const availableEntities = this.getFilteredEntityOptions(mappingIndex);
959
+ return availableEntities.length;
960
+ }
961
+ /**
962
+ * Get the count of total entities
963
+ */
964
+ getTotalEntityCount() {
965
+ return this.entityOptions().length;
966
+ }
967
+ /**
968
+ * Check if all entities are already selected in other mappings
969
+ * @param currentMappingIndex The index of the current mapping being edited
970
+ * @returns True if all entities are already selected
971
+ */
972
+ isAllEntitiesSelected(currentMappingIndex) {
973
+ const allEntities = this.entityOptions();
974
+ const currentMappings = this.academicYearMappingsArray.value;
975
+ // Get all selected entity IDs from other mappings (excluding current mapping)
976
+ const selectedEntityIds = currentMappings
977
+ .map((mapping, index) => {
978
+ if (index !== currentMappingIndex && mapping.acayrmp_entity_id_syen) {
979
+ return mapping.acayrmp_entity_id_syen;
980
+ }
981
+ return null;
982
+ })
983
+ .filter((id) => id !== null && id !== '');
984
+ // Check if all entities are selected
985
+ return allEntities.length > 0 && selectedEntityIds.length >= allEntities.length;
986
+ }
987
+ /**
988
+ * Check if all entities are already mapped (for disabling Add Entity Mapping button)
989
+ * @returns True if all entities are already mapped
990
+ */
991
+ isAllEntitiesMapped() {
992
+ const allEntities = this.entityOptions();
993
+ const currentMappings = this.academicYearMappingsArray.value;
994
+ // Get all selected entity IDs
995
+ const selectedEntityIds = currentMappings
996
+ .map((mapping) => {
997
+ if (mapping.acayrmp_entity_id_syen) {
998
+ return mapping.acayrmp_entity_id_syen;
999
+ }
1000
+ return null;
1001
+ })
1002
+ .filter((id) => id !== null && id !== '');
1003
+ // Check if all entities are selected
1004
+ return allEntities.length > 0 && selectedEntityIds.length >= allEntities.length;
1005
+ }
1006
+ /**
1007
+ * Cleanup when component is destroyed
1008
+ * This ensures that when the component is destroyed (e.g., tab closed),
1009
+ * all state is properly reset to prevent old data from persisting
1010
+ */
1011
+ ngOnDestroy() {
1012
+ console.log('🧹 AcademicYearCreateComponent: Cleaning up component state');
1013
+ // Reset all signals to their initial state
1014
+ this.activeTab.set('basic');
1015
+ this.loading.set(false);
1016
+ this.academicYearId.set('');
1017
+ this.isEditMode.set(false);
1018
+ this.originalMappings.set([]);
1019
+ this.entityOptions.set([]);
1020
+ // Reset form to initial state
1021
+ this.resetForm();
1022
+ console.log('🧹 AcademicYearCreateComponent: Component state cleaned up');
1023
+ }
1024
+ /**
1025
+ * Delete removed academic year mappings
1026
+ */
1027
+ deleteRemovedMappings() {
1028
+ const originalMappings = this.originalMappings();
1029
+ const currentMappings = this.getAcademicYearMappingsValue();
1030
+ // Find mappings that were removed (exist in original but not in current)
1031
+ const removedMappings = originalMappings.filter(originalMapping => {
1032
+ return !currentMappings.some(currentMapping => currentMapping._id === originalMapping._id && originalMapping._id);
1033
+ });
1034
+ console.log('🗑️ Mappings to delete:', removedMappings);
1035
+ if (removedMappings.length === 0) {
1036
+ return of([]);
1037
+ }
1038
+ // Create delete observables for each removed mapping
1039
+ const deleteObservables = removedMappings.map(mapping => {
1040
+ return this.academicYearService.deleteAcademicYearMapping({
1041
+ acayrmp_id: mapping._id || ''
1042
+ }).pipe(catchError(error => {
1043
+ console.error('❌ Error deleting mapping:', error);
1044
+ return of({ success: false, error, mappingId: mapping._id });
1045
+ }));
1046
+ });
1047
+ return forkJoin(deleteObservables);
1048
+ }
1049
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: AcademicYearCreateComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1050
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.7", type: AcademicYearCreateComponent, isStandalone: true, selector: "cide-core-academic-year-create", ngImport: i0, template: "<!-- \n ACADEMIC YEAR MASTER FORM\n \n Enterprise-Level Styling with Tailwind CSS\n Features: Responsive grids, proper typography, enhanced user experience\n-->\n\n<div class=\"tw-w-full tw-h-full\">\n <form class=\"tw-w-full tw-table tw-h-full tw-bg-transparent\" [formGroup]=\"academicYearForm\" [class.tw-opacity-60]=\"loading()\"\n (ngSubmit)=\"onSubmit()\">\n\n <!-- Simple Header Section -->\n <div class=\"tw-table-row tw-w-full tw-h-0\">\n <div class=\"tw-table-cell tw-w-full tw-px-6 tw-py-3 tw-border-b tw-border-gray-200 tw-bg-gray-50\">\n <div class=\"tw-flex tw-flex-col sm:tw-flex-row tw-justify-between tw-items-start sm:tw-items-center tw-space-y-3 sm:tw-space-y-0\">\n \n <!-- Title -->\n <div class=\"tw-flex tw-items-center tw-space-x-2\">\n <cide-ele-icon class=\"tw-text-blue-600 tw-w-5 tw-h-5\">school</cide-ele-icon>\n <h5 class=\"tw-text-base tw-font-medium tw-text-gray-900 tw-m-0\">\n {{ isEditMode() ? 'Edit Academic Year' : 'Create Academic Year' }}\n </h5>\n </div>\n\n <!-- Actions -->\n <div class=\"tw-flex tw-flex-col sm:tw-flex-row tw-items-start sm:tw-items-center tw-space-y-3 sm:tw-space-y-0 sm:tw-space-x-3\">\n <!-- Back button or other actions can be added here if needed -->\n </div>\n </div>\n </div>\n </div>\n\n <!-- Tab Navigation -->\n <div class=\"tw-table-row tw-h-0\">\n <div class=\"tw-table-cell tw-w-full tw-px-2 tw-py-0\">\n <cide-ele-tab [tabs]=\"academicYearTabs()\" [activeTabId]=\"activeTab()\" size=\"md\" variant=\"default\"\n (tabChange)=\"onTabChange($event)\">\n </cide-ele-tab>\n </div>\n </div>\n\n <!-- Tab Content -->\n <div class=\"tw-table-row\">\n <div class=\"tw-table-cell tw-w-full tw-px-6 tw-py-6\">\n <div class=\"tw-transition-opacity tw-duration-300\" [class.tw-opacity-60]=\"loading()\">\n @switch (activeTab()) {\n\n @case ('basic') {\n <!-- Basic Academic Year Information -->\n <div class=\"tw-space-y-6\">\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-6\">\n <cide-ele-input label=\"Academic Year Code *\" formControlName=\"acayr_code\"\n placeholder=\"e.g., AY2024-25\" size=\"md\" leadingIcon=\"code\">\n </cide-ele-input>\n\n <cide-ele-input label=\"Academic Year Name *\" formControlName=\"acayr_name\"\n placeholder=\"e.g., Academic Year 2024-2025\" size=\"md\" leadingIcon=\"school\">\n </cide-ele-input>\n </div>\n\n <div>\n <cide-ele-textarea label=\"Description\" formControlName=\"acayr_description\"\n placeholder=\"Enter detailed description of the academic year...\"\n rows=\"3\" size=\"md\">\n </cide-ele-textarea>\n </div>\n\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-6\">\n <cide-ele-input label=\"From Date *\" formControlName=\"acayr_from_date\" type=\"date\" size=\"md\"\n leadingIcon=\"calendar_today\" id=\"acayr_from_date\">\n </cide-ele-input>\n\n <cide-ele-input label=\"To Date *\" formControlName=\"acayr_to_date\" type=\"date\" size=\"md\"\n leadingIcon=\"calendar_today\" id=\"acayr_to_date\">\n </cide-ele-input>\n </div>\n\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-3 tw-gap-6\">\n <div class=\"tw-flex tw-items-center tw-gap-3 tw-p-4 tw-bg-gray-50 tw-rounded-lg tw-border tw-border-gray-200\">\n <cide-ele-input formControlName=\"acayr_isactive\" type=\"checkbox\" size=\"md\">\n </cide-ele-input>\n <div class=\"tw-flex tw-flex-col\">\n <span class=\"tw-text-sm tw-font-medium tw-text-gray-700\">Active</span>\n <span class=\"tw-text-xs tw-text-gray-500\">Enable/disable this academic year</span>\n </div>\n </div>\n\n <div class=\"tw-flex tw-items-center tw-gap-3 tw-p-4 tw-bg-gray-50 tw-rounded-lg tw-border tw-border-gray-200\">\n <cide-ele-input formControlName=\"acayr_iscurrent\" type=\"checkbox\" size=\"md\">\n </cide-ele-input>\n <div class=\"tw-flex tw-flex-col\">\n <span class=\"tw-text-sm tw-font-medium tw-text-gray-700\">Current</span>\n <span class=\"tw-text-xs tw-text-gray-500\">Mark as current academic year</span>\n </div>\n </div>\n\n <div class=\"tw-flex tw-items-center tw-gap-3 tw-p-4 tw-bg-gray-50 tw-rounded-lg tw-border tw-border-gray-200\">\n <cide-ele-input formControlName=\"acayr_islocked\" type=\"checkbox\" size=\"md\">\n </cide-ele-input>\n <div class=\"tw-flex tw-flex-col\">\n <span class=\"tw-text-sm tw-font-medium tw-text-gray-700\">Locked</span>\n <span class=\"tw-text-xs tw-text-gray-500\">Prevent modifications</span>\n </div>\n </div>\n </div>\n </div>\n }\n\n @case ('mapping') {\n <!-- Academic Year Mapping Configuration -->\n <div class=\"tw-bg-gradient-to-r tw-from-blue-50 tw-to-indigo-50 tw-border tw-border-blue-200 tw-rounded-xl tw-p-6\">\n <div class=\"tw-flex tw-items-center tw-justify-between tw-mb-6\">\n <div class=\"tw-flex tw-items-center tw-gap-3\">\n <div class=\"tw-bg-blue-100 tw-p-2 tw-rounded-lg\">\n <cide-ele-icon class=\"tw-text-blue-600 tw-w-6 tw-h-6\">link</cide-ele-icon>\n </div>\n <div>\n <h6 class=\"tw-text-lg tw-font-semibold tw-text-blue-900 tw-m-0\">Academic Year Mapping</h6>\n <p class=\"tw-text-sm tw-text-blue-600 tw-m-0\">Configure entity mappings for this academic year</p>\n </div>\n </div>\n <button cideEleButton type=\"button\" variant=\"primary\" size=\"md\" leftIcon=\"add\"\n (click)=\"addAcademicYearMapping()\"\n class=\"tw-shadow-md hover:tw-shadow-lg tw-transition-shadow\">\n Add New Mapping\n </button>\n </div>\n \n @if (academicYearMappingsArray.length === 0) {\n <div class=\"tw-text-center tw-py-12 tw-text-gray-500\">\n <div class=\"tw-bg-white tw-p-4 tw-rounded-full tw-w-16 tw-h-16 tw-mx-auto tw-mb-4 tw-flex tw-items-center tw-justify-center\">\n <cide-ele-icon class=\"tw-w-8 tw-h-8 tw-text-gray-400\">link</cide-ele-icon>\n </div>\n <h6 class=\"tw-text-base tw-font-medium tw-text-gray-600 tw-mb-2\">No Mappings Yet</h6>\n <p class=\"tw-text-sm tw-text-gray-500\">Click \"Add New Mapping\" to start configuring entity relationships for this academic year.</p>\n </div>\n } @else {\n <div class=\"tw-space-y-4\" formArrayName=\"acayr_academic_year_mappings\">\n @for (mapping of academicYearMappingsArray.controls; track $index) {\n <div class=\"tw-bg-white tw-rounded-xl tw-border tw-border-gray-200 tw-shadow-sm hover:tw-shadow-md tw-transition-shadow tw-p-6\">\n <div class=\"tw-flex tw-items-start tw-justify-between tw-mb-4\">\n <div class=\"tw-flex tw-items-center tw-gap-2\">\n <div class=\"tw-bg-blue-100 tw-p-2 tw-rounded-lg\">\n <cide-ele-icon class=\"tw-text-blue-600 tw-w-5 tw-h-5\">settings</cide-ele-icon>\n </div>\n <h6 class=\"tw-text-sm tw-font-semibold tw-text-gray-900\">Mapping #{{ $index + 1 }}</h6>\n </div>\n <button cideEleButton type=\"button\" variant=\"danger\" size=\"sm\" leftIcon=\"delete\"\n (click)=\"removeAcademicYearMapping($index)\"\n class=\"tw-opacity-80 hover:tw-opacity-100 tw-transition-opacity\">\n Remove\n </button>\n </div>\n \n <div class=\"tw-grid tw-grid-cols-1 lg:tw-grid-cols-2 tw-gap-4\" [formGroupName]=\"$index\">\n <!-- Hidden Academic Year ID field (internal use only) -->\n <input type=\"hidden\" formControlName=\"acayrmp_academic_year_id_acayr\">\n \n <!-- Entity Selection -->\n <div class=\"tw-space-y-2\">\n <label class=\"tw-text-sm tw-font-medium tw-text-gray-700\">Select Entity *</label>\n <cide-ele-select \n [options]=\"entityOptions()\"\n formControlName=\"acayrmp_entity_id_syen\"\n placeholder=\"Choose entity for this mapping\" \n size=\"md\"\n valueKey=\"_id\"\n labelKey=\"syen_name\"\n class=\"tw-min-w-full\"\n (change)=\"onMappingEntityChange($event, $index)\">\n </cide-ele-select>\n </div>\n \n <!-- Status Controls -->\n <div class=\"tw-space-y-2\">\n <div class=\"tw-grid tw-grid-cols-1 tw-gap-3\">\n <div class=\"tw-flex tw-items-center tw-gap-2 tw-p-3 tw-bg-gray-50 tw-rounded-lg tw-border tw-border-gray-200\">\n <cide-ele-input \n formControlName=\"acayrmp_islocked\" \n type=\"checkbox\" \n size=\"sm\">\n </cide-ele-input>\n <div class=\"tw-flex tw-flex-col\">\n <span class=\"tw-text-sm tw-font-medium tw-text-gray-700\">Locked</span>\n <span class=\"tw-text-xs tw-text-gray-500\">Prevent modifications</span>\n </div>\n </div>\n \n <div class=\"tw-flex tw-items-center tw-gap-2 tw-p-3 tw-bg-gray-50 tw-rounded-lg tw-border tw-border-gray-200\">\n <cide-ele-input \n formControlName=\"acayrmp_iscurrent\" \n type=\"checkbox\" \n size=\"sm\">\n </cide-ele-input>\n <div class=\"tw-flex tw-flex-col\">\n <span class=\"tw-text-sm tw-font-medium tw-text-gray-700\">Current</span>\n <span class=\"tw-text-xs tw-text-gray-500\">Mark as current mapping</span>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n }\n </div>\n }\n\n <!-- Mapping Validation Messages -->\n @if (academicYearMappingsArray.length > 0 && !isMappingsArrayValid()) {\n <div class=\"tw-mt-4 tw-p-4 tw-bg-yellow-50 tw-border tw-border-yellow-200 tw-rounded-lg\">\n <div class=\"tw-flex tw-items-center tw-gap-2\">\n <cide-ele-icon variant=\"warning\" size=\"sm\">warning</cide-ele-icon>\n <span class=\"tw-text-sm tw-font-medium tw-text-yellow-800\">\n Please ensure all mappings have required fields filled in.\n </span>\n </div>\n </div>\n }\n </div>\n }\n }\n </div>\n </div>\n </div>\n\n <!-- Form Actions -->\n <div class=\"tw-table-row tw-h-0\">\n <div class=\"tw-table-cell tw-w-full tw-px-6 tw-py-2 tw-bg-gray-50 tw-border-t tw-border-gray-200\">\n <div class=\"tw-flex tw-justify-between tw-items-center tw-gap-4\">\n <!-- Form Validation Errors -->\n <cide-form-field-error [formGroup]=\"academicYearForm\"></cide-form-field-error>\n \n <!-- Action Buttons -->\n <div class=\"tw-flex tw-justify-end tw-gap-4\">\n <button cideEleButton type=\"button\" variant=\"secondary\" (click)=\"resetForm()\" leftIcon=\"refresh\"\n [disabled]=\"loading()\">\n Reset Form\n </button>\n\n <button cideEleButton type=\"button\" variant=\"secondary\" (click)=\"cancelForm()\" leftIcon=\"close\"\n [disabled]=\"loading()\">\n Cancel\n </button>\n\n <button cideEleButton type=\"submit\" variant=\"primary\" [disabled]=\"loading() || academicYearForm.invalid\"\n [loading]=\"loading()\" leftIcon=\"save\">\n {{ isEditMode() ? 'Update Academic Year' : 'Create Academic Year' }}\n </button>\n </div>\n </div>\n </div>\n </div>\n </form>\n </div>", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i1.FormGroupName, selector: "[formGroupName]", inputs: ["formGroupName"] }, { kind: "directive", type: i1.FormArrayName, selector: "[formArrayName]", inputs: ["formArrayName"] }, { kind: "component", type: CideInputComponent, selector: "cide-ele-input", inputs: ["fill", "label", "labelHide", "disabled", "clearInput", "labelPlacement", "labelDir", "placeholder", "leadingIcon", "trailingIcon", "helperText", "helperTextCollapse", "hideHelperAndErrorText", "errorText", "maxlength", "minlength", "required", "autocapitalize", "autocomplete", "type", "width", "id", "ngModel", "option", "min", "max", "size"], outputs: ["ngModelChange"] }, { kind: "component", type: CideTextareaComponent, selector: "cide-ele-textarea", inputs: ["label", "labelHide", "placeholder", "helperText", "errorText", "required", "disabled", "minlength", "maxlength", "rows", "id", "ngModel", "size", "fill", "labelPlacement", "labelDir", "leadingIcon", "trailingIcon", "clearInput"], outputs: ["ngModelChange"] }, { kind: "component", type: CideEleButtonComponent, selector: "button[cideEleButton], a[cideEleButton]", inputs: ["label", "variant", "size", "type", "shape", "elevation", "disabled", "id", "loading", "fullWidth", "leftIcon", "rightIcon", "customClass", "tooltip", "ariaLabel", "testId", "routerLink", "routerExtras", "preventDoubleClick", "animated"], outputs: ["btnClick", "doubleClick"] }, { kind: "component", type: CideEleTabComponent, selector: "cide-ele-tab", inputs: ["tabs", "activeTabId", "size", "variant", "fullWidth", "disabled"], outputs: ["tabChange"] }, { kind: "component", type: CideIconComponent, selector: "cide-ele-icon", inputs: ["size", "type", "toolTip"] }, { kind: "component", type: CideSelectComponent, selector: "cide-ele-select", inputs: ["label", "labelHide", "placeholder", "helperText", "errorText", "required", "disabled", "id", "ngModel", "size", "fill", "labelPlacement", "labelDir", "leadingIcon", "trailingIcon", "clearInput", "options", "multiple", "searchable", "showSearchInput", "loading", "valueKey", "labelKey"], outputs: ["ngModelChange", "change", "searchChange"] }, { kind: "component", type: CideFormFieldErrorComponent, selector: "cide-form-field-error", inputs: ["control", "formGroup", "fieldName", "customMessages"] }] });
1051
+ }
1052
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: AcademicYearCreateComponent, decorators: [{
1053
+ type: Component,
1054
+ args: [{ selector: 'cide-core-academic-year-create', standalone: true, imports: [
1055
+ CommonModule,
1056
+ ReactiveFormsModule,
1057
+ CideInputComponent,
1058
+ CideTextareaComponent,
1059
+ CideEleButtonComponent,
1060
+ CideEleTabComponent,
1061
+ CideIconComponent,
1062
+ CideSelectComponent,
1063
+ CideFormFieldErrorComponent
1064
+ ], template: "<!-- \n ACADEMIC YEAR MASTER FORM\n \n Enterprise-Level Styling with Tailwind CSS\n Features: Responsive grids, proper typography, enhanced user experience\n-->\n\n<div class=\"tw-w-full tw-h-full\">\n <form class=\"tw-w-full tw-table tw-h-full tw-bg-transparent\" [formGroup]=\"academicYearForm\" [class.tw-opacity-60]=\"loading()\"\n (ngSubmit)=\"onSubmit()\">\n\n <!-- Simple Header Section -->\n <div class=\"tw-table-row tw-w-full tw-h-0\">\n <div class=\"tw-table-cell tw-w-full tw-px-6 tw-py-3 tw-border-b tw-border-gray-200 tw-bg-gray-50\">\n <div class=\"tw-flex tw-flex-col sm:tw-flex-row tw-justify-between tw-items-start sm:tw-items-center tw-space-y-3 sm:tw-space-y-0\">\n \n <!-- Title -->\n <div class=\"tw-flex tw-items-center tw-space-x-2\">\n <cide-ele-icon class=\"tw-text-blue-600 tw-w-5 tw-h-5\">school</cide-ele-icon>\n <h5 class=\"tw-text-base tw-font-medium tw-text-gray-900 tw-m-0\">\n {{ isEditMode() ? 'Edit Academic Year' : 'Create Academic Year' }}\n </h5>\n </div>\n\n <!-- Actions -->\n <div class=\"tw-flex tw-flex-col sm:tw-flex-row tw-items-start sm:tw-items-center tw-space-y-3 sm:tw-space-y-0 sm:tw-space-x-3\">\n <!-- Back button or other actions can be added here if needed -->\n </div>\n </div>\n </div>\n </div>\n\n <!-- Tab Navigation -->\n <div class=\"tw-table-row tw-h-0\">\n <div class=\"tw-table-cell tw-w-full tw-px-2 tw-py-0\">\n <cide-ele-tab [tabs]=\"academicYearTabs()\" [activeTabId]=\"activeTab()\" size=\"md\" variant=\"default\"\n (tabChange)=\"onTabChange($event)\">\n </cide-ele-tab>\n </div>\n </div>\n\n <!-- Tab Content -->\n <div class=\"tw-table-row\">\n <div class=\"tw-table-cell tw-w-full tw-px-6 tw-py-6\">\n <div class=\"tw-transition-opacity tw-duration-300\" [class.tw-opacity-60]=\"loading()\">\n @switch (activeTab()) {\n\n @case ('basic') {\n <!-- Basic Academic Year Information -->\n <div class=\"tw-space-y-6\">\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-6\">\n <cide-ele-input label=\"Academic Year Code *\" formControlName=\"acayr_code\"\n placeholder=\"e.g., AY2024-25\" size=\"md\" leadingIcon=\"code\">\n </cide-ele-input>\n\n <cide-ele-input label=\"Academic Year Name *\" formControlName=\"acayr_name\"\n placeholder=\"e.g., Academic Year 2024-2025\" size=\"md\" leadingIcon=\"school\">\n </cide-ele-input>\n </div>\n\n <div>\n <cide-ele-textarea label=\"Description\" formControlName=\"acayr_description\"\n placeholder=\"Enter detailed description of the academic year...\"\n rows=\"3\" size=\"md\">\n </cide-ele-textarea>\n </div>\n\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-6\">\n <cide-ele-input label=\"From Date *\" formControlName=\"acayr_from_date\" type=\"date\" size=\"md\"\n leadingIcon=\"calendar_today\" id=\"acayr_from_date\">\n </cide-ele-input>\n\n <cide-ele-input label=\"To Date *\" formControlName=\"acayr_to_date\" type=\"date\" size=\"md\"\n leadingIcon=\"calendar_today\" id=\"acayr_to_date\">\n </cide-ele-input>\n </div>\n\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-3 tw-gap-6\">\n <div class=\"tw-flex tw-items-center tw-gap-3 tw-p-4 tw-bg-gray-50 tw-rounded-lg tw-border tw-border-gray-200\">\n <cide-ele-input formControlName=\"acayr_isactive\" type=\"checkbox\" size=\"md\">\n </cide-ele-input>\n <div class=\"tw-flex tw-flex-col\">\n <span class=\"tw-text-sm tw-font-medium tw-text-gray-700\">Active</span>\n <span class=\"tw-text-xs tw-text-gray-500\">Enable/disable this academic year</span>\n </div>\n </div>\n\n <div class=\"tw-flex tw-items-center tw-gap-3 tw-p-4 tw-bg-gray-50 tw-rounded-lg tw-border tw-border-gray-200\">\n <cide-ele-input formControlName=\"acayr_iscurrent\" type=\"checkbox\" size=\"md\">\n </cide-ele-input>\n <div class=\"tw-flex tw-flex-col\">\n <span class=\"tw-text-sm tw-font-medium tw-text-gray-700\">Current</span>\n <span class=\"tw-text-xs tw-text-gray-500\">Mark as current academic year</span>\n </div>\n </div>\n\n <div class=\"tw-flex tw-items-center tw-gap-3 tw-p-4 tw-bg-gray-50 tw-rounded-lg tw-border tw-border-gray-200\">\n <cide-ele-input formControlName=\"acayr_islocked\" type=\"checkbox\" size=\"md\">\n </cide-ele-input>\n <div class=\"tw-flex tw-flex-col\">\n <span class=\"tw-text-sm tw-font-medium tw-text-gray-700\">Locked</span>\n <span class=\"tw-text-xs tw-text-gray-500\">Prevent modifications</span>\n </div>\n </div>\n </div>\n </div>\n }\n\n @case ('mapping') {\n <!-- Academic Year Mapping Configuration -->\n <div class=\"tw-bg-gradient-to-r tw-from-blue-50 tw-to-indigo-50 tw-border tw-border-blue-200 tw-rounded-xl tw-p-6\">\n <div class=\"tw-flex tw-items-center tw-justify-between tw-mb-6\">\n <div class=\"tw-flex tw-items-center tw-gap-3\">\n <div class=\"tw-bg-blue-100 tw-p-2 tw-rounded-lg\">\n <cide-ele-icon class=\"tw-text-blue-600 tw-w-6 tw-h-6\">link</cide-ele-icon>\n </div>\n <div>\n <h6 class=\"tw-text-lg tw-font-semibold tw-text-blue-900 tw-m-0\">Academic Year Mapping</h6>\n <p class=\"tw-text-sm tw-text-blue-600 tw-m-0\">Configure entity mappings for this academic year</p>\n </div>\n </div>\n <button cideEleButton type=\"button\" variant=\"primary\" size=\"md\" leftIcon=\"add\"\n (click)=\"addAcademicYearMapping()\"\n class=\"tw-shadow-md hover:tw-shadow-lg tw-transition-shadow\">\n Add New Mapping\n </button>\n </div>\n \n @if (academicYearMappingsArray.length === 0) {\n <div class=\"tw-text-center tw-py-12 tw-text-gray-500\">\n <div class=\"tw-bg-white tw-p-4 tw-rounded-full tw-w-16 tw-h-16 tw-mx-auto tw-mb-4 tw-flex tw-items-center tw-justify-center\">\n <cide-ele-icon class=\"tw-w-8 tw-h-8 tw-text-gray-400\">link</cide-ele-icon>\n </div>\n <h6 class=\"tw-text-base tw-font-medium tw-text-gray-600 tw-mb-2\">No Mappings Yet</h6>\n <p class=\"tw-text-sm tw-text-gray-500\">Click \"Add New Mapping\" to start configuring entity relationships for this academic year.</p>\n </div>\n } @else {\n <div class=\"tw-space-y-4\" formArrayName=\"acayr_academic_year_mappings\">\n @for (mapping of academicYearMappingsArray.controls; track $index) {\n <div class=\"tw-bg-white tw-rounded-xl tw-border tw-border-gray-200 tw-shadow-sm hover:tw-shadow-md tw-transition-shadow tw-p-6\">\n <div class=\"tw-flex tw-items-start tw-justify-between tw-mb-4\">\n <div class=\"tw-flex tw-items-center tw-gap-2\">\n <div class=\"tw-bg-blue-100 tw-p-2 tw-rounded-lg\">\n <cide-ele-icon class=\"tw-text-blue-600 tw-w-5 tw-h-5\">settings</cide-ele-icon>\n </div>\n <h6 class=\"tw-text-sm tw-font-semibold tw-text-gray-900\">Mapping #{{ $index + 1 }}</h6>\n </div>\n <button cideEleButton type=\"button\" variant=\"danger\" size=\"sm\" leftIcon=\"delete\"\n (click)=\"removeAcademicYearMapping($index)\"\n class=\"tw-opacity-80 hover:tw-opacity-100 tw-transition-opacity\">\n Remove\n </button>\n </div>\n \n <div class=\"tw-grid tw-grid-cols-1 lg:tw-grid-cols-2 tw-gap-4\" [formGroupName]=\"$index\">\n <!-- Hidden Academic Year ID field (internal use only) -->\n <input type=\"hidden\" formControlName=\"acayrmp_academic_year_id_acayr\">\n \n <!-- Entity Selection -->\n <div class=\"tw-space-y-2\">\n <label class=\"tw-text-sm tw-font-medium tw-text-gray-700\">Select Entity *</label>\n <cide-ele-select \n [options]=\"entityOptions()\"\n formControlName=\"acayrmp_entity_id_syen\"\n placeholder=\"Choose entity for this mapping\" \n size=\"md\"\n valueKey=\"_id\"\n labelKey=\"syen_name\"\n class=\"tw-min-w-full\"\n (change)=\"onMappingEntityChange($event, $index)\">\n </cide-ele-select>\n </div>\n \n <!-- Status Controls -->\n <div class=\"tw-space-y-2\">\n <div class=\"tw-grid tw-grid-cols-1 tw-gap-3\">\n <div class=\"tw-flex tw-items-center tw-gap-2 tw-p-3 tw-bg-gray-50 tw-rounded-lg tw-border tw-border-gray-200\">\n <cide-ele-input \n formControlName=\"acayrmp_islocked\" \n type=\"checkbox\" \n size=\"sm\">\n </cide-ele-input>\n <div class=\"tw-flex tw-flex-col\">\n <span class=\"tw-text-sm tw-font-medium tw-text-gray-700\">Locked</span>\n <span class=\"tw-text-xs tw-text-gray-500\">Prevent modifications</span>\n </div>\n </div>\n \n <div class=\"tw-flex tw-items-center tw-gap-2 tw-p-3 tw-bg-gray-50 tw-rounded-lg tw-border tw-border-gray-200\">\n <cide-ele-input \n formControlName=\"acayrmp_iscurrent\" \n type=\"checkbox\" \n size=\"sm\">\n </cide-ele-input>\n <div class=\"tw-flex tw-flex-col\">\n <span class=\"tw-text-sm tw-font-medium tw-text-gray-700\">Current</span>\n <span class=\"tw-text-xs tw-text-gray-500\">Mark as current mapping</span>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n }\n </div>\n }\n\n <!-- Mapping Validation Messages -->\n @if (academicYearMappingsArray.length > 0 && !isMappingsArrayValid()) {\n <div class=\"tw-mt-4 tw-p-4 tw-bg-yellow-50 tw-border tw-border-yellow-200 tw-rounded-lg\">\n <div class=\"tw-flex tw-items-center tw-gap-2\">\n <cide-ele-icon variant=\"warning\" size=\"sm\">warning</cide-ele-icon>\n <span class=\"tw-text-sm tw-font-medium tw-text-yellow-800\">\n Please ensure all mappings have required fields filled in.\n </span>\n </div>\n </div>\n }\n </div>\n }\n }\n </div>\n </div>\n </div>\n\n <!-- Form Actions -->\n <div class=\"tw-table-row tw-h-0\">\n <div class=\"tw-table-cell tw-w-full tw-px-6 tw-py-2 tw-bg-gray-50 tw-border-t tw-border-gray-200\">\n <div class=\"tw-flex tw-justify-between tw-items-center tw-gap-4\">\n <!-- Form Validation Errors -->\n <cide-form-field-error [formGroup]=\"academicYearForm\"></cide-form-field-error>\n \n <!-- Action Buttons -->\n <div class=\"tw-flex tw-justify-end tw-gap-4\">\n <button cideEleButton type=\"button\" variant=\"secondary\" (click)=\"resetForm()\" leftIcon=\"refresh\"\n [disabled]=\"loading()\">\n Reset Form\n </button>\n\n <button cideEleButton type=\"button\" variant=\"secondary\" (click)=\"cancelForm()\" leftIcon=\"close\"\n [disabled]=\"loading()\">\n Cancel\n </button>\n\n <button cideEleButton type=\"submit\" variant=\"primary\" [disabled]=\"loading() || academicYearForm.invalid\"\n [loading]=\"loading()\" leftIcon=\"save\">\n {{ isEditMode() ? 'Update Academic Year' : 'Create Academic Year' }}\n </button>\n </div>\n </div>\n </div>\n </div>\n </form>\n </div>" }]
1065
+ }], ctorParameters: () => [] });
1066
+
1067
+ var academicYearCreate_component = /*#__PURE__*/Object.freeze({
1068
+ __proto__: null,
1069
+ AcademicYearCreateComponent: AcademicYearCreateComponent
1070
+ });
1071
+
1072
+ class AcademicYearListComponent {
1073
+ // Modern Angular 20+ dependency injection using inject()
1074
+ destroyRef = inject(DestroyRef);
1075
+ academicYearService = inject(CideLytAcademicYearService);
1076
+ router = inject(Router);
1077
+ appState = inject(AppStateHelperService);
1078
+ confirmationService = inject(ConfirmationService);
1079
+ notificationService = inject(NotificationService);
1080
+ // Modern ViewChild signals for template renderers (Angular 20 approach)
1081
+ academicYearDetailsRendererTemplate = viewChild.required('academicYearDetailsRendererTemplate');
1082
+ dateRangeRendererTemplate = viewChild.required('dateRangeRendererTemplate');
1083
+ statusRendererTemplate = viewChild.required('statusRendererTemplate');
1084
+ actionsDropdownRendererTemplate = viewChild.required('actionsDropdownRendererTemplate');
1085
+ // Modern Angular 20+ state management using signals with proper typing
1086
+ academicYears = signal([], ...(ngDevMode ? [{ debugName: "academicYears" }] : []));
1087
+ loading = signal(false, ...(ngDevMode ? [{ debugName: "loading" }] : []));
1088
+ error = signal(null, ...(ngDevMode ? [{ debugName: "error" }] : []));
1089
+ // Server-side pagination state using signals
1090
+ currentPage = signal(1, ...(ngDevMode ? [{ debugName: "currentPage" }] : []));
1091
+ pageSize = signal(10, ...(ngDevMode ? [{ debugName: "pageSize" }] : []));
1092
+ totalItems = signal(0, ...(ngDevMode ? [{ debugName: "totalItems" }] : []));
1093
+ totalPages = signal(0, ...(ngDevMode ? [{ debugName: "totalPages" }] : []));
1094
+ // Server-side search state using signals
1095
+ searchQuery = signal('', ...(ngDevMode ? [{ debugName: "searchQuery" }] : []));
1096
+ // Server-side sorting state using signals
1097
+ sortColumn = signal('acayr_name', ...(ngDevMode ? [{ debugName: "sortColumn" }] : []));
1098
+ sortDirection = signal('asc', ...(ngDevMode ? [{ debugName: "sortDirection" }] : []));
1099
+ // Server-side filtering state using signals
1100
+ selectedStatusFilter = signal('', ...(ngDevMode ? [{ debugName: "selectedStatusFilter" }] : []));
1101
+ // Filter options using computed signal for better performance
1102
+ statusFilterOptions = computed(() => [
1103
+ { value: '', label: 'All Status' },
1104
+ { value: 'active', label: 'Active Years' },
1105
+ { value: 'inactive', label: 'Inactive Years' },
1106
+ { value: 'current', label: 'Current Year' },
1107
+ { value: 'locked', label: 'Locked Years' }
1108
+ ], ...(ngDevMode ? [{ debugName: "statusFilterOptions" }] : []));
1109
+ // Modern Angular 20+ grid configuration using computed signal with proper typing
1110
+ gridConfig = computed(() => ({
1111
+ id: 'academic-year-list-grid',
1112
+ columns: [
1113
+ {
1114
+ key: 'acayr_code',
1115
+ header: 'Academic Year Code',
1116
+ type: 'text',
1117
+ width: '140px',
1118
+ truncate: true,
1119
+ align: 'left',
1120
+ sortable: true
1121
+ },
1122
+ {
1123
+ key: 'details',
1124
+ header: 'Academic Year Details',
1125
+ type: 'custom',
1126
+ width: 'auto',
1127
+ truncate: true,
1128
+ align: 'left',
1129
+ renderer: 'academicYearDetailsRenderer',
1130
+ sortable: true
1131
+ },
1132
+ {
1133
+ key: 'date_range',
1134
+ header: 'Date Range',
1135
+ type: 'custom',
1136
+ width: '200px',
1137
+ truncate: false,
1138
+ align: 'left',
1139
+ renderer: 'dateRangeRenderer',
1140
+ sortable: true
1141
+ },
1142
+ {
1143
+ key: 'acayr_isactive',
1144
+ header: 'Status',
1145
+ type: 'custom',
1146
+ width: '140px',
1147
+ truncate: false,
1148
+ align: 'center',
1149
+ renderer: 'statusRenderer'
1150
+ },
1151
+ {
1152
+ key: 'actions',
1153
+ header: 'Actions',
1154
+ type: 'custom',
1155
+ width: '80px',
1156
+ truncate: false,
1157
+ align: 'center',
1158
+ renderer: 'actionsDropdownRenderer'
1159
+ }
1160
+ ],
1161
+ data: this.academicYears(),
1162
+ trackBy: '_id',
1163
+ pagination: {
1164
+ enabled: true,
1165
+ pageSize: this.pageSize(),
1166
+ pageSizeOptions: [10, 25, 50, 100],
1167
+ showQuickJump: true,
1168
+ showPageInfo: true,
1169
+ showRefresh: true
1170
+ },
1171
+ search: {
1172
+ enabled: true,
1173
+ placeholder: 'Search by code, name, or description...',
1174
+ searchableColumns: ['acayr_code', 'acayr_name', 'acayr_description'],
1175
+ debounceMs: 300,
1176
+ showClearButton: true
1177
+ },
1178
+ loading: {
1179
+ useDefer: true,
1180
+ skeletonRows: 5,
1181
+ showOverlay: this.loading()
1182
+ },
1183
+ scroll: {
1184
+ enabled: true,
1185
+ maxHeight: '',
1186
+ minHeight: '',
1187
+ stickyHeader: true,
1188
+ virtualScroll: false,
1189
+ rowHeight: 50
1190
+ },
1191
+ export: {
1192
+ enabled: true,
1193
+ formats: ['csv', 'excel', 'pdf'],
1194
+ filename: 'academic-years',
1195
+ includeHeaders: true
1196
+ },
1197
+ responsive: true,
1198
+ striped: false,
1199
+ bordered: true,
1200
+ compact: false,
1201
+ tableClass: 'tw-table-fixed tw-w-full tw-rounded-none'
1202
+ }), ...(ngDevMode ? [{ debugName: "gridConfig" }] : []));
1203
+ ngOnInit() {
1204
+ console.log('🎓 Academic Year List Component initialized');
1205
+ this.loadAcademicYears();
1206
+ }
1207
+ ngOnDestroy() {
1208
+ // Cleanup if needed
1209
+ }
1210
+ /**
1211
+ * Load academic years from API
1212
+ */
1213
+ loadAcademicYears() {
1214
+ this.loading.set(true);
1215
+ this.error.set(null);
1216
+ const payload = {
1217
+ pageIndex: this.currentPage(),
1218
+ pageSize: this.pageSize(),
1219
+ query: this.searchQuery() || "",
1220
+ sort: {
1221
+ key: this.sortColumn(),
1222
+ order: this.sortDirection()
1223
+ }
1224
+ };
1225
+ this.academicYearService.getAcademicYearList(payload)
1226
+ .pipe(takeUntilDestroyed(this.destroyRef))
1227
+ .subscribe({
1228
+ next: (response) => {
1229
+ if (response?.success && response.data) {
1230
+ console.log('📚 Academic years loaded:', response.data);
1231
+ console.log('📊 Pagination info:', {
1232
+ total: response.total,
1233
+ pageIndex: response.pageIndex,
1234
+ pageSize: response.pageSize
1235
+ });
1236
+ this.academicYears.set(response.data);
1237
+ this.totalItems.set(response.total || 0);
1238
+ this.totalPages.set(Math.ceil((response.total || 0) / this.pageSize()));
1239
+ // Show success notification if data was loaded successfully
1240
+ if (response.data.length > 0) {
1241
+ this.notificationService.success(`Loaded ${response.data.length} academic year(s) successfully.`);
1242
+ }
1243
+ }
1244
+ else {
1245
+ console.warn('⚠️ No academic year data received');
1246
+ this.academicYears.set([]);
1247
+ this.totalItems.set(0);
1248
+ this.totalPages.set(0);
1249
+ this.notificationService.warning('No academic years found.');
1250
+ }
1251
+ this.loading.set(false);
1252
+ },
1253
+ error: (error) => {
1254
+ console.error('❌ Error loading academic years:', error);
1255
+ this.error.set('Failed to load academic years. Please try again.');
1256
+ this.academicYears.set([]);
1257
+ this.totalItems.set(0);
1258
+ this.totalPages.set(0);
1259
+ this.notificationService.error('Failed to load academic years. Please try again.');
1260
+ this.loading.set(false);
1261
+ }
1262
+ });
1263
+ }
1264
+ // Computed template renderers for grid
1265
+ templateRenderers = computed(() => ({
1266
+ academicYearDetailsRenderer: this.academicYearDetailsRendererTemplate(),
1267
+ dateRangeRenderer: this.dateRangeRendererTemplate(),
1268
+ statusRenderer: this.statusRendererTemplate(),
1269
+ actionsDropdownRenderer: this.actionsDropdownRendererTemplate()
1270
+ }), ...(ngDevMode ? [{ debugName: "templateRenderers" }] : []));
1271
+ /**
1272
+ * Handle grid events
1273
+ */
1274
+ onGridEvent(event) {
1275
+ switch (event.type) {
1276
+ case 'pageChange':
1277
+ if (event.data && typeof event.data === 'object' && 'pageIndex' in event.data && 'pageSize' in event.data) {
1278
+ this.currentPage.set(event.data['pageIndex']);
1279
+ this.pageSize.set(event.data['pageSize']);
1280
+ this.loadAcademicYears();
1281
+ }
1282
+ break;
1283
+ case 'search':
1284
+ this.searchQuery.set(event.data);
1285
+ this.currentPage.set(1);
1286
+ this.loadAcademicYears();
1287
+ break;
1288
+ case 'refresh':
1289
+ this.loadAcademicYears();
1290
+ break;
1291
+ case 'action':
1292
+ // Handle action events if needed
1293
+ console.log('Action event:', event);
1294
+ break;
1295
+ case 'rowClick':
1296
+ // Handle row click events if needed
1297
+ console.log('Row click event:', event);
1298
+ break;
1299
+ case 'sort':
1300
+ if (event.data && typeof event.data === 'object' && 'column' in event.data && 'direction' in event.data) {
1301
+ this.sortColumn.set(event.data['column']);
1302
+ this.sortDirection.set(event.data['direction']);
1303
+ this.currentPage.set(1); // Reset to first page when sorting
1304
+ this.loadAcademicYears();
1305
+ }
1306
+ break;
1307
+ case 'export':
1308
+ if (event.data && typeof event.data === 'string') {
1309
+ this.handleExport(event.data);
1310
+ }
1311
+ break;
1312
+ default:
1313
+ console.log('🔄 Unhandled grid event:', event.type);
1314
+ }
1315
+ }
1316
+ // Filter handlers
1317
+ onStatusFilterChange() {
1318
+ console.log('🔍 Status filter changed:', this.selectedStatusFilter());
1319
+ this.currentPage.set(1); // Reset to first page when filtering
1320
+ this.loadAcademicYears();
1321
+ }
1322
+ clearFilters() {
1323
+ console.log('🧹 Clearing filters');
1324
+ this.selectedStatusFilter.set('');
1325
+ this.searchQuery.set('');
1326
+ this.currentPage.set(1);
1327
+ this.loadAcademicYears();
1328
+ }
1329
+ // Academic Year actions with proper typing
1330
+ createAcademicYear() {
1331
+ console.log('➕ Navigating to create academic year');
1332
+ this.notificationService.info('Opening form to create a new academic year.');
1333
+ this.router.navigate(['/control-panel/academic_year/create']);
1334
+ }
1335
+ viewAcademicYear(academicYear) {
1336
+ console.log('👁️ Viewing academic year:', academicYear);
1337
+ this.notificationService.info(`Opening academic year "${academicYear.acayr_name}" for viewing.`);
1338
+ const queryParams = generateStringFromObject({ acayr_id: academicYear._id });
1339
+ this.router.navigate(['/control-panel/academic_year/view', queryParams]);
1340
+ }
1341
+ editAcademicYear(academicYear) {
1342
+ console.log('✏️ Editing academic year:', academicYear);
1343
+ // Check if the academic year is locked
1344
+ if (academicYear.acayr_islocked) {
1345
+ this.notificationService.error(`Cannot edit "${academicYear.acayr_name}" - This academic year is locked and cannot be modified. Please contact an administrator to unlock it first.`);
1346
+ return;
1347
+ }
1348
+ this.notificationService.info(`Opening academic year "${academicYear.acayr_name}" for editing.`);
1349
+ const queryParams = generateStringFromObject({ acayr_id: academicYear._id });
1350
+ this.router.navigate(['/control-panel/academic_year/edit', queryParams]);
1351
+ }
1352
+ /**
1353
+ * Get dropdown configuration
1354
+ */
1355
+ getDropdownConfig() {
1356
+ return {
1357
+ triggerIcon: 'more_vert',
1358
+ triggerSize: 'sm',
1359
+ // menuPosition: 'right' as const,
1360
+ // forcePosition: 'bottom' as const,
1361
+ // offsetX: 0,
1362
+ // offsetY: 1,
1363
+ // usePortal: true,
1364
+ // showArrow: false
1365
+ };
1366
+ }
1367
+ /**
1368
+ * Get action dropdown items
1369
+ */
1370
+ getActionDropdownItems(academicYear) {
1371
+ console.log('🔽 Generating dropdown items for:', academicYear.acayr_name);
1372
+ console.log('🔽 Academic year data:', {
1373
+ isCurrent: academicYear.acayr_iscurrent,
1374
+ isLocked: academicYear.acayr_islocked,
1375
+ isActive: academicYear.acayr_isactive
1376
+ });
1377
+ const items = [
1378
+ {
1379
+ id: 'view',
1380
+ label: 'View Details',
1381
+ icon: 'visibility',
1382
+ iconColor: 'tw-text-gray-400',
1383
+ textColor: 'tw-text-gray-700',
1384
+ hoverBgColor: 'hover:tw-bg-gray-100'
1385
+ },
1386
+ {
1387
+ id: 'edit',
1388
+ label: 'Edit',
1389
+ icon: 'edit',
1390
+ iconColor: academicYear?.acayr_islocked ? 'tw-text-gray-300' : 'tw-text-blue-400',
1391
+ textColor: academicYear?.acayr_islocked ? 'tw-text-gray-400' : 'tw-text-blue-600',
1392
+ hoverBgColor: academicYear?.acayr_islocked ? 'hover:tw-bg-gray-50' : 'hover:tw-bg-blue-50'
1393
+ },
1394
+ {
1395
+ id: 'toggle-status',
1396
+ label: academicYear.acayr_isactive ? 'Deactivate' : 'Activate',
1397
+ icon: academicYear.acayr_isactive ? 'toggle_off' : 'toggle_on',
1398
+ iconColor: academicYear?.acayr_islocked ? 'tw-text-gray-300' : 'tw-text-gray-400',
1399
+ textColor: academicYear?.acayr_islocked ? 'tw-text-gray-400' : 'tw-text-gray-700',
1400
+ hoverBgColor: academicYear?.acayr_islocked ? 'hover:tw-bg-gray-50' : 'hover:tw-bg-gray-100'
1401
+ }
1402
+ ];
1403
+ return items;
1404
+ }
1405
+ /**
1406
+ * Handle dropdown item click
1407
+ */
1408
+ onDropdownItemClick(item, academicYear) {
1409
+ console.log('🖱️ Dropdown item clicked:', item.id, 'for academic year:', academicYear.acayr_name);
1410
+ // Check if item is disabled
1411
+ if (item.disabled) {
1412
+ console.log('⚠️ Item is disabled, ignoring click');
1413
+ return;
1414
+ }
1415
+ switch (item.id) {
1416
+ case 'view':
1417
+ this.viewAcademicYear(academicYear);
1418
+ break;
1419
+ case 'edit':
1420
+ this.editAcademicYear(academicYear);
1421
+ break;
1422
+ case 'toggle-status':
1423
+ this.toggleAcademicYearStatus(academicYear);
1424
+ break;
1425
+ default:
1426
+ console.log('❓ Unknown dropdown item clicked:', item.id);
1427
+ }
1428
+ }
1429
+ /**
1430
+ * Toggle academic year status (active/inactive)
1431
+ */
1432
+ toggleAcademicYearStatus(academicYear) {
1433
+ console.log('🔄 Toggling academic year status:', academicYear);
1434
+ // Check if the academic year is locked
1435
+ if (academicYear.acayr_islocked) {
1436
+ this.notificationService.error(`Cannot ${academicYear.acayr_isactive ? 'deactivate' : 'activate'} "${academicYear.acayr_name}" - This academic year is locked and its status cannot be changed. Please contact an administrator to unlock it first.`);
1437
+ return;
1438
+ }
1439
+ const action = academicYear.acayr_isactive ? 'deactivate' : 'activate';
1440
+ const actionText = academicYear.acayr_isactive ? 'Deactivate' : 'Activate';
1441
+ // Show confirmation dialog
1442
+ console.log('🔔 Showing confirmation dialog for toggle status');
1443
+ this.confirmationService.ask({
1444
+ title: `${actionText} Academic Year`,
1445
+ message: `Are you sure you want to ${action} the academic year "${academicYear.acayr_name}"?${!academicYear.acayr_isactive ? '\n\nThis will also deactivate all associated mappings.' : ''}`,
1446
+ confirmText: actionText,
1447
+ cancelText: 'Cancel',
1448
+ type: academicYear.acayr_isactive ? 'warning' : 'info'
1449
+ }).then((confirmed) => {
1450
+ console.log('🔔 Confirmation dialog result:', confirmed);
1451
+ if (confirmed) {
1452
+ this.loading.set(true);
1453
+ // First toggle the academic year status
1454
+ console.log('🔄 Calling toggleAcademicYearStatus with ID:', academicYear._id);
1455
+ this.academicYearService.toggleAcademicYearStatus({ acayr_id: academicYear._id }).subscribe({
1456
+ next: (response) => {
1457
+ console.log('🔄 Toggle academic year status response:', response);
1458
+ if (response?.success) {
1459
+ console.log('✅ Academic year status toggled successfully');
1460
+ // If deactivating, also toggle status of all academic year mappings
1461
+ if (!academicYear.acayr_isactive) { // If we're deactivating (was active, now inactive)
1462
+ this.toggleAcademicYearMappingsStatus(academicYear._id || '', false);
1463
+ }
1464
+ else {
1465
+ // If activating, just reload the list
1466
+ this.notificationService.success(`Academic year "${academicYear.acayr_name}" has been activated successfully.`);
1467
+ this.loadAcademicYears();
1468
+ }
1469
+ }
1470
+ else {
1471
+ console.error('❌ Failed to toggle academic year status');
1472
+ this.notificationService.error(response?.message || 'Failed to toggle academic year status');
1473
+ this.loading.set(false);
1474
+ }
1475
+ },
1476
+ error: (error) => {
1477
+ console.error('❌ Error toggling academic year status:', error);
1478
+ console.error('❌ Error details:', {
1479
+ status: error.status,
1480
+ message: error.message,
1481
+ error: error.error
1482
+ });
1483
+ this.notificationService.error('Failed to toggle academic year status. Please try again.');
1484
+ this.loading.set(false);
1485
+ }
1486
+ });
1487
+ }
1488
+ });
1489
+ }
1490
+ /**
1491
+ * Toggle status of all academic year mappings for a specific academic year
1492
+ */
1493
+ toggleAcademicYearMappingsStatus(academicYearId, isActive) {
1494
+ console.log(`🔄 Toggling mappings status for academic year ${academicYearId} to ${isActive ? 'active' : 'inactive'}`);
1495
+ // Get all mappings for this academic year and toggle their status
1496
+ // For now, we'll reload the academic year data to get the mappings
1497
+ // In a real implementation, you might want to get mappings separately
1498
+ this.academicYearService.getAcademicYearById({ acayr_id: academicYearId }).subscribe({
1499
+ next: (response) => {
1500
+ if (response?.success && response.data && response.data.acayr_academic_year_mappings) {
1501
+ const mappings = response.data.acayr_academic_year_mappings;
1502
+ console.log('📋 Found mappings to toggle:', mappings);
1503
+ // Toggle each mapping's status
1504
+ const toggleObservables = mappings.map((mapping) => {
1505
+ return this.academicYearService.toggleAcademicYearMappingStatus({
1506
+ acayrmp_id: mapping._id
1507
+ }).pipe(catchError(error => {
1508
+ console.error('❌ Error toggling mapping status:', error);
1509
+ return of({ success: false, error, mappingId: mapping._id });
1510
+ }));
1511
+ });
1512
+ if (toggleObservables.length > 0) {
1513
+ forkJoin(toggleObservables).subscribe((results) => {
1514
+ console.log('✅ All mapping statuses toggled:', results);
1515
+ const resultsArray = results;
1516
+ const failedCount = resultsArray.filter((result) => !result.success).length;
1517
+ if (failedCount === 0) {
1518
+ this.notificationService.success(`Academic year and all ${resultsArray.length} associated mappings have been deactivated successfully.`);
1519
+ }
1520
+ else {
1521
+ this.notificationService.warning(`Academic year deactivated, but ${failedCount} out of ${resultsArray.length} mappings failed to update.`);
1522
+ }
1523
+ this.loadAcademicYears(); // Reload the list
1524
+ }, (error) => {
1525
+ console.error('❌ Error toggling mapping statuses:', error);
1526
+ this.notificationService.error('Academic year deactivated, but failed to update some mappings.');
1527
+ this.loadAcademicYears(); // Still reload the list
1528
+ });
1529
+ }
1530
+ else {
1531
+ this.notificationService.success('Academic year has been deactivated successfully.');
1532
+ this.loadAcademicYears(); // No mappings to toggle, just reload
1533
+ }
1534
+ }
1535
+ else {
1536
+ this.notificationService.success('Academic year has been deactivated successfully.');
1537
+ this.loadAcademicYears(); // No mappings found, just reload
1538
+ }
1539
+ },
1540
+ error: (error) => {
1541
+ console.error('❌ Error getting academic year mappings:', error);
1542
+ this.notificationService.error('Academic year deactivated, but failed to update mappings.');
1543
+ this.loadAcademicYears(); // Still reload the list
1544
+ }
1545
+ });
1546
+ }
1547
+ // Export handler
1548
+ handleExport(format) {
1549
+ console.log(`📤 Exporting academic years as ${format}`);
1550
+ const data = this.academicYears().map(item => ({
1551
+ 'Academic Year Code': item.acayr_code,
1552
+ 'Academic Year Name': item.acayr_name,
1553
+ 'Description': item.acayr_description,
1554
+ 'From Date': this.formatDate(item?.acayr_from_date || ""),
1555
+ 'To Date': this.formatDate(item?.acayr_to_date || ""),
1556
+ 'Duration': this.getDuration(item?.acayr_from_date || "", item?.acayr_to_date || ""),
1557
+ 'Status': this.getStatusText(item),
1558
+ 'Is Current': item.acayr_iscurrent ? 'Yes' : 'No',
1559
+ 'Is Active': item.acayr_isactive ? 'Yes' : 'No',
1560
+ 'Is Locked': item.acayr_islocked ? 'Yes' : 'No'
1561
+ }));
1562
+ // Create filename with timestamp
1563
+ const timestamp = new Date().toISOString().split('T')[0];
1564
+ const filename = `academic-years-${timestamp}`;
1565
+ switch (format.toLowerCase()) {
1566
+ case 'csv':
1567
+ this.exportToCSV(data, filename);
1568
+ break;
1569
+ case 'excel':
1570
+ this.exportToExcel(data, filename);
1571
+ break;
1572
+ case 'pdf':
1573
+ this.exportToPDF(data, filename);
1574
+ break;
1575
+ default:
1576
+ console.warn(`Unsupported export format: ${format}`);
1577
+ }
1578
+ }
1579
+ exportToCSV(data, filename) {
1580
+ const headers = Object.keys(data[0] || {});
1581
+ const csvContent = [
1582
+ headers.join(','),
1583
+ ...data.map(row => headers.map(header => `"${row[header] || ''}"`).join(','))
1584
+ ].join('\n');
1585
+ this.downloadFile(csvContent, `${filename}.csv`, 'text/csv');
1586
+ }
1587
+ exportToExcel(data, filename) {
1588
+ // For Excel export, you might want to use a library like xlsx
1589
+ // For now, we'll export as CSV with .xlsx extension
1590
+ this.exportToCSV(data, filename);
1591
+ }
1592
+ exportToPDF(data, filename) {
1593
+ // For PDF export, you might want to use a library like jsPDF
1594
+ // For now, we'll export as CSV
1595
+ this.exportToCSV(data, filename);
1596
+ }
1597
+ downloadFile(content, filename, mimeType) {
1598
+ const blob = new Blob([content], { type: mimeType });
1599
+ const url = window.URL.createObjectURL(blob);
1600
+ const link = document.createElement('a');
1601
+ link.href = url;
1602
+ link.download = filename;
1603
+ document.body.appendChild(link);
1604
+ link.click();
1605
+ document.body.removeChild(link);
1606
+ window.URL.revokeObjectURL(url);
1607
+ }
1608
+ // Utility methods with proper typing
1609
+ formatDate(date) {
1610
+ if (!date)
1611
+ return '-';
1612
+ return new Date(date).toLocaleDateString('en-US', {
1613
+ year: 'numeric',
1614
+ month: 'short',
1615
+ day: 'numeric'
1616
+ });
1617
+ }
1618
+ getDuration(fromDate, toDate) {
1619
+ if (!fromDate || !toDate)
1620
+ return '';
1621
+ const from = new Date(fromDate);
1622
+ const to = new Date(toDate);
1623
+ const diffTime = Math.abs(to.getTime() - from.getTime());
1624
+ const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24));
1625
+ const months = Math.floor(diffDays / 30);
1626
+ const years = Math.floor(months / 12);
1627
+ if (years > 0) {
1628
+ return `${years} year${years > 1 ? 's' : ''}`;
1629
+ }
1630
+ else if (months > 0) {
1631
+ return `${months} month${months > 1 ? 's' : ''}`;
1632
+ }
1633
+ else {
1634
+ return `${diffDays} day${diffDays > 1 ? 's' : ''}`;
1635
+ }
1636
+ }
1637
+ getStatusBadgeClass(academicYear) {
1638
+ if (academicYear.acayr_iscurrent)
1639
+ return 'tw-bg-green-100 tw-text-green-800';
1640
+ if (academicYear.acayr_islocked)
1641
+ return 'tw-bg-red-100 tw-text-red-800';
1642
+ if (academicYear.acayr_isactive)
1643
+ return 'tw-bg-blue-100 tw-text-blue-800';
1644
+ return 'tw-bg-gray-100 tw-text-gray-800';
1645
+ }
1646
+ getActiveStatusBadgeClass(academicYear) {
1647
+ if (academicYear.acayr_isactive) {
1648
+ return 'tw-bg-green-100 tw-text-green-800';
1649
+ }
1650
+ else {
1651
+ return 'tw-bg-orange-100 tw-text-orange-800';
1652
+ }
1653
+ }
1654
+ getStatusText(academicYear) {
1655
+ if (academicYear.acayr_iscurrent)
1656
+ return 'Current';
1657
+ if (academicYear.acayr_islocked)
1658
+ return 'Locked';
1659
+ if (academicYear.acayr_isactive)
1660
+ return 'Active';
1661
+ return 'Inactive';
1662
+ }
1663
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: AcademicYearListComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1664
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.7", type: AcademicYearListComponent, isStandalone: true, selector: "cide-core-academic-year-list", viewQueries: [{ propertyName: "academicYearDetailsRendererTemplate", first: true, predicate: ["academicYearDetailsRendererTemplate"], descendants: true, isSignal: true }, { propertyName: "dateRangeRendererTemplate", first: true, predicate: ["dateRangeRendererTemplate"], descendants: true, isSignal: true }, { propertyName: "statusRendererTemplate", first: true, predicate: ["statusRendererTemplate"], descendants: true, isSignal: true }, { propertyName: "actionsDropdownRendererTemplate", first: true, predicate: ["actionsDropdownRendererTemplate"], descendants: true, isSignal: true }], ngImport: i0, template: "<!-- Academic Year Container -->\r\n<div class=\"tw-table tw-w-full tw-h-full\">\r\n\r\n <!-- Header Section with Filters -->\r\n <div class=\"tw-table-row tw-h-0\">\r\n <div class=\"tw-table-cell tw-px-6 tw-py-3 tw-border-b tw-border-gray-200 tw-bg-gray-50\">\r\n <div\r\n class=\"tw-flex tw-flex-col sm:tw-flex-row tw-justify-between tw-items-start sm:tw-items-center tw-space-y-3 sm:tw-space-y-0\">\r\n\r\n <!-- Title -->\r\n <div class=\"tw-flex tw-items-center tw-space-x-2\">\r\n <cide-ele-icon class=\"tw-text-blue-600 tw-w-5 tw-h-5\">school</cide-ele-icon>\r\n <h5 class=\"tw-text-base tw-font-medium tw-text-gray-900 tw-m-0\">Academic Year Management</h5>\r\n </div>\r\n\r\n <!-- Actions -->\r\n <div\r\n class=\"tw-flex tw-flex-col sm:tw-flex-row tw-items-start sm:tw-items-center tw-space-y-3 sm:tw-space-y-0 sm:tw-space-x-3\">\r\n <button cideEleButton variant=\"primary\" size=\"sm\" leftIcon=\"add\" (click)=\"createAcademicYear()\">\r\n Create Academic Year\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Main Content Area -->\r\n <div class=\"tw-table-row\">\r\n <div class=\"tw-table-cell tw-h-full tw-relative\">\r\n\r\n <!-- Data Grid Component -->\r\n <div class=\"tw-h-full tw-overflow-auto\">\r\n <cide-ele-data-grid [config]=\"gridConfig()\" [templateRenderers]=\"templateRenderers()\"\r\n (gridEvent)=\"onGridEvent($event)\">\r\n </cide-ele-data-grid>\r\n </div>\r\n\r\n </div>\r\n </div>\r\n\r\n</div>\r\n\r\n<!-- Template Renderers -->\r\n<ng-template #academicYearDetailsRendererTemplate let-row=\"row\">\r\n <div class=\"tw-flex tw-flex-col tw-w-full\">\r\n <div class=\"tw-font-medium tw-text-gray-900\">{{ row.acayr_name || 'N/A' }}</div>\r\n <div class=\"tw-text-sm tw-text-gray-500 tw-truncate\">{{ row.acayr_description || 'No description' }}</div>\r\n </div>\r\n</ng-template>\r\n\r\n<ng-template #dateRangeRendererTemplate let-row=\"row\">\r\n <div class=\"tw-flex tw-flex-col tw-text-sm\">\r\n <span class=\"tw-text-gray-900 tw-font-medium\">{{ formatDate(row.acayr_from_date) }}</span>\r\n <span class=\"tw-text-gray-500\">to {{ formatDate(row.acayr_to_date) }}</span>\r\n <span class=\"tw-text-xs tw-text-gray-400\">{{ getDuration(row.acayr_from_date, row.acayr_to_date) }}</span>\r\n </div>\r\n</ng-template>\r\n\r\n<ng-template #statusRendererTemplate let-row=\"row\">\r\n <div class=\"tw-flex tw-flex-col tw-gap-1 tw-items-center\">\r\n <!-- Current Year Badge (Priority) -->\r\n @if (row.acayr_iscurrent) {\r\n <span\r\n class=\"tw-inline-flex tw-items-center tw-justify-center tw-px-2.5 tw-py-1 tw-rounded-full tw-text-xs tw-font-medium tw-bg-yellow-100 tw-text-yellow-800 tw-text-center\">\r\n <cide-ele-icon size=\"2xs\" class=\"tw-mr-1\">star</cide-ele-icon>\r\n Current Year\r\n </span>\r\n }\r\n \r\n <!-- Active/Inactive Status Badge -->\r\n <span class=\"tw-inline-flex tw-items-center tw-justify-center tw-px-2.5 tw-py-0.5 tw-rounded-full tw-text-xs tw-font-medium tw-text-center\"\r\n [ngClass]=\"getActiveStatusBadgeClass(row)\">\r\n <cide-ele-icon size=\"2xs\" class=\"tw-mr-1\">\r\n {{ row.acayr_isactive ? 'check_circle' : 'cancel' }}\r\n </cide-ele-icon>\r\n {{ row.acayr_isactive ? 'Active' : 'Inactive' }}\r\n </span>\r\n \r\n <!-- Locked Status Badge (Additional info) -->\r\n @if (row.acayr_islocked) {\r\n <span\r\n class=\"tw-inline-flex tw-items-center tw-justify-center tw-px-2 tw-py-1 tw-rounded-full tw-text-xs tw-font-medium tw-bg-red-100 tw-text-red-800 tw-text-center\">\r\n <cide-ele-icon size=\"2xs\" class=\"tw-mr-1\">lock</cide-ele-icon>\r\n Locked\r\n </span>\r\n }\r\n </div>\r\n</ng-template>\r\n\r\n<ng-template #actionsDropdownRendererTemplate let-row=\"row\" let-value=\"value\">\r\n <cide-ele-dropdown \r\n [items]=\"getActionDropdownItems(row)\"\r\n [config]=\"{ triggerIcon: 'more_vert', triggerSize: 'sm' }\"\r\n (itemClick)=\"onDropdownItemClick($event, row)\">\r\n </cide-ele-dropdown>\r\n</ng-template>", styles: [".academic-year-listing-container{@apply tw-w-full tw-h-full;}:host{@apply tw-w-full tw-h-full tw-flex tw-flex-col;}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: FormsModule }, { kind: "component", type: CideIconComponent, selector: "cide-ele-icon", inputs: ["size", "type", "toolTip"] }, { kind: "component", type: CideEleButtonComponent, selector: "button[cideEleButton], a[cideEleButton]", inputs: ["label", "variant", "size", "type", "shape", "elevation", "disabled", "id", "loading", "fullWidth", "leftIcon", "rightIcon", "customClass", "tooltip", "ariaLabel", "testId", "routerLink", "routerExtras", "preventDoubleClick", "animated"], outputs: ["btnClick", "doubleClick"] }, { kind: "component", type: CideEleDataGridComponent, selector: "cide-ele-data-grid", inputs: ["config", "templateRenderers", "customFormatters", "actionHandlers", "serverSidePagination", "totalServerItems", "currentServerPage", "currentServerPageSize", "dragDropEnabled"], outputs: ["gridEvent"] }, { kind: "component", type: CideEleDropdownComponent, selector: "cide-ele-dropdown", inputs: ["items", "config", "triggerTemplate", "menuTemplate"], outputs: ["itemClick", "dropdownToggle"] }] });
1665
+ }
1666
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: AcademicYearListComponent, decorators: [{
1667
+ type: Component,
1668
+ args: [{ selector: 'cide-core-academic-year-list', standalone: true, imports: [
1669
+ CommonModule,
1670
+ FormsModule,
1671
+ CideIconComponent,
1672
+ CideEleButtonComponent,
1673
+ CideEleDataGridComponent,
1674
+ CideEleDropdownComponent
1675
+ ], template: "<!-- Academic Year Container -->\r\n<div class=\"tw-table tw-w-full tw-h-full\">\r\n\r\n <!-- Header Section with Filters -->\r\n <div class=\"tw-table-row tw-h-0\">\r\n <div class=\"tw-table-cell tw-px-6 tw-py-3 tw-border-b tw-border-gray-200 tw-bg-gray-50\">\r\n <div\r\n class=\"tw-flex tw-flex-col sm:tw-flex-row tw-justify-between tw-items-start sm:tw-items-center tw-space-y-3 sm:tw-space-y-0\">\r\n\r\n <!-- Title -->\r\n <div class=\"tw-flex tw-items-center tw-space-x-2\">\r\n <cide-ele-icon class=\"tw-text-blue-600 tw-w-5 tw-h-5\">school</cide-ele-icon>\r\n <h5 class=\"tw-text-base tw-font-medium tw-text-gray-900 tw-m-0\">Academic Year Management</h5>\r\n </div>\r\n\r\n <!-- Actions -->\r\n <div\r\n class=\"tw-flex tw-flex-col sm:tw-flex-row tw-items-start sm:tw-items-center tw-space-y-3 sm:tw-space-y-0 sm:tw-space-x-3\">\r\n <button cideEleButton variant=\"primary\" size=\"sm\" leftIcon=\"add\" (click)=\"createAcademicYear()\">\r\n Create Academic Year\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Main Content Area -->\r\n <div class=\"tw-table-row\">\r\n <div class=\"tw-table-cell tw-h-full tw-relative\">\r\n\r\n <!-- Data Grid Component -->\r\n <div class=\"tw-h-full tw-overflow-auto\">\r\n <cide-ele-data-grid [config]=\"gridConfig()\" [templateRenderers]=\"templateRenderers()\"\r\n (gridEvent)=\"onGridEvent($event)\">\r\n </cide-ele-data-grid>\r\n </div>\r\n\r\n </div>\r\n </div>\r\n\r\n</div>\r\n\r\n<!-- Template Renderers -->\r\n<ng-template #academicYearDetailsRendererTemplate let-row=\"row\">\r\n <div class=\"tw-flex tw-flex-col tw-w-full\">\r\n <div class=\"tw-font-medium tw-text-gray-900\">{{ row.acayr_name || 'N/A' }}</div>\r\n <div class=\"tw-text-sm tw-text-gray-500 tw-truncate\">{{ row.acayr_description || 'No description' }}</div>\r\n </div>\r\n</ng-template>\r\n\r\n<ng-template #dateRangeRendererTemplate let-row=\"row\">\r\n <div class=\"tw-flex tw-flex-col tw-text-sm\">\r\n <span class=\"tw-text-gray-900 tw-font-medium\">{{ formatDate(row.acayr_from_date) }}</span>\r\n <span class=\"tw-text-gray-500\">to {{ formatDate(row.acayr_to_date) }}</span>\r\n <span class=\"tw-text-xs tw-text-gray-400\">{{ getDuration(row.acayr_from_date, row.acayr_to_date) }}</span>\r\n </div>\r\n</ng-template>\r\n\r\n<ng-template #statusRendererTemplate let-row=\"row\">\r\n <div class=\"tw-flex tw-flex-col tw-gap-1 tw-items-center\">\r\n <!-- Current Year Badge (Priority) -->\r\n @if (row.acayr_iscurrent) {\r\n <span\r\n class=\"tw-inline-flex tw-items-center tw-justify-center tw-px-2.5 tw-py-1 tw-rounded-full tw-text-xs tw-font-medium tw-bg-yellow-100 tw-text-yellow-800 tw-text-center\">\r\n <cide-ele-icon size=\"2xs\" class=\"tw-mr-1\">star</cide-ele-icon>\r\n Current Year\r\n </span>\r\n }\r\n \r\n <!-- Active/Inactive Status Badge -->\r\n <span class=\"tw-inline-flex tw-items-center tw-justify-center tw-px-2.5 tw-py-0.5 tw-rounded-full tw-text-xs tw-font-medium tw-text-center\"\r\n [ngClass]=\"getActiveStatusBadgeClass(row)\">\r\n <cide-ele-icon size=\"2xs\" class=\"tw-mr-1\">\r\n {{ row.acayr_isactive ? 'check_circle' : 'cancel' }}\r\n </cide-ele-icon>\r\n {{ row.acayr_isactive ? 'Active' : 'Inactive' }}\r\n </span>\r\n \r\n <!-- Locked Status Badge (Additional info) -->\r\n @if (row.acayr_islocked) {\r\n <span\r\n class=\"tw-inline-flex tw-items-center tw-justify-center tw-px-2 tw-py-1 tw-rounded-full tw-text-xs tw-font-medium tw-bg-red-100 tw-text-red-800 tw-text-center\">\r\n <cide-ele-icon size=\"2xs\" class=\"tw-mr-1\">lock</cide-ele-icon>\r\n Locked\r\n </span>\r\n }\r\n </div>\r\n</ng-template>\r\n\r\n<ng-template #actionsDropdownRendererTemplate let-row=\"row\" let-value=\"value\">\r\n <cide-ele-dropdown \r\n [items]=\"getActionDropdownItems(row)\"\r\n [config]=\"{ triggerIcon: 'more_vert', triggerSize: 'sm' }\"\r\n (itemClick)=\"onDropdownItemClick($event, row)\">\r\n </cide-ele-dropdown>\r\n</ng-template>", styles: [".academic-year-listing-container{@apply tw-w-full tw-h-full;}:host{@apply tw-w-full tw-h-full tw-flex tw-flex-col;}\n"] }]
1676
+ }] });
1677
+
1678
+ var academicYearList_component = /*#__PURE__*/Object.freeze({
1679
+ __proto__: null,
1680
+ AcademicYearListComponent: AcademicYearListComponent
1681
+ });
1682
+
1683
+ // Academic Year Management Components
1684
+
1685
+ class CideLytClassProgramBranchService {
1686
+ http = inject(HttpClient);
1687
+ /**
1688
+ * Get list of class program branches
1689
+ * @param payload - Query parameters for filtering/pagination
1690
+ * @returns Observable of class program branch list response
1691
+ */
1692
+ getClassProgramBranchList(payload) {
1693
+ console.log("Class Program Branch List Payload:", payload);
1694
+ const query = generateStringFromObject(payload);
1695
+ const url = cidePath.join([
1696
+ hostManagerRoutesUrl.cideSuiteHost,
1697
+ academicsRoutesUrl.module,
1698
+ academicsRoutesUrl.classProgramBranch,
1699
+ query
1700
+ ]);
1701
+ return this.http.get(url);
1702
+ }
1703
+ /**
1704
+ * Get class program branch by ID
1705
+ * @param payload - Class program branch ID payload
1706
+ * @returns Observable of class program branch data
1707
+ */
1708
+ getClassProgramBranchById(payload) {
1709
+ const query = generateStringFromObject(payload);
1710
+ const url = cidePath.join([
1711
+ hostManagerRoutesUrl.cideSuiteHost,
1712
+ academicsRoutesUrl.module,
1713
+ academicsRoutesUrl.classProgramBranch,
1714
+ 'byId',
1715
+ query
1716
+ ]);
1717
+ return this.http.get(url);
1718
+ }
1719
+ /**
1720
+ * Create or update class program branch
1721
+ * @param data - Class program branch data to save
1722
+ * @returns Observable of the save response
1723
+ */
1724
+ saveClassProgramBranch(data) {
1725
+ const url = cidePath.join([
1726
+ hostManagerRoutesUrl.cideSuiteHost,
1727
+ academicsRoutesUrl.module,
1728
+ academicsRoutesUrl.classProgramBranch
1729
+ ]);
1730
+ return this.http.post(url, data);
1731
+ }
1732
+ /**
1733
+ * Delete class program branch
1734
+ * @param payload - Class program branch delete payload
1735
+ * @returns Observable of the delete response
1736
+ */
1737
+ deleteClassProgramBranch(payload) {
1738
+ const query = generateStringFromObject(payload);
1739
+ const url = cidePath.join([
1740
+ hostManagerRoutesUrl.cideSuiteHost,
1741
+ academicsRoutesUrl.module,
1742
+ academicsRoutesUrl.classProgramBranch,
1743
+ query
1744
+ ]);
1745
+ return this.http.delete(url);
1746
+ }
1747
+ /**
1748
+ * Toggle class program branch status (active/inactive)
1749
+ * @param payload - Class program branch toggle status payload
1750
+ * @returns Observable of the toggle status response
1751
+ */
1752
+ toggleClassProgramBranchStatus(payload) {
1753
+ const query = generateStringFromObject(payload);
1754
+ const url = cidePath.join([
1755
+ hostManagerRoutesUrl.cideSuiteHost,
1756
+ academicsRoutesUrl.module,
1757
+ academicsRoutesUrl.classProgramBranch,
1758
+ 'toggleStatus',
1759
+ query
1760
+ ]);
1761
+ return this.http.put(url, {});
1762
+ }
1763
+ /**
1764
+ * Toggle class program branch lock
1765
+ * @param payload - Class program branch toggle lock payload
1766
+ * @returns Observable of the toggle lock response
1767
+ */
1768
+ toggleClassProgramBranchLock(payload) {
1769
+ const query = generateStringFromObject(payload);
1770
+ const url = cidePath.join([
1771
+ hostManagerRoutesUrl.cideSuiteHost,
1772
+ academicsRoutesUrl.module,
1773
+ academicsRoutesUrl.classProgramBranch,
1774
+ 'toggleLock',
1775
+ query
1776
+ ]);
1777
+ return this.http.put(url, {});
1778
+ }
1779
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: CideLytClassProgramBranchService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
1780
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: CideLytClassProgramBranchService, providedIn: 'root' });
1781
+ }
1782
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: CideLytClassProgramBranchService, decorators: [{
1783
+ type: Injectable,
1784
+ args: [{
1785
+ providedIn: 'root'
1786
+ }]
1787
+ }] });
1788
+
1789
+ class CideLytClassProgramBranchListComponent {
1790
+ // Dependency injection
1791
+ destroyRef = inject(DestroyRef);
1792
+ router = inject(Router);
1793
+ route = inject(ActivatedRoute);
1794
+ appState = inject(AppStateHelperService);
1795
+ notificationService = inject(NotificationService);
1796
+ confirmationService = inject(ConfirmationService);
1797
+ classProgramBranchService = inject(CideLytClassProgramBranchService);
1798
+ // State management
1799
+ loading = signal(false, ...(ngDevMode ? [{ debugName: "loading" }] : []));
1800
+ error = signal(null, ...(ngDevMode ? [{ debugName: "error" }] : []));
1801
+ branches = signal([], ...(ngDevMode ? [{ debugName: "branches" }] : []));
1802
+ totalCount = signal(0, ...(ngDevMode ? [{ debugName: "totalCount" }] : []));
1803
+ programId = signal(null, ...(ngDevMode ? [{ debugName: "programId" }] : []));
1804
+ // Template renderers
1805
+ dragHandleRendererTemplate = viewChild('dragHandleRendererTemplate', ...(ngDevMode ? [{ debugName: "dragHandleRendererTemplate" }] : []));
1806
+ classProgramRendererTemplate = viewChild('classProgramRendererTemplate', ...(ngDevMode ? [{ debugName: "classProgramRendererTemplate" }] : []));
1807
+ actionsDropdownRendererTemplate = viewChild('actionsDropdownRendererTemplate', ...(ngDevMode ? [{ debugName: "actionsDropdownRendererTemplate" }] : []));
1808
+ // Grid configuration
1809
+ gridConfig = signal({
1810
+ id: 'class-program-branch-list-grid',
1811
+ title: '',
1812
+ subtitle: '',
1813
+ columns: [
1814
+ {
1815
+ key: 'drag',
1816
+ header: '',
1817
+ type: 'custom',
1818
+ width: '40px',
1819
+ truncate: false,
1820
+ align: 'center',
1821
+ renderer: 'dragHandleRenderer'
1822
+ },
1823
+ {
1824
+ key: 'acabrn_name',
1825
+ header: 'Branch Name',
1826
+ type: 'text',
1827
+ width: '200px',
1828
+ truncate: true,
1829
+ align: 'left'
1830
+ },
1831
+ {
1832
+ key: 'acabrn_code',
1833
+ header: 'Code',
1834
+ type: 'text',
1835
+ width: '150px',
1836
+ truncate: true,
1837
+ align: 'left'
1838
+ },
1839
+ {
1840
+ key: 'acabrn_class_program_id_acacpm',
1841
+ header: 'Class Program',
1842
+ type: 'custom',
1843
+ width: '200px',
1844
+ truncate: true,
1845
+ align: 'left',
1846
+ renderer: 'classProgramRenderer'
1847
+ },
1848
+ {
1849
+ key: 'acabrn_isactive',
1850
+ header: 'Status',
1851
+ type: 'status',
1852
+ width: '100px',
1853
+ truncate: false,
1854
+ align: 'center',
1855
+ statusConfig: {
1856
+ activeValue: true,
1857
+ activeLabel: 'Active',
1858
+ inactiveLabel: 'Inactive',
1859
+ activeClass: 'tw-bg-green-100 tw-text-green-800',
1860
+ inactiveClass: 'tw-bg-red-100 tw-text-red-800'
1861
+ }
1862
+ },
1863
+ {
1864
+ key: 'acabrn_islocked',
1865
+ header: 'Locked',
1866
+ type: 'status',
1867
+ width: '100px',
1868
+ truncate: false,
1869
+ align: 'center',
1870
+ statusConfig: {
1871
+ activeValue: true,
1872
+ activeLabel: 'Locked',
1873
+ inactiveLabel: 'Unlocked',
1874
+ activeClass: 'tw-bg-yellow-100 tw-text-yellow-800',
1875
+ inactiveClass: 'tw-bg-gray-100 tw-text-gray-800'
1876
+ }
1877
+ },
1878
+ {
1879
+ key: 'actions',
1880
+ header: '',
1881
+ type: 'custom',
1882
+ width: '80px',
1883
+ truncate: false,
1884
+ align: 'center',
1885
+ renderer: 'actionsDropdownRenderer'
1886
+ }
1887
+ ],
1888
+ data: [],
1889
+ trackBy: '_id',
1890
+ pagination: {
1891
+ enabled: true,
1892
+ pageSize: 10,
1893
+ pageSizeOptions: [10, 25, 50, 100],
1894
+ showQuickJump: true,
1895
+ showPageInfo: true,
1896
+ showRefresh: true
1897
+ },
1898
+ search: {
1899
+ enabled: true,
1900
+ placeholder: 'Search branches...',
1901
+ searchableColumns: ['acabrn_name', 'acabrn_code'],
1902
+ debounceMs: 300
1903
+ },
1904
+ loading: {
1905
+ useDefer: true,
1906
+ skeletonRows: 5,
1907
+ showOverlay: false
1908
+ },
1909
+ scroll: {
1910
+ enabled: true,
1911
+ maxHeight: '600px',
1912
+ minHeight: '400px',
1913
+ stickyHeader: true,
1914
+ virtualScroll: false,
1915
+ rowHeight: 50
1916
+ },
1917
+ responsive: true,
1918
+ striped: true,
1919
+ bordered: true,
1920
+ compact: false,
1921
+ tableClass: 'tw-table-fixed tw-w-full tw-rounded-lg',
1922
+ dragDrop: {
1923
+ enabled: true
1924
+ },
1925
+ onRefresh: 'onRefresh',
1926
+ onPageChange: 'onPageChange',
1927
+ onSearch: 'onSearch',
1928
+ onRowReorder: 'onRowReorder'
1929
+ }, ...(ngDevMode ? [{ debugName: "gridConfig" }] : []));
1930
+ // Computed template renderers
1931
+ templateRenderers = computed(() => {
1932
+ const renderers = {};
1933
+ if (this.dragHandleRendererTemplate()) {
1934
+ renderers['dragHandleRenderer'] = this.dragHandleRendererTemplate();
1935
+ }
1936
+ if (this.classProgramRendererTemplate()) {
1937
+ renderers['classProgramRenderer'] = this.classProgramRendererTemplate();
1938
+ }
1939
+ if (this.actionsDropdownRendererTemplate()) {
1940
+ renderers['actionsDropdownRenderer'] = this.actionsDropdownRendererTemplate();
1941
+ }
1942
+ return renderers;
1943
+ }, ...(ngDevMode ? [{ debugName: "templateRenderers" }] : []));
1944
+ ngOnInit() {
1945
+ console.log('🏢 Class Program Branch List Component initialized');
1946
+ this.checkRouteParams();
1947
+ // Load branches will be called when programId is set in checkRouteParams
1948
+ }
1949
+ /**
1950
+ * Check route parameters for program ID
1951
+ */
1952
+ checkRouteParams() {
1953
+ this.route.params.pipe(takeUntilDestroyed(this.destroyRef)).subscribe(params => {
1954
+ const queryParams = params['query'];
1955
+ console.log('🏢 Route params:', params, 'queryParams:', queryParams);
1956
+ if (queryParams) {
1957
+ // Query parameters passed (following page-controls pattern)
1958
+ const queryData = generateObjectFromString(queryParams);
1959
+ console.log('🏢 Program Class ID from route:', queryData);
1960
+ if (queryData?.programId) {
1961
+ this.programId.set(queryData.programId);
1962
+ console.log('🏢 Will filter branches by acabrn_class_program_id_acacpm:', queryData.programId);
1963
+ this.loadBranches();
1964
+ }
1965
+ }
1966
+ else {
1967
+ // Check for direct query parameters (fallback)
1968
+ const queryParams = this.route.snapshot.queryParams;
1969
+ const programId = queryParams['programId'] || queryParams['acabrn_class_program_id_acacpm'];
1970
+ if (programId) {
1971
+ this.programId.set(programId);
1972
+ console.log('🏢 Program Class ID from query params:', programId);
1973
+ console.log('🏢 Will filter branches by acabrn_class_program_id_acacpm:', programId);
1974
+ this.loadBranches();
1975
+ }
1976
+ else {
1977
+ // Load all branches if no program ID is provided
1978
+ console.log('🏢 No program class ID provided, loading all branches');
1979
+ this.loadBranches();
1980
+ }
1981
+ }
1982
+ });
1983
+ }
1984
+ /**
1985
+ * Load branches from API
1986
+ */
1987
+ loadBranches() {
1988
+ this.loading.set(true);
1989
+ this.error.set(null);
1990
+ const payload = {
1991
+ pagination: true,
1992
+ pageIndex: 0,
1993
+ pageSize: 10,
1994
+ acabrn_class_program_id_acacpm: this.programId()
1995
+ };
1996
+ // Add program class ID filter if available
1997
+ const currentProgramId = this.programId();
1998
+ if (currentProgramId) {
1999
+ // Filter branches by program class ID using acabrn_class_program_id_acacpm field
2000
+ console.log('🏢 Filtering branches by acabrn_class_program_id_acacpm:', currentProgramId);
2001
+ }
2002
+ else {
2003
+ console.log('🏢 No program class ID filter applied, loading all branches');
2004
+ }
2005
+ this.classProgramBranchService.getClassProgramBranchList(payload)
2006
+ .pipe(takeUntilDestroyed(this.destroyRef))
2007
+ .subscribe({
2008
+ next: (response) => {
2009
+ console.log('✅ Branches loaded:', response);
2010
+ if (response?.success && response.data) {
2011
+ this.branches.set(response.data);
2012
+ this.totalCount.set(response.total || 0);
2013
+ this.updateGridData();
2014
+ }
2015
+ else {
2016
+ this.error.set('Failed to load branches');
2017
+ this.notificationService.error('Failed to load branches');
2018
+ }
2019
+ this.loading.set(false);
2020
+ },
2021
+ error: (error) => {
2022
+ console.error('❌ Error loading branches:', error);
2023
+ this.error.set('Failed to load branches');
2024
+ this.loading.set(false);
2025
+ this.notificationService.error('Failed to load branches');
2026
+ }
2027
+ });
2028
+ }
2029
+ /**
2030
+ * Update grid data
2031
+ */
2032
+ updateGridData() {
2033
+ this.gridConfig.update(config => ({
2034
+ ...config,
2035
+ data: this.branches()
2036
+ }));
2037
+ }
2038
+ /**
2039
+ * Handle grid events
2040
+ */
2041
+ onGridEvent(event) {
2042
+ console.log('Grid Event:', event);
2043
+ switch (event.type) {
2044
+ case 'refresh':
2045
+ this.onRefresh();
2046
+ break;
2047
+ case 'pageChange':
2048
+ this.onPageChange(event.data);
2049
+ break;
2050
+ case 'search':
2051
+ this.onSearch(event.data);
2052
+ break;
2053
+ case 'rowReorder':
2054
+ this.onRowReorder(event.data);
2055
+ break;
2056
+ }
2057
+ }
2058
+ /**
2059
+ * Handle refresh
2060
+ */
2061
+ onRefresh() {
2062
+ this.loadBranches();
2063
+ }
2064
+ /**
2065
+ * Handle page change
2066
+ */
2067
+ onPageChange(event) {
2068
+ console.log('Page change:', event);
2069
+ // Implement pagination logic here
2070
+ }
2071
+ /**
2072
+ * Handle search
2073
+ */
2074
+ onSearch(event) {
2075
+ console.log('Search:', event);
2076
+ // Implement search logic here
2077
+ }
2078
+ /**
2079
+ * Handle row reorder (drag and drop)
2080
+ */
2081
+ onRowReorder(event) {
2082
+ console.log('Row reorder:', event);
2083
+ if (event && event.newOrder) {
2084
+ // Update the sequence order based on the new drag and drop order
2085
+ this.updateSequenceOrder(event.newOrder);
2086
+ }
2087
+ }
2088
+ /**
2089
+ * Update sequence order for branches
2090
+ */
2091
+ updateSequenceOrder(branches) {
2092
+ // Update sequence numbers based on new order
2093
+ const updatedBranches = branches.map((branch, index) => ({
2094
+ ...branch,
2095
+ acabrn_sequence: index + 1
2096
+ }));
2097
+ // Update local state
2098
+ this.branches.set(updatedBranches);
2099
+ this.updateGridData();
2100
+ // TODO: Implement API call to update sequence order on server
2101
+ // This would typically be a bulk update API call
2102
+ console.log('Updated sequence order:', updatedBranches.map(b => ({ id: b._id, sequence: b.acabrn_sequence })));
2103
+ this.notificationService.success('Sequence order updated successfully');
2104
+ }
2105
+ /**
2106
+ * Navigate to create branch
2107
+ */
2108
+ onCreateBranch() {
2109
+ const currentProgramId = this.programId();
2110
+ if (currentProgramId) {
2111
+ // Use generateStringFromObject to pass programId as route parameter
2112
+ const queryParams = generateStringFromObject({ programId: currentProgramId });
2113
+ this.router.navigate(['/control-panel/program_specialization/create', queryParams]);
2114
+ }
2115
+ else {
2116
+ // No program ID, navigate to create without parameters
2117
+ this.router.navigate(['/control-panel/program_specialization/create']);
2118
+ }
2119
+ }
2120
+ /**
2121
+ * Navigate to view branch
2122
+ */
2123
+ onViewBranch(branch) {
2124
+ if (branch._id) {
2125
+ const currentProgramId = this.programId();
2126
+ const queryParams = generateStringFromObject({ acabrn_id: branch._id });
2127
+ // Add programId as query parameter if available
2128
+ const navigationExtras = {};
2129
+ if (currentProgramId) {
2130
+ navigationExtras.queryParams = { programId: currentProgramId };
2131
+ }
2132
+ this.router.navigate(['/control-panel/program_specialization/view', queryParams], navigationExtras);
2133
+ }
2134
+ }
2135
+ /**
2136
+ * Navigate to edit branch
2137
+ */
2138
+ onEditBranch(branch) {
2139
+ if (branch._id) {
2140
+ const currentProgramId = this.programId();
2141
+ const queryParams = generateStringFromObject({ acabrn_id: branch._id });
2142
+ this.router.navigate(['/control-panel/program_specialization/edit', queryParams]);
2143
+ }
2144
+ }
2145
+ /**
2146
+ * Navigate to manage term for branch
2147
+ */
2148
+ onManageTerm(branch) {
2149
+ if (branch._id) {
2150
+ const currentProgramId = this.programId();
2151
+ const queryParams = generateStringFromObject({
2152
+ acabrn_id: branch._id,
2153
+ acacpm_id: currentProgramId
2154
+ });
2155
+ // Navigate to term management page
2156
+ this.router.navigate(['/control-panel/program-term-management', queryParams]);
2157
+ }
2158
+ }
2159
+ /**
2160
+ * Get dropdown items for branch actions
2161
+ */
2162
+ getBranchActionDropdownItems(branch) {
2163
+ return [
2164
+ {
2165
+ id: 'view',
2166
+ label: 'View',
2167
+ icon: 'visibility'
2168
+ },
2169
+ {
2170
+ id: 'edit',
2171
+ label: 'Edit',
2172
+ icon: 'edit'
2173
+ },
2174
+ {
2175
+ id: 'manage-term',
2176
+ label: 'Manage Term',
2177
+ icon: 'school'
2178
+ },
2179
+ {
2180
+ id: 'toggle-status',
2181
+ label: branch.acabrn_isactive ? 'Deactivate' : 'Activate',
2182
+ icon: branch.acabrn_isactive ? 'block' : 'check_circle'
2183
+ },
2184
+ {
2185
+ id: 'toggle-lock',
2186
+ label: branch.acabrn_islocked ? 'Unlock' : 'Lock',
2187
+ icon: branch.acabrn_islocked ? 'lock_open' : 'lock'
2188
+ },
2189
+ {
2190
+ id: 'delete',
2191
+ label: 'Delete',
2192
+ icon: 'delete',
2193
+ }
2194
+ ];
2195
+ }
2196
+ /**
2197
+ * Handle dropdown item click
2198
+ */
2199
+ onDropdownItemClick(item, branch) {
2200
+ switch (item.id) {
2201
+ case 'view':
2202
+ this.onViewBranch(branch);
2203
+ break;
2204
+ case 'edit':
2205
+ this.onEditBranch(branch);
2206
+ break;
2207
+ case 'manage-term':
2208
+ this.onManageTerm(branch);
2209
+ break;
2210
+ case 'toggle-status':
2211
+ this.toggleBranchStatus(branch);
2212
+ break;
2213
+ case 'toggle-lock':
2214
+ this.toggleBranchLock(branch);
2215
+ break;
2216
+ case 'delete':
2217
+ this.deleteBranch(branch);
2218
+ break;
2219
+ }
2220
+ }
2221
+ /**
2222
+ * Toggle branch status
2223
+ */
2224
+ toggleBranchStatus(branch) {
2225
+ if (!branch._id)
2226
+ return;
2227
+ const action = branch.acabrn_isactive ? 'deactivate' : 'activate';
2228
+ this.confirmationService.ask({
2229
+ title: `${action.charAt(0).toUpperCase() + action.slice(1)} Branch`,
2230
+ message: `Are you sure you want to ${action} this branch?`,
2231
+ confirmText: action.charAt(0).toUpperCase() + action.slice(1),
2232
+ cancelText: 'Cancel',
2233
+ type: 'warning'
2234
+ }).then((confirmed) => {
2235
+ if (confirmed) {
2236
+ const payload = {
2237
+ acabrn_id: branch._id
2238
+ };
2239
+ this.classProgramBranchService.toggleClassProgramBranchStatus(payload)
2240
+ .pipe(takeUntilDestroyed(this.destroyRef))
2241
+ .subscribe({
2242
+ next: (response) => {
2243
+ if (response?.success) {
2244
+ this.notificationService.success(`Branch ${action}d successfully`);
2245
+ this.loadBranches();
2246
+ }
2247
+ else {
2248
+ this.notificationService.error(`Failed to ${action} branch`);
2249
+ }
2250
+ },
2251
+ error: (error) => {
2252
+ console.error('❌ Error toggling branch status:', error);
2253
+ this.notificationService.error(`Failed to ${action} branch`);
2254
+ }
2255
+ });
2256
+ }
2257
+ });
2258
+ }
2259
+ /**
2260
+ * Toggle branch lock
2261
+ */
2262
+ toggleBranchLock(branch) {
2263
+ if (!branch._id)
2264
+ return;
2265
+ const action = branch.acabrn_islocked ? 'unlock' : 'lock';
2266
+ this.confirmationService.ask({
2267
+ title: `${action.charAt(0).toUpperCase() + action.slice(1)} Branch`,
2268
+ message: `Are you sure you want to ${action} this branch?`,
2269
+ confirmText: action.charAt(0).toUpperCase() + action.slice(1),
2270
+ cancelText: 'Cancel',
2271
+ type: 'warning'
2272
+ }).then((confirmed) => {
2273
+ if (confirmed) {
2274
+ const payload = {
2275
+ acabrn_id: branch._id
2276
+ };
2277
+ this.classProgramBranchService.toggleClassProgramBranchLock(payload)
2278
+ .pipe(takeUntilDestroyed(this.destroyRef))
2279
+ .subscribe({
2280
+ next: (response) => {
2281
+ if (response?.success) {
2282
+ this.notificationService.success(`Branch ${action}ed successfully`);
2283
+ this.loadBranches();
2284
+ }
2285
+ else {
2286
+ this.notificationService.error(`Failed to ${action} branch`);
2287
+ }
2288
+ },
2289
+ error: (error) => {
2290
+ console.error('❌ Error toggling branch lock:', error);
2291
+ this.notificationService.error(`Failed to ${action} branch`);
2292
+ }
2293
+ });
2294
+ }
2295
+ });
2296
+ }
2297
+ /**
2298
+ * Delete branch
2299
+ */
2300
+ deleteBranch(branch) {
2301
+ if (!branch._id)
2302
+ return;
2303
+ this.confirmationService.ask({
2304
+ title: 'Delete Branch',
2305
+ message: `Are you sure you want to delete "${branch.acabrn_name}"? This action cannot be undone.`,
2306
+ confirmText: 'Delete',
2307
+ cancelText: 'Cancel',
2308
+ type: 'danger'
2309
+ }).then((confirmed) => {
2310
+ if (confirmed) {
2311
+ const payload = {
2312
+ acabrn_id: branch._id
2313
+ };
2314
+ this.classProgramBranchService.deleteClassProgramBranch(payload)
2315
+ .pipe(takeUntilDestroyed(this.destroyRef))
2316
+ .subscribe({
2317
+ next: (response) => {
2318
+ if (response?.success) {
2319
+ this.notificationService.success('Branch deleted successfully');
2320
+ this.loadBranches();
2321
+ }
2322
+ else {
2323
+ this.notificationService.error('Failed to delete branch');
2324
+ }
2325
+ },
2326
+ error: (error) => {
2327
+ console.error('❌ Error deleting branch:', error);
2328
+ this.notificationService.error('Failed to delete branch');
2329
+ }
2330
+ });
2331
+ }
2332
+ });
2333
+ }
2334
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: CideLytClassProgramBranchListComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2335
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "20.1.7", type: CideLytClassProgramBranchListComponent, isStandalone: true, selector: "cide-academics-class-program-branch-list", viewQueries: [{ propertyName: "dragHandleRendererTemplate", first: true, predicate: ["dragHandleRendererTemplate"], descendants: true, isSignal: true }, { propertyName: "classProgramRendererTemplate", first: true, predicate: ["classProgramRendererTemplate"], descendants: true, isSignal: true }, { propertyName: "actionsDropdownRendererTemplate", first: true, predicate: ["actionsDropdownRendererTemplate"], descendants: true, isSignal: true }], ngImport: i0, template: "<!-- Class Program Branch Container -->\r\n<div class=\"tw-table tw-w-full tw-h-full\">\r\n\r\n <!-- Header Section -->\r\n <div class=\"tw-table-row tw-h-0\">\r\n <div class=\"tw-table-cell tw-px-6 tw-py-3 tw-border-b tw-border-gray-200 tw-bg-gray-50\">\r\n <div\r\n class=\"tw-flex tw-flex-col sm:tw-flex-row tw-justify-between tw-items-start sm:tw-items-center tw-space-y-3 sm:tw-space-y-0\">\r\n <div class=\"tw-flex tw-items-center tw-space-x-2\">\r\n <cide-ele-icon class=\"tw-text-blue-600 tw-w-5 tw-h-5\">account_tree</cide-ele-icon>\r\n <h5 class=\"tw-text-base tw-font-medium tw-text-gray-900 tw-m-0\">Class Program Branch Management</h5>\r\n </div>\r\n <div\r\n class=\"tw-flex tw-flex-col sm:tw-flex-row tw-items-start sm:tw-items-center tw-space-y-3 sm:tw-space-y-0 sm:tw-space-x-3\">\r\n <button cideEleButton variant=\"primary\" size=\"sm\" leftIcon=\"add\" (click)=\"onCreateBranch()\">\r\n Create Branch\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Data Grid Section -->\r\n <div class=\"tw-table-row\">\r\n <div class=\"tw-table-cell tw-p-0\">\r\n <cide-ele-data-grid\r\n [config]=\"gridConfig()\"\r\n [templateRenderers]=\"templateRenderers()\"\r\n (gridEvent)=\"onGridEvent($event)\">\r\n </cide-ele-data-grid>\r\n </div>\r\n </div>\r\n</div>\r\n\r\n<!-- Template Renderers -->\r\n<ng-template #dragHandleRendererTemplate let-row=\"row\">\r\n <div class=\"tw-flex tw-justify-center tw-cursor-move drag-handle\" title=\"Drag to reorder\">\r\n <cide-ele-icon name=\"drag_indicator\" class=\"tw-w-4 tw-h-4 tw-text-gray-400 hover:tw-text-gray-600\"></cide-ele-icon>\r\n </div>\r\n</ng-template>\r\n\r\n\r\n<ng-template #classProgramRendererTemplate let-row=\"row\">\r\n <div class=\"tw-text-sm tw-text-gray-900\">\r\n {{ row.acabrn_class_program_id_acacpm?.acacpm_alise_title || 'N/A' }}\r\n </div>\r\n</ng-template>\r\n\r\n<ng-template #actionsDropdownRendererTemplate let-row=\"row\">\r\n <div class=\"tw-relative tw-inline-block\">\r\n <cide-ele-dropdown \r\n [items]=\"getBranchActionDropdownItems(row)\" \r\n (itemClick)=\"onDropdownItemClick($event, row)\">\r\n </cide-ele-dropdown>\r\n </div>\r\n</ng-template>\r\n\r\n", styles: [".drag-handle{cursor:move}.drag-handle:hover{background-color:#0000000d;border-radius:4px}.tw-table tbody tr{cursor:pointer}.tw-table tbody tr:hover{background-color:#00000005}.tw-table tbody tr.selected{background-color:#3b82f61a}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: CideEleDataGridComponent, selector: "cide-ele-data-grid", inputs: ["config", "templateRenderers", "customFormatters", "actionHandlers", "serverSidePagination", "totalServerItems", "currentServerPage", "currentServerPageSize", "dragDropEnabled"], outputs: ["gridEvent"] }, { kind: "component", type: CideIconComponent, selector: "cide-ele-icon", inputs: ["size", "type", "toolTip"] }, { kind: "component", type: CideEleButtonComponent, selector: "button[cideEleButton], a[cideEleButton]", inputs: ["label", "variant", "size", "type", "shape", "elevation", "disabled", "id", "loading", "fullWidth", "leftIcon", "rightIcon", "customClass", "tooltip", "ariaLabel", "testId", "routerLink", "routerExtras", "preventDoubleClick", "animated"], outputs: ["btnClick", "doubleClick"] }, { kind: "component", type: CideEleDropdownComponent, selector: "cide-ele-dropdown", inputs: ["items", "config", "triggerTemplate", "menuTemplate"], outputs: ["itemClick", "dropdownToggle"] }] });
2336
+ }
2337
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: CideLytClassProgramBranchListComponent, decorators: [{
2338
+ type: Component,
2339
+ args: [{ selector: 'cide-academics-class-program-branch-list', standalone: true, imports: [
2340
+ CommonModule,
2341
+ CideEleDataGridComponent,
2342
+ CideIconComponent,
2343
+ CideEleButtonComponent,
2344
+ CideEleDropdownComponent
2345
+ ], template: "<!-- Class Program Branch Container -->\r\n<div class=\"tw-table tw-w-full tw-h-full\">\r\n\r\n <!-- Header Section -->\r\n <div class=\"tw-table-row tw-h-0\">\r\n <div class=\"tw-table-cell tw-px-6 tw-py-3 tw-border-b tw-border-gray-200 tw-bg-gray-50\">\r\n <div\r\n class=\"tw-flex tw-flex-col sm:tw-flex-row tw-justify-between tw-items-start sm:tw-items-center tw-space-y-3 sm:tw-space-y-0\">\r\n <div class=\"tw-flex tw-items-center tw-space-x-2\">\r\n <cide-ele-icon class=\"tw-text-blue-600 tw-w-5 tw-h-5\">account_tree</cide-ele-icon>\r\n <h5 class=\"tw-text-base tw-font-medium tw-text-gray-900 tw-m-0\">Class Program Branch Management</h5>\r\n </div>\r\n <div\r\n class=\"tw-flex tw-flex-col sm:tw-flex-row tw-items-start sm:tw-items-center tw-space-y-3 sm:tw-space-y-0 sm:tw-space-x-3\">\r\n <button cideEleButton variant=\"primary\" size=\"sm\" leftIcon=\"add\" (click)=\"onCreateBranch()\">\r\n Create Branch\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Data Grid Section -->\r\n <div class=\"tw-table-row\">\r\n <div class=\"tw-table-cell tw-p-0\">\r\n <cide-ele-data-grid\r\n [config]=\"gridConfig()\"\r\n [templateRenderers]=\"templateRenderers()\"\r\n (gridEvent)=\"onGridEvent($event)\">\r\n </cide-ele-data-grid>\r\n </div>\r\n </div>\r\n</div>\r\n\r\n<!-- Template Renderers -->\r\n<ng-template #dragHandleRendererTemplate let-row=\"row\">\r\n <div class=\"tw-flex tw-justify-center tw-cursor-move drag-handle\" title=\"Drag to reorder\">\r\n <cide-ele-icon name=\"drag_indicator\" class=\"tw-w-4 tw-h-4 tw-text-gray-400 hover:tw-text-gray-600\"></cide-ele-icon>\r\n </div>\r\n</ng-template>\r\n\r\n\r\n<ng-template #classProgramRendererTemplate let-row=\"row\">\r\n <div class=\"tw-text-sm tw-text-gray-900\">\r\n {{ row.acabrn_class_program_id_acacpm?.acacpm_alise_title || 'N/A' }}\r\n </div>\r\n</ng-template>\r\n\r\n<ng-template #actionsDropdownRendererTemplate let-row=\"row\">\r\n <div class=\"tw-relative tw-inline-block\">\r\n <cide-ele-dropdown \r\n [items]=\"getBranchActionDropdownItems(row)\" \r\n (itemClick)=\"onDropdownItemClick($event, row)\">\r\n </cide-ele-dropdown>\r\n </div>\r\n</ng-template>\r\n\r\n", styles: [".drag-handle{cursor:move}.drag-handle:hover{background-color:#0000000d;border-radius:4px}.tw-table tbody tr{cursor:pointer}.tw-table tbody tr:hover{background-color:#00000005}.tw-table tbody tr.selected{background-color:#3b82f61a}\n"] }]
2346
+ }] });
2347
+
2348
+ var classProgramBranchList_component = /*#__PURE__*/Object.freeze({
2349
+ __proto__: null,
2350
+ CideLytClassProgramBranchListComponent: CideLytClassProgramBranchListComponent
2351
+ });
2352
+
2353
+ class CideLytProgramClassService {
2354
+ http = inject(HttpClient);
2355
+ /**
2356
+ * Get list of program classes
2357
+ * @param payload - Query parameters for filtering/pagination
2358
+ * @returns Observable of program class list response
2359
+ */
2360
+ getProgramClassList(payload) {
2361
+ console.log("Program Class List Payload:", payload);
2362
+ const query = generateStringFromObject(payload);
2363
+ const url = cidePath.join([
2364
+ hostManagerRoutesUrl.cideSuiteHost,
2365
+ academicsRoutesUrl.module,
2366
+ academicsRoutesUrl.classProgramMaster,
2367
+ query
2368
+ ]);
2369
+ return this.http.get(url);
2370
+ }
2371
+ /**
2372
+ * Get program class by ID
2373
+ * @param payload - Program class ID payload
2374
+ * @returns Observable of program class data
2375
+ */
2376
+ getProgramClassById(payload) {
2377
+ const query = generateStringFromObject(payload);
2378
+ const url = cidePath.join([
2379
+ hostManagerRoutesUrl.cideSuiteHost,
2380
+ academicsRoutesUrl.module,
2381
+ academicsRoutesUrl.classProgramMaster,
2382
+ 'byId',
2383
+ query
2384
+ ]);
2385
+ return this.http.get(url);
2386
+ }
2387
+ /**
2388
+ * Create or update program class
2389
+ * @param data - Program class data to save
2390
+ * @returns Observable of the save response
2391
+ */
2392
+ saveProgramClass(data) {
2393
+ const url = cidePath.join([
2394
+ hostManagerRoutesUrl.cideSuiteHost,
2395
+ academicsRoutesUrl.module,
2396
+ academicsRoutesUrl.classProgramMaster
2397
+ ]);
2398
+ return this.http.post(url, data);
2399
+ }
2400
+ /**
2401
+ * Delete program class
2402
+ * @param payload - Program class delete payload
2403
+ * @returns Observable of the delete response
2404
+ */
2405
+ deleteProgramClass(payload) {
2406
+ const query = generateStringFromObject(payload);
2407
+ const url = cidePath.join([
2408
+ hostManagerRoutesUrl.cideSuiteHost,
2409
+ academicsRoutesUrl.module,
2410
+ academicsRoutesUrl.classProgramMaster,
2411
+ query
2412
+ ]);
2413
+ return this.http.delete(url);
2414
+ }
2415
+ /**
2416
+ * Toggle program class status (active/inactive)
2417
+ * @param payload - Program class toggle status payload
2418
+ * @returns Observable of the toggle status response
2419
+ */
2420
+ toggleProgramClassStatus(payload) {
2421
+ const query = generateStringFromObject(payload);
2422
+ const url = cidePath.join([
2423
+ hostManagerRoutesUrl.cideSuiteHost,
2424
+ academicsRoutesUrl.module,
2425
+ academicsRoutesUrl.classProgramMaster,
2426
+ 'toggleStatus',
2427
+ query
2428
+ ]);
2429
+ return this.http.put(url, {});
2430
+ }
2431
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: CideLytProgramClassService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
2432
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: CideLytProgramClassService, providedIn: 'root' });
2433
+ }
2434
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: CideLytProgramClassService, decorators: [{
2435
+ type: Injectable,
2436
+ args: [{
2437
+ providedIn: 'root'
2438
+ }]
2439
+ }] });
2440
+
2441
+ class CideLytClassProgramBranchFormComponent {
2442
+ // Dependency injection
2443
+ destroyRef = inject(DestroyRef);
2444
+ fb = inject(FormBuilder);
2445
+ router = inject(Router);
2446
+ route = inject(ActivatedRoute);
2447
+ location = inject(Location);
2448
+ appState = inject(AppStateHelperService);
2449
+ notificationService = inject(NotificationService);
2450
+ confirmationService = inject(ConfirmationService);
2451
+ classProgramBranchService = inject(CideLytClassProgramBranchService);
2452
+ programClassService = inject(CideLytProgramClassService);
2453
+ // Form and state management
2454
+ branchForm;
2455
+ loading = signal(false, ...(ngDevMode ? [{ debugName: "loading" }] : []));
2456
+ error = signal(null, ...(ngDevMode ? [{ debugName: "error" }] : []));
2457
+ isEditMode = signal(false, ...(ngDevMode ? [{ debugName: "isEditMode" }] : []));
2458
+ isViewMode = signal(false, ...(ngDevMode ? [{ debugName: "isViewMode" }] : []));
2459
+ branchId = signal(null, ...(ngDevMode ? [{ debugName: "branchId" }] : []));
2460
+ // Data signals
2461
+ programClasses = signal([], ...(ngDevMode ? [{ debugName: "programClasses" }] : []));
2462
+ constructor() {
2463
+ this.branchForm = this.fb.group({
2464
+ acabrn_name: ['', [Validators.required, Validators.minLength(2)]],
2465
+ acabrn_code: ['', [Validators.required, Validators.minLength(2)]],
2466
+ acabrn_sequence: [0, [Validators.required, Validators.min(0)]],
2467
+ acabrn_class_program_id_acacpm: ['', [Validators.required]],
2468
+ acabrn_isactive: [true],
2469
+ acabrn_islocked: [false]
2470
+ });
2471
+ }
2472
+ ngOnInit() {
2473
+ console.log('🏢 Class Program Branch Form Component initialized');
2474
+ this.initializeComponent();
2475
+ }
2476
+ ngOnDestroy() {
2477
+ console.log('🏢 Class Program Branch Form Component destroyed');
2478
+ }
2479
+ /**
2480
+ * Initialize component
2481
+ */
2482
+ initializeComponent() {
2483
+ this.loadMasterData();
2484
+ this.checkRouteParams();
2485
+ }
2486
+ /**
2487
+ * Check route parameters to determine mode
2488
+ */
2489
+ checkRouteParams() {
2490
+ const url = this.router.url;
2491
+ const queryParams = this.route.snapshot.queryParams;
2492
+ const routeParams = this.route.snapshot.params;
2493
+ // Check for program ID from route parameters or query parameters
2494
+ // Also check route parameters for programId (for create operations)
2495
+ let programId = {};
2496
+ if (routeParams['query']) {
2497
+ const params = generateObjectFromString(routeParams['query']);
2498
+ console.log('🏢 Params:generateObjectFromString', params);
2499
+ programId = params?.programId;
2500
+ }
2501
+ if (programId) {
2502
+ console.log('🏢 Program ID from route:', programId);
2503
+ // Pre-select the program in the form
2504
+ this.branchForm.patchValue({
2505
+ acabrn_class_program_id_acacpm: programId
2506
+ });
2507
+ }
2508
+ if (url.includes('/view/')) {
2509
+ this.isViewMode.set(true);
2510
+ this.loadBranchForView(queryParams);
2511
+ }
2512
+ else if (url.includes('/edit/')) {
2513
+ this.isEditMode.set(true);
2514
+ this.loadBranchForEdit(queryParams);
2515
+ }
2516
+ else {
2517
+ // Create mode
2518
+ this.isEditMode.set(false);
2519
+ this.isViewMode.set(false);
2520
+ }
2521
+ }
2522
+ /**
2523
+ * Load master data
2524
+ */
2525
+ loadMasterData() {
2526
+ console.log('🔄 Loading master data for Class Program Branch Form...');
2527
+ // Load program classes
2528
+ this.loadProgramClasses();
2529
+ }
2530
+ /**
2531
+ * Load program classes
2532
+ */
2533
+ loadProgramClasses() {
2534
+ this.programClassService.getProgramClassList({ pagination: false })
2535
+ .pipe(takeUntilDestroyed(this.destroyRef))
2536
+ .subscribe({
2537
+ next: (response) => {
2538
+ console.log('✅ Program classes loaded:', response);
2539
+ if (response?.success && response.data) {
2540
+ this.programClasses.set(response.data);
2541
+ }
2542
+ else {
2543
+ console.warn('⚠️ No program class data received');
2544
+ this.programClasses.set([]);
2545
+ }
2546
+ },
2547
+ error: (error) => {
2548
+ console.error('❌ Error loading program classes:', error);
2549
+ this.programClasses.set([]);
2550
+ }
2551
+ });
2552
+ }
2553
+ /**
2554
+ * Load branch for viewing
2555
+ */
2556
+ loadBranchForView(queryParams) {
2557
+ const routeParams = this.route.snapshot.params;
2558
+ // Check query parameters first
2559
+ let params = generateObjectFromString(routeParams['query']);
2560
+ console.log('🏢 Params:generateObjectFromString', params);
2561
+ if (params?.acabrn_id) {
2562
+ console.log('🏢 Branch ID for view:', params.acabrn_id);
2563
+ this.branchId.set(params.acabrn_id);
2564
+ this.loadBranchData(params.acabrn_id, true);
2565
+ }
2566
+ else {
2567
+ console.error('❌ No branch ID found in route parameters');
2568
+ this.error.set('Branch ID not found in route parameters');
2569
+ }
2570
+ }
2571
+ /**
2572
+ * Load branch for editing
2573
+ */
2574
+ loadBranchForEdit(queryParams) {
2575
+ const routeParams = this.route.snapshot.params;
2576
+ // Check query parameters first
2577
+ let params = generateObjectFromString(routeParams['query']);
2578
+ console.log('🏢 Params:generateObjectFromString', params);
2579
+ if (params?.acabrn_id) {
2580
+ console.log('🏢 Branch ID for edit:', params.acabrn_id);
2581
+ this.branchId.set(params.acabrn_id);
2582
+ this.loadBranchData(params.acabrn_id, false);
2583
+ }
2584
+ else {
2585
+ console.error('❌ No branch ID found in route parameters');
2586
+ this.error.set('Branch ID not found in route parameters');
2587
+ }
2588
+ }
2589
+ /**
2590
+ * Load branch data
2591
+ */
2592
+ loadBranchData(branchId, isViewMode) {
2593
+ this.loading.set(true);
2594
+ this.error.set(null);
2595
+ const payload = {
2596
+ acabrn_id: branchId
2597
+ };
2598
+ this.classProgramBranchService.getClassProgramBranchById(payload)
2599
+ .pipe(takeUntilDestroyed(this.destroyRef))
2600
+ .subscribe({
2601
+ next: (response) => {
2602
+ if (response?.success && response.data) {
2603
+ const branchData = response.data;
2604
+ // Populate form with branch data
2605
+ this.branchForm.patchValue({
2606
+ acabrn_name: branchData.acabrn_name,
2607
+ acabrn_code: branchData.acabrn_code,
2608
+ acabrn_sequence: branchData.acabrn_sequence,
2609
+ acabrn_class_program_id_acacpm: branchData.acabrn_class_program_id_acacpm?._id,
2610
+ acabrn_isactive: (branchData).acabrn_isactive,
2611
+ acabrn_islocked: branchData.acabrn_islocked
2612
+ });
2613
+ // Disable form if in view mode
2614
+ if (isViewMode) {
2615
+ this.branchForm.disable();
2616
+ }
2617
+ this.notificationService.success('Branch data loaded successfully.');
2618
+ }
2619
+ else {
2620
+ this.error.set('Failed to load branch data.');
2621
+ this.notificationService.error('Failed to load branch data.');
2622
+ }
2623
+ this.loading.set(false);
2624
+ },
2625
+ error: (error) => {
2626
+ console.error('❌ Error loading branch data:', error);
2627
+ this.error.set('Failed to load branch data. Please try again.');
2628
+ this.loading.set(false);
2629
+ this.notificationService.error('Failed to load branch data. Please try again.');
2630
+ }
2631
+ });
2632
+ }
2633
+ /**
2634
+ * Get form title
2635
+ */
2636
+ get formTitle() {
2637
+ if (this.isViewMode())
2638
+ return 'View Program Specialization';
2639
+ if (this.isEditMode())
2640
+ return 'Edit Program Specialization';
2641
+ return 'Create Program Specialization';
2642
+ }
2643
+ /**
2644
+ * Get submit button text
2645
+ */
2646
+ get submitButtonText() {
2647
+ if (this.isViewMode())
2648
+ return 'Close';
2649
+ if (this.isEditMode())
2650
+ return 'Update Branch';
2651
+ return 'Create Branch';
2652
+ }
2653
+ /**
2654
+ * Handle form submission
2655
+ */
2656
+ onSubmit() {
2657
+ if (this.isViewMode()) {
2658
+ this.location.back();
2659
+ return;
2660
+ }
2661
+ if (this.branchForm.invalid) {
2662
+ this.notificationService.error('Please fill in all required fields correctly.');
2663
+ return;
2664
+ }
2665
+ const formData = this.branchForm.value;
2666
+ const payload = {
2667
+ _id: this.branchId() || undefined,
2668
+ acabrn_name: formData.acabrn_name,
2669
+ acabrn_code: formData.acabrn_code,
2670
+ acabrn_sequence: formData.acabrn_sequence,
2671
+ acabrn_class_program_id_acacpm: formData.acabrn_class_program_id_acacpm,
2672
+ acabrn_isactive: formData.acabrn_isactive,
2673
+ acabrn_islocked: formData.acabrn_islocked
2674
+ };
2675
+ this.saveBranch(payload);
2676
+ }
2677
+ /**
2678
+ * Save branch
2679
+ */
2680
+ saveBranch(payload) {
2681
+ this.loading.set(true);
2682
+ this.classProgramBranchService.saveClassProgramBranch(payload)
2683
+ .pipe(takeUntilDestroyed(this.destroyRef))
2684
+ .subscribe({
2685
+ next: (response) => {
2686
+ if (response?.success) {
2687
+ const action = this.isEditMode() ? 'updated' : 'created';
2688
+ this.notificationService.success(`Branch has been ${action} successfully.`);
2689
+ this.location.back();
2690
+ }
2691
+ else {
2692
+ this.notificationService.error(response?.message || 'Failed to save branch.');
2693
+ }
2694
+ this.loading.set(false);
2695
+ },
2696
+ error: (error) => {
2697
+ console.error('❌ Error saving branch:', error);
2698
+ this.notificationService.error('Failed to save branch. Please try again.');
2699
+ this.loading.set(false);
2700
+ }
2701
+ });
2702
+ }
2703
+ /**
2704
+ * Handle cancel
2705
+ */
2706
+ onCancel() {
2707
+ if (this.branchForm.dirty && !this.isViewMode()) {
2708
+ this.confirmationService.ask({
2709
+ title: 'Discard Changes',
2710
+ message: 'You have unsaved changes. Are you sure you want to discard them?',
2711
+ confirmText: 'Discard',
2712
+ cancelText: 'Keep Editing',
2713
+ type: 'warning'
2714
+ }).then((confirmed) => {
2715
+ if (confirmed) {
2716
+ this.location.back();
2717
+ }
2718
+ });
2719
+ }
2720
+ else {
2721
+ this.location.back();
2722
+ }
2723
+ }
2724
+ /**
2725
+ * Reset form to initial state
2726
+ */
2727
+ resetForm() {
2728
+ this.branchForm.reset();
2729
+ this.branchForm.patchValue({
2730
+ acabrn_isactive: true,
2731
+ acabrn_islocked: false,
2732
+ acabrn_sequence: 0
2733
+ });
2734
+ this.notificationService.info('Form has been reset to initial values.');
2735
+ }
2736
+ /**
2737
+ * Toggle active status on card click
2738
+ */
2739
+ onActiveCardClick() {
2740
+ if (this.isViewMode())
2741
+ return;
2742
+ const currentValue = this.branchForm.get('acabrn_isactive')?.value;
2743
+ this.branchForm.patchValue({
2744
+ acabrn_isactive: !currentValue
2745
+ });
2746
+ }
2747
+ /**
2748
+ * Toggle locked status on card click
2749
+ */
2750
+ onLockedCardClick() {
2751
+ if (this.isViewMode())
2752
+ return;
2753
+ const currentValue = this.branchForm.get('acabrn_islocked')?.value;
2754
+ this.branchForm.patchValue({
2755
+ acabrn_islocked: !currentValue
2756
+ });
2757
+ }
2758
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: CideLytClassProgramBranchFormComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2759
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.7", type: CideLytClassProgramBranchFormComponent, isStandalone: true, selector: "cide-academics-class-program-branch-form", ngImport: i0, template: "<!-- \r\n CLASS PROGRAM BRANCH FORM COMPONENT\r\n \r\n Enterprise-Level Styling with Tailwind CSS\r\n Features: Responsive grids, proper typography, enhanced user experience\r\n-->\r\n\r\n<div class=\"tw-w-full tw-h-full\">\r\n <form class=\"tw-w-full tw-table tw-h-full tw-bg-transparent\" [formGroup]=\"branchForm\"\r\n [class.tw-opacity-60]=\"loading()\" (ngSubmit)=\"onSubmit()\">\r\n\r\n <!-- Simple Header Section -->\r\n <div class=\"tw-table-row tw-w-full tw-h-0\">\r\n <div class=\"tw-table-cell tw-w-full tw-px-6 tw-py-3 tw-border-b tw-border-gray-200 tw-bg-gray-50\">\r\n <div class=\"tw-flex tw-flex-col sm:tw-flex-row tw-justify-between tw-items-start sm:tw-items-center tw-space-y-3 sm:tw-space-y-0\">\r\n \r\n <!-- Title -->\r\n <div class=\"tw-flex tw-items-center tw-space-x-2\">\r\n <cide-ele-icon class=\"tw-text-blue-600 tw-w-5 tw-h-5\">account_tree</cide-ele-icon>\r\n <h5 class=\"tw-text-base tw-font-medium tw-text-gray-900 tw-m-0\">\r\n {{ formTitle }}\r\n </h5>\r\n </div>\r\n\r\n <!-- Actions -->\r\n <div class=\"tw-flex tw-flex-col sm:tw-flex-row tw-items-start sm:tw-items-center tw-space-y-3 sm:tw-space-y-0 sm:tw-space-x-3\">\r\n <!-- Back button or other actions can be added here if needed -->\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Form Content -->\r\n <div class=\"tw-table-row\">\r\n <div class=\"tw-table-cell tw-w-full tw-px-6 tw-py-6\">\r\n <div class=\"tw-transition-opacity tw-duration-300\" [class.tw-opacity-60]=\"loading()\">\r\n \r\n <!-- Error Message -->\r\n @if (error()) {\r\n <div class=\"tw-mb-6 tw-p-4 tw-bg-red-50 tw-border tw-border-red-200 tw-rounded-md\">\r\n <div class=\"tw-flex tw-items-start\">\r\n <cide-ele-icon name=\"error\" class=\"tw-text-red-400 tw-w-5 tw-h-5 tw-mt-0.5 tw-flex-shrink-0\"></cide-ele-icon>\r\n <div class=\"tw-ml-3\">\r\n <h3 class=\"tw-text-sm tw-font-medium tw-text-red-800 tw-m-0\">Error</h3>\r\n <p class=\"tw-text-sm tw-text-red-700 tw-mt-1 tw-m-0\">{{ error() }}</p>\r\n </div>\r\n </div>\r\n </div>\r\n }\r\n\r\n <!-- Basic Branch Information -->\r\n <div class=\"tw-space-y-6\">\r\n <!-- Class Program Selection -->\r\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-1 tw-gap-6\">\r\n <div class=\"tw-space-y-2\">\r\n <label class=\"tw-text-sm tw-font-medium tw-text-gray-700\">Class Program *</label>\r\n <cide-ele-select \r\n formControlName=\"acabrn_class_program_id_acacpm\" \r\n placeholder=\"Select class program\"\r\n [disabled]=\"isViewMode()\" \r\n valueKey=\"_id\" \r\n labelKey=\"acacpm_alise_title\" \r\n [options]=\"programClasses()\">\r\n </cide-ele-select>\r\n <p class=\"tw-text-xs tw-text-gray-500 tw-mt-1\">\r\n <cide-ele-icon name=\"info\" class=\"tw-w-4 tw-h-4 tw-mr-1\"></cide-ele-icon>\r\n Sequence will be automatically assigned based on the order in the listing\r\n </p>\r\n </div>\r\n </div>\r\n\r\n <!-- Branch Name and Code -->\r\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-6\">\r\n <div>\r\n <cide-ele-input \r\n label=\"Branch Name *\" \r\n formControlName=\"acabrn_name\"\r\n placeholder=\"e.g., Computer Science Branch\" \r\n size=\"md\" \r\n leadingIcon=\"account_tree\"\r\n [disabled]=\"isViewMode()\">\r\n </cide-ele-input>\r\n </div>\r\n\r\n <div>\r\n <cide-ele-input \r\n label=\"Branch Code *\" \r\n formControlName=\"acabrn_code\"\r\n placeholder=\"e.g., CS\" \r\n size=\"md\" \r\n leadingIcon=\"code\"\r\n [disabled]=\"isViewMode()\">\r\n </cide-ele-input>\r\n </div>\r\n </div>\r\n\r\n <!-- Status and Lock Options -->\r\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-6\">\r\n <div class=\"tw-flex tw-items-center tw-gap-3 tw-p-4 tw-bg-gray-50 tw-rounded-lg tw-border tw-border-gray-200 tw-cursor-pointer hover:tw-bg-gray-100 tw-transition-colors tw-duration-200\"\r\n [class.tw-cursor-not-allowed]=\"isViewMode()\"\r\n [class.tw-opacity-60]=\"isViewMode()\"\r\n (click)=\"onActiveCardClick()\">\r\n <cide-ele-input formControlName=\"acabrn_isactive\" type=\"checkbox\" size=\"md\" [disabled]=\"isViewMode()\">\r\n </cide-ele-input>\r\n <div class=\"tw-flex tw-flex-col\">\r\n <span class=\"tw-text-sm tw-font-medium tw-text-gray-700\">Active</span>\r\n <span class=\"tw-text-xs tw-text-gray-500\">Enable/disable this branch</span>\r\n </div>\r\n </div>\r\n\r\n <div class=\"tw-flex tw-items-center tw-gap-3 tw-p-4 tw-bg-gray-50 tw-rounded-lg tw-border tw-border-gray-200 tw-cursor-pointer hover:tw-bg-gray-100 tw-transition-colors tw-duration-200\"\r\n [class.tw-cursor-not-allowed]=\"isViewMode()\"\r\n [class.tw-opacity-60]=\"isViewMode()\"\r\n (click)=\"onLockedCardClick()\">\r\n <cide-ele-input formControlName=\"acabrn_islocked\" type=\"checkbox\" size=\"md\" [disabled]=\"isViewMode()\">\r\n </cide-ele-input>\r\n <div class=\"tw-flex tw-flex-col\">\r\n <span class=\"tw-text-sm tw-font-medium tw-text-gray-700\">Locked</span>\r\n <span class=\"tw-text-xs tw-text-gray-500\">Prevent modifications</span>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Form Actions -->\r\n <div class=\"tw-table-row tw-h-0\">\r\n <div class=\"tw-table-cell tw-w-full tw-px-6 tw-py-2 tw-bg-gray-50 tw-border-t tw-border-gray-200\">\r\n <div class=\"tw-flex tw-justify-end tw-gap-4\">\r\n <button cideEleButton type=\"button\" variant=\"secondary\" (click)=\"resetForm()\" leftIcon=\"refresh\"\r\n [disabled]=\"loading()\">\r\n Reset Form\r\n </button>\r\n\r\n <button cideEleButton type=\"button\" variant=\"secondary\" (click)=\"onCancel()\" leftIcon=\"close\"\r\n [disabled]=\"loading()\">\r\n {{ isViewMode() ? 'Close' : 'Cancel' }}\r\n </button>\r\n\r\n @if (!isViewMode()) {\r\n <button cideEleButton type=\"submit\" variant=\"primary\" [disabled]=\"loading() || branchForm.invalid\"\r\n [loading]=\"loading()\" leftIcon=\"save\">\r\n {{ submitButtonText }}\r\n </button>\r\n }\r\n </div>\r\n </div>\r\n </div>\r\n </form>\r\n</div>\r\n\r\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: CideInputComponent, selector: "cide-ele-input", inputs: ["fill", "label", "labelHide", "disabled", "clearInput", "labelPlacement", "labelDir", "placeholder", "leadingIcon", "trailingIcon", "helperText", "helperTextCollapse", "hideHelperAndErrorText", "errorText", "maxlength", "minlength", "required", "autocapitalize", "autocomplete", "type", "width", "id", "ngModel", "option", "min", "max", "size"], outputs: ["ngModelChange"] }, { kind: "component", type: CideEleButtonComponent, selector: "button[cideEleButton], a[cideEleButton]", inputs: ["label", "variant", "size", "type", "shape", "elevation", "disabled", "id", "loading", "fullWidth", "leftIcon", "rightIcon", "customClass", "tooltip", "ariaLabel", "testId", "routerLink", "routerExtras", "preventDoubleClick", "animated"], outputs: ["btnClick", "doubleClick"] }, { kind: "component", type: CideIconComponent, selector: "cide-ele-icon", inputs: ["size", "type", "toolTip"] }, { kind: "component", type: CideSelectComponent, selector: "cide-ele-select", inputs: ["label", "labelHide", "placeholder", "helperText", "errorText", "required", "disabled", "id", "ngModel", "size", "fill", "labelPlacement", "labelDir", "leadingIcon", "trailingIcon", "clearInput", "options", "multiple", "searchable", "showSearchInput", "loading", "valueKey", "labelKey"], outputs: ["ngModelChange", "change", "searchChange"] }] });
2760
+ }
2761
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: CideLytClassProgramBranchFormComponent, decorators: [{
2762
+ type: Component,
2763
+ args: [{ selector: 'cide-academics-class-program-branch-form', standalone: true, imports: [
2764
+ CommonModule,
2765
+ ReactiveFormsModule,
2766
+ CideInputComponent,
2767
+ CideEleButtonComponent,
2768
+ CideIconComponent,
2769
+ CideSelectComponent,
2770
+ ], template: "<!-- \r\n CLASS PROGRAM BRANCH FORM COMPONENT\r\n \r\n Enterprise-Level Styling with Tailwind CSS\r\n Features: Responsive grids, proper typography, enhanced user experience\r\n-->\r\n\r\n<div class=\"tw-w-full tw-h-full\">\r\n <form class=\"tw-w-full tw-table tw-h-full tw-bg-transparent\" [formGroup]=\"branchForm\"\r\n [class.tw-opacity-60]=\"loading()\" (ngSubmit)=\"onSubmit()\">\r\n\r\n <!-- Simple Header Section -->\r\n <div class=\"tw-table-row tw-w-full tw-h-0\">\r\n <div class=\"tw-table-cell tw-w-full tw-px-6 tw-py-3 tw-border-b tw-border-gray-200 tw-bg-gray-50\">\r\n <div class=\"tw-flex tw-flex-col sm:tw-flex-row tw-justify-between tw-items-start sm:tw-items-center tw-space-y-3 sm:tw-space-y-0\">\r\n \r\n <!-- Title -->\r\n <div class=\"tw-flex tw-items-center tw-space-x-2\">\r\n <cide-ele-icon class=\"tw-text-blue-600 tw-w-5 tw-h-5\">account_tree</cide-ele-icon>\r\n <h5 class=\"tw-text-base tw-font-medium tw-text-gray-900 tw-m-0\">\r\n {{ formTitle }}\r\n </h5>\r\n </div>\r\n\r\n <!-- Actions -->\r\n <div class=\"tw-flex tw-flex-col sm:tw-flex-row tw-items-start sm:tw-items-center tw-space-y-3 sm:tw-space-y-0 sm:tw-space-x-3\">\r\n <!-- Back button or other actions can be added here if needed -->\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Form Content -->\r\n <div class=\"tw-table-row\">\r\n <div class=\"tw-table-cell tw-w-full tw-px-6 tw-py-6\">\r\n <div class=\"tw-transition-opacity tw-duration-300\" [class.tw-opacity-60]=\"loading()\">\r\n \r\n <!-- Error Message -->\r\n @if (error()) {\r\n <div class=\"tw-mb-6 tw-p-4 tw-bg-red-50 tw-border tw-border-red-200 tw-rounded-md\">\r\n <div class=\"tw-flex tw-items-start\">\r\n <cide-ele-icon name=\"error\" class=\"tw-text-red-400 tw-w-5 tw-h-5 tw-mt-0.5 tw-flex-shrink-0\"></cide-ele-icon>\r\n <div class=\"tw-ml-3\">\r\n <h3 class=\"tw-text-sm tw-font-medium tw-text-red-800 tw-m-0\">Error</h3>\r\n <p class=\"tw-text-sm tw-text-red-700 tw-mt-1 tw-m-0\">{{ error() }}</p>\r\n </div>\r\n </div>\r\n </div>\r\n }\r\n\r\n <!-- Basic Branch Information -->\r\n <div class=\"tw-space-y-6\">\r\n <!-- Class Program Selection -->\r\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-1 tw-gap-6\">\r\n <div class=\"tw-space-y-2\">\r\n <label class=\"tw-text-sm tw-font-medium tw-text-gray-700\">Class Program *</label>\r\n <cide-ele-select \r\n formControlName=\"acabrn_class_program_id_acacpm\" \r\n placeholder=\"Select class program\"\r\n [disabled]=\"isViewMode()\" \r\n valueKey=\"_id\" \r\n labelKey=\"acacpm_alise_title\" \r\n [options]=\"programClasses()\">\r\n </cide-ele-select>\r\n <p class=\"tw-text-xs tw-text-gray-500 tw-mt-1\">\r\n <cide-ele-icon name=\"info\" class=\"tw-w-4 tw-h-4 tw-mr-1\"></cide-ele-icon>\r\n Sequence will be automatically assigned based on the order in the listing\r\n </p>\r\n </div>\r\n </div>\r\n\r\n <!-- Branch Name and Code -->\r\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-6\">\r\n <div>\r\n <cide-ele-input \r\n label=\"Branch Name *\" \r\n formControlName=\"acabrn_name\"\r\n placeholder=\"e.g., Computer Science Branch\" \r\n size=\"md\" \r\n leadingIcon=\"account_tree\"\r\n [disabled]=\"isViewMode()\">\r\n </cide-ele-input>\r\n </div>\r\n\r\n <div>\r\n <cide-ele-input \r\n label=\"Branch Code *\" \r\n formControlName=\"acabrn_code\"\r\n placeholder=\"e.g., CS\" \r\n size=\"md\" \r\n leadingIcon=\"code\"\r\n [disabled]=\"isViewMode()\">\r\n </cide-ele-input>\r\n </div>\r\n </div>\r\n\r\n <!-- Status and Lock Options -->\r\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-6\">\r\n <div class=\"tw-flex tw-items-center tw-gap-3 tw-p-4 tw-bg-gray-50 tw-rounded-lg tw-border tw-border-gray-200 tw-cursor-pointer hover:tw-bg-gray-100 tw-transition-colors tw-duration-200\"\r\n [class.tw-cursor-not-allowed]=\"isViewMode()\"\r\n [class.tw-opacity-60]=\"isViewMode()\"\r\n (click)=\"onActiveCardClick()\">\r\n <cide-ele-input formControlName=\"acabrn_isactive\" type=\"checkbox\" size=\"md\" [disabled]=\"isViewMode()\">\r\n </cide-ele-input>\r\n <div class=\"tw-flex tw-flex-col\">\r\n <span class=\"tw-text-sm tw-font-medium tw-text-gray-700\">Active</span>\r\n <span class=\"tw-text-xs tw-text-gray-500\">Enable/disable this branch</span>\r\n </div>\r\n </div>\r\n\r\n <div class=\"tw-flex tw-items-center tw-gap-3 tw-p-4 tw-bg-gray-50 tw-rounded-lg tw-border tw-border-gray-200 tw-cursor-pointer hover:tw-bg-gray-100 tw-transition-colors tw-duration-200\"\r\n [class.tw-cursor-not-allowed]=\"isViewMode()\"\r\n [class.tw-opacity-60]=\"isViewMode()\"\r\n (click)=\"onLockedCardClick()\">\r\n <cide-ele-input formControlName=\"acabrn_islocked\" type=\"checkbox\" size=\"md\" [disabled]=\"isViewMode()\">\r\n </cide-ele-input>\r\n <div class=\"tw-flex tw-flex-col\">\r\n <span class=\"tw-text-sm tw-font-medium tw-text-gray-700\">Locked</span>\r\n <span class=\"tw-text-xs tw-text-gray-500\">Prevent modifications</span>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Form Actions -->\r\n <div class=\"tw-table-row tw-h-0\">\r\n <div class=\"tw-table-cell tw-w-full tw-px-6 tw-py-2 tw-bg-gray-50 tw-border-t tw-border-gray-200\">\r\n <div class=\"tw-flex tw-justify-end tw-gap-4\">\r\n <button cideEleButton type=\"button\" variant=\"secondary\" (click)=\"resetForm()\" leftIcon=\"refresh\"\r\n [disabled]=\"loading()\">\r\n Reset Form\r\n </button>\r\n\r\n <button cideEleButton type=\"button\" variant=\"secondary\" (click)=\"onCancel()\" leftIcon=\"close\"\r\n [disabled]=\"loading()\">\r\n {{ isViewMode() ? 'Close' : 'Cancel' }}\r\n </button>\r\n\r\n @if (!isViewMode()) {\r\n <button cideEleButton type=\"submit\" variant=\"primary\" [disabled]=\"loading() || branchForm.invalid\"\r\n [loading]=\"loading()\" leftIcon=\"save\">\r\n {{ submitButtonText }}\r\n </button>\r\n }\r\n </div>\r\n </div>\r\n </div>\r\n </form>\r\n</div>\r\n\r\n" }]
2771
+ }], ctorParameters: () => [] });
2772
+
2773
+ var classProgramBranchForm_component = /*#__PURE__*/Object.freeze({
2774
+ __proto__: null,
2775
+ CideLytClassProgramBranchFormComponent: CideLytClassProgramBranchFormComponent
2776
+ });
2777
+
2778
+ // Class Program Branch Management Module
2779
+ // This module provides components and services for managing class program branches
2780
+ // Components
2781
+
2782
+ /*
2783
+ * Public API Surface of cloud-ide-academics
2784
+ */
2785
+
2786
+ /**
2787
+ * Generated bundle index. Do not edit.
2788
+ */
2789
+
2790
+ export { AcademicYearCreateComponent as A, CideLytProgramClassService as C, CideLytAcademicYearService as a, CideLytClassProgramBranchService as b, academicsRoutes as c, AcademicYearListComponent as d, CideLytAcademicYearMappingService as e, CideLytClassProgramBranchListComponent as f, CideLytClassProgramBranchFormComponent as g };
2791
+ //# sourceMappingURL=cloud-ide-academics-cloud-ide-academics-Czexp3pk.mjs.map