cloud-ide-academics 0.0.28 → 0.0.30

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 (26) hide show
  1. package/fesm2022/cloud-ide-academics-class-program-term-create.component-B-7JRpVE.mjs +1196 -0
  2. package/fesm2022/cloud-ide-academics-class-program-term-create.component-B-7JRpVE.mjs.map +1 -0
  3. package/fesm2022/{cloud-ide-academics-class-program-term-list.component-CP2vlRBP.mjs → cloud-ide-academics-class-program-term-list.component-DObKkh-y.mjs} +186 -48
  4. package/fesm2022/cloud-ide-academics-class-program-term-list.component-DObKkh-y.mjs.map +1 -0
  5. package/fesm2022/cloud-ide-academics-cloud-ide-academics-FwQEJSnJ.mjs +6127 -0
  6. package/fesm2022/cloud-ide-academics-cloud-ide-academics-FwQEJSnJ.mjs.map +1 -0
  7. package/fesm2022/{cloud-ide-academics-program-class-create.component-KijRP6Nl.mjs → cloud-ide-academics-program-class-create.component-x0rh1ESo.mjs} +45 -23
  8. package/fesm2022/cloud-ide-academics-program-class-create.component-x0rh1ESo.mjs.map +1 -0
  9. package/fesm2022/{cloud-ide-academics-program-class-list.component-B5cy2Gpk.mjs → cloud-ide-academics-program-class-list.component-CkzH8u8u.mjs} +10 -9
  10. package/fesm2022/cloud-ide-academics-program-class-list.component-CkzH8u8u.mjs.map +1 -0
  11. package/fesm2022/cloud-ide-academics.mjs +1 -1
  12. package/index.d.ts +500 -18
  13. package/package.json +1 -1
  14. package/fesm2022/cloud-ide-academics-class-program-term-create.component-BRbHViJN.mjs +0 -659
  15. package/fesm2022/cloud-ide-academics-class-program-term-create.component-BRbHViJN.mjs.map +0 -1
  16. package/fesm2022/cloud-ide-academics-class-program-term-list.component-CP2vlRBP.mjs.map +0 -1
  17. package/fesm2022/cloud-ide-academics-class-program-term.service-BW4PJQEM.mjs +0 -111
  18. package/fesm2022/cloud-ide-academics-class-program-term.service-BW4PJQEM.mjs.map +0 -1
  19. package/fesm2022/cloud-ide-academics-cloud-ide-academics-g9qZGJtG.mjs +0 -3102
  20. package/fesm2022/cloud-ide-academics-cloud-ide-academics-g9qZGJtG.mjs.map +0 -1
  21. package/fesm2022/cloud-ide-academics-program-class-create.component-KijRP6Nl.mjs.map +0 -1
  22. package/fesm2022/cloud-ide-academics-program-class-list.component-B5cy2Gpk.mjs.map +0 -1
  23. package/fesm2022/cloud-ide-academics-program-term-section-create.component-DHrTb-XI.mjs +0 -248
  24. package/fesm2022/cloud-ide-academics-program-term-section-create.component-DHrTb-XI.mjs.map +0 -1
  25. package/fesm2022/cloud-ide-academics-program-term-section-list.component-ktIAxvxR.mjs +0 -495
  26. package/fesm2022/cloud-ide-academics-program-term-section-list.component-ktIAxvxR.mjs.map +0 -1
@@ -0,0 +1,1196 @@
1
+ import * as i0 from '@angular/core';
2
+ import { inject, DestroyRef, ChangeDetectorRef, signal, computed, Component } from '@angular/core';
3
+ import { CommonModule } from '@angular/common';
4
+ import * as i1 from '@angular/forms';
5
+ import { FormBuilder, Validators, ReactiveFormsModule } from '@angular/forms';
6
+ import { Router, ActivatedRoute } from '@angular/router';
7
+ import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
8
+ import { NotificationService, ConfirmationService, CideInputComponent, CideTextareaComponent, CideEleButtonComponent, CideIconComponent, CideSelectComponent } from 'cloud-ide-element';
9
+ import { AppStateHelperService, CideLytSharedWrapperComponent } from 'cloud-ide-layout';
10
+ import { ENTITY_SERVICE_TOKEN } from 'cloud-ide-shared';
11
+ import { b as CideLytClassProgramBranchService, C as CideLytProgramClassService, c as CideLytClassProgramTermService } from './cloud-ide-academics-cloud-ide-academics-FwQEJSnJ.mjs';
12
+ import { generateObjectFromString, MClassProgramTerm } from 'cloud-ide-lms-model';
13
+
14
+ class ClassProgramTermCreateComponent {
15
+ // Dependency injection
16
+ destroyRef = inject(DestroyRef);
17
+ fb = inject(FormBuilder);
18
+ entityService = inject(ENTITY_SERVICE_TOKEN);
19
+ router = inject(Router);
20
+ route = inject(ActivatedRoute);
21
+ appState = inject(AppStateHelperService);
22
+ notificationService = inject(NotificationService);
23
+ confirmationService = inject(ConfirmationService);
24
+ classProgramBranchService = inject(CideLytClassProgramBranchService);
25
+ programClassService = inject(CideLytProgramClassService);
26
+ classProgramTermService = inject(CideLytClassProgramTermService);
27
+ cdr = inject(ChangeDetectorRef);
28
+ classProgramTermForm;
29
+ loading = signal(false, ...(ngDevMode ? [{ debugName: "loading" }] : []));
30
+ error = signal(null, ...(ngDevMode ? [{ debugName: "error" }] : []));
31
+ // Class program term information from route
32
+ classProgramTermId = signal('', ...(ngDevMode ? [{ debugName: "classProgramTermId" }] : []));
33
+ isEditMode = signal(false, ...(ngDevMode ? [{ debugName: "isEditMode" }] : []));
34
+ isViewMode = signal(false, ...(ngDevMode ? [{ debugName: "isViewMode" }] : []));
35
+ // Data signals
36
+ programClasses = signal([], ...(ngDevMode ? [{ debugName: "programClasses" }] : []));
37
+ classProgramBranches = signal([], ...(ngDevMode ? [{ debugName: "classProgramBranches" }] : []));
38
+ // Options for dropdowns
39
+ programClassOptions = signal([], ...(ngDevMode ? [{ debugName: "programClassOptions" }] : []));
40
+ branchOptions = signal([], ...(ngDevMode ? [{ debugName: "branchOptions" }] : []));
41
+ parentTermOptions = signal([], ...(ngDevMode ? [{ debugName: "parentTermOptions" }] : []));
42
+ // Selected program class for branchType check
43
+ selectedProgramClass = signal(null, ...(ngDevMode ? [{ debugName: "selectedProgramClass" }] : []));
44
+ // Computed signal to check if branch dropdown should be shown
45
+ showBranchDropdown = computed(() => {
46
+ const selectedProgram = this.selectedProgramClass();
47
+ if (!selectedProgram)
48
+ return false;
49
+ const generalMaster = selectedProgram.acacpm_class_program_id_sygms;
50
+ if (!generalMaster || typeof generalMaster !== 'object')
51
+ return false;
52
+ let config;
53
+ if ('sygms_configuration' in generalMaster) {
54
+ const configValue = generalMaster.sygms_configuration;
55
+ if (typeof configValue === 'string') {
56
+ try {
57
+ config = JSON.parse(configValue);
58
+ }
59
+ catch {
60
+ return false;
61
+ }
62
+ }
63
+ else if (typeof configValue === 'object') {
64
+ config = configValue;
65
+ }
66
+ }
67
+ return config?.branchType === true;
68
+ }, ...(ngDevMode ? [{ debugName: "showBranchDropdown" }] : []));
69
+ // Computed signal to check if term dropdown should be shown
70
+ // Hide term dropdown if termType=true, termProgramLevelOneConnected=true, and termLevelUpTo <= 1
71
+ showTermDropdown = computed(() => {
72
+ const selectedProgram = this.selectedProgramClass();
73
+ if (!selectedProgram)
74
+ return true; // Show by default if no program selected
75
+ const generalMaster = selectedProgram.acacpm_class_program_id_sygms;
76
+ if (!generalMaster || typeof generalMaster !== 'object')
77
+ return true;
78
+ let config;
79
+ if ('sygms_configuration' in generalMaster) {
80
+ const configValue = generalMaster.sygms_configuration;
81
+ if (typeof configValue === 'string') {
82
+ try {
83
+ config = JSON.parse(configValue);
84
+ }
85
+ catch {
86
+ return true;
87
+ }
88
+ }
89
+ else if (typeof configValue === 'object') {
90
+ config = configValue;
91
+ }
92
+ }
93
+ // If termType=true AND termProgramLevelOneConnected=true AND termLevelUpTo <= 1, hide dropdown
94
+ if (config?.termType === true &&
95
+ config?.termProgramLevelOneConnected === true &&
96
+ config?.termLevelUpTo !== undefined &&
97
+ config.termLevelUpTo <= 1) {
98
+ return false;
99
+ }
100
+ return true; // Show dropdown by default
101
+ }, ...(ngDevMode ? [{ debugName: "showTermDropdown" }] : []));
102
+ // Get the auto-selected term ID when termLevelUpTo <= 1
103
+ autoSelectedTermId = computed(() => {
104
+ if (!this.showTermDropdown()) {
105
+ // When dropdown is hidden, we need to find the term for this program
106
+ // This will be handled in the program class change handler
107
+ return null;
108
+ }
109
+ return null;
110
+ }, ...(ngDevMode ? [{ debugName: "autoSelectedTermId" }] : []));
111
+ // Route parameters
112
+ acabrnId = signal(null, ...(ngDevMode ? [{ debugName: "acabrnId" }] : []));
113
+ acacpmId = signal(null, ...(ngDevMode ? [{ debugName: "acacpmId" }] : []));
114
+ parentTermId = signal(null, ...(ngDevMode ? [{ debugName: "parentTermId" }] : []));
115
+ // Signal for breadcrumb data that will be passed to shared wrapper
116
+ breadcrumbData = signal([], ...(ngDevMode ? [{ debugName: "breadcrumbData" }] : []));
117
+ // Date constraints
118
+ endDateMinDate = signal('', ...(ngDevMode ? [{ debugName: "endDateMinDate" }] : []));
119
+ constructor() {
120
+ this.classProgramTermForm = this.fb.group({
121
+ // Basic Class Program Term Information
122
+ acapt_code: ['', [Validators.required]],
123
+ acapt_name: ['', [Validators.required]],
124
+ acapt_description: [''],
125
+ acapt_class_program_id_acacpm: ['', [Validators.required]],
126
+ acapt_class_program_branch_id_acabrn: [''], // Will be conditionally required based on branchType
127
+ acapt_parent_class_prog_term_acapt: [''],
128
+ acapt_start_date: [''],
129
+ acapt_end_date: [''],
130
+ acapt_isactive: [true],
131
+ acapt_islocked: [false]
132
+ });
133
+ }
134
+ ngOnInit() {
135
+ this.initializeComponent();
136
+ this.setupFormSubscriptions();
137
+ this.updateBreadcrumbData();
138
+ }
139
+ /**
140
+ * Update breadcrumb data based on mode
141
+ */
142
+ updateBreadcrumbData() {
143
+ const additionalItems = [];
144
+ if (this.isViewMode()) {
145
+ additionalItems.push({
146
+ id: 'view',
147
+ label: 'View',
148
+ icon: 'visibility',
149
+ url: undefined
150
+ });
151
+ }
152
+ else if (this.isEditMode()) {
153
+ additionalItems.push({
154
+ id: 'edit',
155
+ label: 'Edit',
156
+ icon: 'edit',
157
+ url: undefined
158
+ });
159
+ }
160
+ else {
161
+ additionalItems.push({
162
+ id: 'create',
163
+ label: 'Create',
164
+ icon: 'add',
165
+ url: undefined
166
+ });
167
+ }
168
+ this.breadcrumbData.set(additionalItems);
169
+ }
170
+ /**
171
+ * Setup form subscriptions for dependent dropdowns
172
+ */
173
+ setupFormSubscriptions() {
174
+ // Watch for program class changes to filter branches
175
+ this.classProgramTermForm.get('acapt_class_program_id_acacpm')?.valueChanges
176
+ .pipe(takeUntilDestroyed(this.destroyRef))
177
+ .subscribe(programClassId => {
178
+ console.log('🔔 Program class changed to:', programClassId);
179
+ if (programClassId) {
180
+ // Update selected program class
181
+ const selectedProgram = this.programClassOptions().find(p => p._id === programClassId);
182
+ this.selectedProgramClass.set(selectedProgram || null);
183
+ // Load branches only if branchType is true
184
+ if (this.showBranchDropdown()) {
185
+ this.loadBranchesForProgramClass(programClassId);
186
+ // Set branch as required when branchType is true
187
+ this.classProgramTermForm.get('acapt_class_program_branch_id_acabrn')?.setValidators([Validators.required]);
188
+ }
189
+ else {
190
+ // Clear branches and remove required validator when branchType is false
191
+ this.branchOptions.set([]);
192
+ this.classProgramTermForm.get('acapt_class_program_branch_id_acabrn')?.clearValidators();
193
+ this.classProgramTermForm.get('acapt_class_program_branch_id_acabrn')?.setValue('');
194
+ }
195
+ // Handle term dropdown visibility and auto-selection
196
+ if (!this.showTermDropdown()) {
197
+ // If term dropdown should be hidden, auto-select the term for this program
198
+ this.autoSelectTermForProgram(programClassId);
199
+ }
200
+ else {
201
+ // If term dropdown should be shown, load parent terms as usual
202
+ // Clear parent term selection when program class changes (only if not setting from route)
203
+ const acabrnId = this.acabrnId();
204
+ if (!acabrnId) {
205
+ console.log('🧹 Clearing branch and parent term (program class changed)');
206
+ if (!this.showBranchDropdown()) {
207
+ this.classProgramTermForm.patchValue({
208
+ acapt_class_program_branch_id_acabrn: ''
209
+ });
210
+ }
211
+ this.parentTermOptions.set([]);
212
+ }
213
+ }
214
+ }
215
+ else {
216
+ // Clear all dependent dropdowns when program class is cleared
217
+ console.log('🧹 Clearing all dependent dropdowns (no program class)');
218
+ this.selectedProgramClass.set(null);
219
+ this.branchOptions.set([]);
220
+ this.parentTermOptions.set([]);
221
+ this.classProgramTermForm.get('acapt_class_program_branch_id_acabrn')?.clearValidators();
222
+ this.classProgramTermForm.patchValue({
223
+ acapt_class_program_branch_id_acabrn: '',
224
+ acapt_parent_class_prog_term_acapt: ''
225
+ });
226
+ }
227
+ this.classProgramTermForm.get('acapt_class_program_branch_id_acabrn')?.updateValueAndValidity();
228
+ });
229
+ // Watch for branch changes to determine parent term
230
+ this.classProgramTermForm.get('acapt_class_program_branch_id_acabrn')?.valueChanges
231
+ .pipe(takeUntilDestroyed(this.destroyRef))
232
+ .subscribe(branchId => {
233
+ console.log('🔔🔔🔔 Branch valueChanges triggered! Branch ID:', branchId);
234
+ if (branchId) {
235
+ // Load parent terms for the selected branch
236
+ console.log('🔄 Calling determineParentTerm for branch:', branchId);
237
+ this.determineParentTerm(branchId);
238
+ }
239
+ else {
240
+ // Clear parent term options and value when branch is cleared
241
+ console.log('🧹 Clearing parent term options (no branch selected)');
242
+ this.parentTermOptions.set([]);
243
+ this.classProgramTermForm.patchValue({
244
+ acapt_parent_class_prog_term_acapt: ''
245
+ });
246
+ }
247
+ });
248
+ // Watch for parent term changes to set date constraints
249
+ this.classProgramTermForm.get('acapt_parent_class_prog_term_acapt')?.valueChanges
250
+ .pipe(takeUntilDestroyed(this.destroyRef))
251
+ .subscribe(parentTermId => {
252
+ this.loadParentTermDetails(parentTermId);
253
+ });
254
+ // Watch for start date changes to set minimum date for end date
255
+ this.classProgramTermForm.get('acapt_start_date')?.valueChanges
256
+ .pipe(takeUntilDestroyed(this.destroyRef))
257
+ .subscribe(startDate => {
258
+ this.updateEndDateMinDate(startDate);
259
+ });
260
+ }
261
+ /**
262
+ * Initialize component
263
+ */
264
+ initializeComponent() {
265
+ // Check route parameters to determine mode
266
+ const routeParams = this.route.snapshot.params;
267
+ const queryParams = routeParams['query'];
268
+ // Check if we have query params (for edit/view mode)
269
+ if (queryParams) {
270
+ const queryData = generateObjectFromString(queryParams);
271
+ // Check for edit mode (acapt_id in query)
272
+ if (queryData?.acapt_id && !queryData?.acapt_parent_id) {
273
+ // This is edit mode (acapt_id without acapt_parent_id means editing the term itself)
274
+ this.isEditMode.set(true);
275
+ this.classProgramTermId.set(queryData.acapt_id);
276
+ this.loadClassProgramTermForEdit(queryData);
277
+ this.checkRouteParams(); // Still check for pre-selection of other fields
278
+ }
279
+ else if (this.router.url.includes('/view/')) {
280
+ // View mode
281
+ this.isViewMode.set(true);
282
+ this.loadClassProgramTermForView(queryData);
283
+ }
284
+ else {
285
+ // Create mode with pre-selection
286
+ this.checkRouteParams();
287
+ }
288
+ }
289
+ else {
290
+ // No query params - check URL for edit/view mode
291
+ const url = this.router.url;
292
+ if (url.includes('/view/')) {
293
+ this.isViewMode.set(true);
294
+ this.loadClassProgramTermForView({});
295
+ }
296
+ else if (url.includes('/edit/')) {
297
+ this.isEditMode.set(true);
298
+ this.loadClassProgramTermForEdit({});
299
+ }
300
+ else {
301
+ // Create mode
302
+ this.isEditMode.set(false);
303
+ this.isViewMode.set(false);
304
+ this.checkRouteParams();
305
+ }
306
+ }
307
+ // Update breadcrumb after mode is determined
308
+ this.updateBreadcrumbData();
309
+ // Load dropdown options
310
+ this.loadDropdownOptions();
311
+ // Set parent term if provided from route (for child term creation)
312
+ // This will be called after branches are loaded if acabrnId is present
313
+ // Otherwise, set it directly
314
+ if (!this.acabrnId() && !this.isEditMode() && !this.isViewMode()) {
315
+ this.setParentTermFromRoute();
316
+ }
317
+ }
318
+ /**
319
+ * Set parent term from route parameters
320
+ */
321
+ setParentTermFromRoute() {
322
+ const parentId = this.parentTermId();
323
+ if (parentId && !this.isEditMode() && !this.isViewMode()) {
324
+ this.classProgramTermForm.patchValue({
325
+ acapt_parent_class_prog_term_acapt: parentId
326
+ }, { emitEvent: true }); // Allow emitEvent to trigger parent term details loading
327
+ }
328
+ }
329
+ /**
330
+ * Check route parameters for acabrn_id and acacpm_id
331
+ */
332
+ checkRouteParams() {
333
+ // First check synchronously from snapshot
334
+ const routeParams = this.route.snapshot.params;
335
+ const queryParams = routeParams['query'];
336
+ console.log('🏢 Route params (snapshot):', routeParams, 'queryParams:', queryParams);
337
+ if (queryParams) {
338
+ console.log('✅ Query parameters found in route, will pre-select fields');
339
+ // Query parameters passed (following page-controls pattern)
340
+ const queryData = generateObjectFromString(queryParams);
341
+ console.log('🏢 Class Program Term Create params from route:', queryData);
342
+ // Check for branch ID in multiple possible formats
343
+ const branchId = queryData?.acabrn_id || queryData?.acabrnId || queryData?.branch_id || queryData?.branchId;
344
+ if (branchId) {
345
+ this.acabrnId.set(branchId);
346
+ console.log('🏢 Branch ID from route:', branchId);
347
+ }
348
+ if (queryData?.acacpm_id) {
349
+ const programId = queryData.acacpm_id;
350
+ this.acacpmId.set(programId);
351
+ console.log('🏢 ✅✅✅ Class Program ID SET from route:', programId);
352
+ console.log('🏢 ✅✅✅ acacpmId signal value:', this.acacpmId());
353
+ }
354
+ else {
355
+ console.log('🏢 ❌❌❌ NO acacpm_id in queryData:', queryData);
356
+ }
357
+ // Only set parent term ID if it's for creating a child term (acapt_parent_id)
358
+ // If acapt_id is present without acapt_parent_id, it's edit mode, not parent selection
359
+ if (queryData?.acapt_parent_id) {
360
+ const parentId = queryData.acapt_parent_id;
361
+ this.parentTermId.set(parentId);
362
+ console.log('🏢 Parent Term ID from route (for child term):', parentId);
363
+ }
364
+ }
365
+ else {
366
+ console.log('ℹ️ No query parameters in route - creating new term without pre-selection');
367
+ }
368
+ // Also subscribe to route params for dynamic changes
369
+ this.route.params.pipe(takeUntilDestroyed(this.destroyRef)).subscribe(params => {
370
+ const dynamicQueryParams = params['query'];
371
+ if (dynamicQueryParams && dynamicQueryParams !== queryParams) {
372
+ const queryData = generateObjectFromString(dynamicQueryParams);
373
+ console.log('🏢 Route params changed:', queryData);
374
+ // Check for branch ID in multiple possible formats
375
+ const branchId = queryData?.acabrn_id || queryData?.acabrnId || queryData?.branch_id || queryData?.branchId;
376
+ if (branchId) {
377
+ this.acabrnId.set(branchId);
378
+ }
379
+ if (queryData?.acacpm_id) {
380
+ this.acacpmId.set(queryData.acacpm_id);
381
+ }
382
+ if (queryData?.acapt_parent_id) {
383
+ const parentId = queryData.acapt_parent_id;
384
+ this.parentTermId.set(parentId);
385
+ }
386
+ }
387
+ });
388
+ }
389
+ /**
390
+ * Load class program term for viewing
391
+ */
392
+ loadClassProgramTermForView(queryParams) {
393
+ // Implementation for view mode
394
+ this.classProgramTermForm.disable();
395
+ }
396
+ /**
397
+ * Load class program term for editing
398
+ */
399
+ loadClassProgramTermForEdit(queryData) {
400
+ const routeParams = this.route.snapshot.params;
401
+ const queryParams = routeParams['query'];
402
+ // Get term ID from query data or route params
403
+ let termId;
404
+ if (queryData?.acapt_id) {
405
+ termId = queryData.acapt_id;
406
+ }
407
+ else if (queryParams) {
408
+ const decoded = generateObjectFromString(queryParams);
409
+ termId = decoded?.acapt_id;
410
+ }
411
+ if (!termId) {
412
+ console.error('❌ No term ID found in route parameters for edit mode');
413
+ this.error.set('Term ID not found in route parameters');
414
+ return;
415
+ }
416
+ console.log('🏢 Loading term for edit, ID:', termId);
417
+ this.classProgramTermId.set(termId);
418
+ this.loading.set(true);
419
+ this.error.set(null);
420
+ // Load term data
421
+ this.classProgramTermService.getClassProgramTermById({ acapt_id: termId })
422
+ .pipe(takeUntilDestroyed(this.destroyRef))
423
+ .subscribe({
424
+ next: (response) => {
425
+ console.log('🏢 Term data loaded for edit:', response);
426
+ this.loading.set(false);
427
+ if (response?.success && response.data) {
428
+ const term = response.data; // Type cast to handle property name differences
429
+ // Set program class and branch IDs for loading dropdowns
430
+ if (term.acapt_class_program_id_acacpm) {
431
+ const programId = typeof term.acapt_class_program_id_acacpm === 'string'
432
+ ? term.acapt_class_program_id_acacpm
433
+ : term.acapt_class_program_id_acacpm?._id;
434
+ if (programId) {
435
+ this.acacpmId.set(programId);
436
+ }
437
+ }
438
+ // Handle branch ID - check both property name variations
439
+ const branchIdValue = term.acapt_class_program_branch_id_acabrn || term.acapt_class_prg_branch_acabrn;
440
+ if (branchIdValue) {
441
+ const branchId = typeof branchIdValue === 'string'
442
+ ? branchIdValue
443
+ : branchIdValue?._id;
444
+ if (branchId) {
445
+ this.acabrnId.set(branchId);
446
+ }
447
+ }
448
+ // Load dropdowns first, then patch form
449
+ this.loadDropdownOptions();
450
+ // Wait a bit for dropdowns to load, then patch form
451
+ setTimeout(() => {
452
+ // Get branch ID for form patching
453
+ const branchIdForForm = typeof branchIdValue === 'string'
454
+ ? branchIdValue
455
+ : branchIdValue?._id || '';
456
+ const programClassId = typeof term.acapt_class_program_id_acacpm === 'string'
457
+ ? term.acapt_class_program_id_acacpm
458
+ : term.acapt_class_program_id_acacpm?._id || '';
459
+ // Set selected program class to check branchType
460
+ const selectedProgram = this.programClassOptions().find(p => p._id === programClassId);
461
+ this.selectedProgramClass.set(selectedProgram || null);
462
+ // Update branch validation based on branchType
463
+ if (this.showBranchDropdown()) {
464
+ this.classProgramTermForm.get('acapt_class_program_branch_id_acabrn')?.setValidators([Validators.required]);
465
+ }
466
+ else {
467
+ this.classProgramTermForm.get('acapt_class_program_branch_id_acabrn')?.clearValidators();
468
+ }
469
+ this.classProgramTermForm.patchValue({
470
+ acapt_code: term.acapt_code || '',
471
+ acapt_name: term.acapt_name || '',
472
+ acapt_description: term.acapt_description || term.acapt_desc || '',
473
+ acapt_class_program_id_acacpm: programClassId,
474
+ acapt_class_program_branch_id_acabrn: branchIdForForm,
475
+ acapt_parent_class_prog_term_acapt: typeof term.acapt_parent_class_prog_term_acapt === 'string'
476
+ ? term.acapt_parent_class_prog_term_acapt
477
+ : term.acapt_parent_class_prog_term_acapt?._id || '',
478
+ acapt_sequence: term.acapt_sequence || 0,
479
+ acapt_start_date: term.acapt_start_date || '',
480
+ acapt_end_date: term.acapt_end_date || '',
481
+ acapt_isactive: term.acapt_isactive ?? true,
482
+ acapt_islocked: term.acapt_islocked ?? false
483
+ }, { emitEvent: true });
484
+ // Load parent terms after form is patched
485
+ if (this.showBranchDropdown() && branchIdForForm) {
486
+ this.loadParentTermsForBranch(branchIdForForm);
487
+ }
488
+ else if (!this.showBranchDropdown() && programClassId) {
489
+ this.loadParentTermsForProgramClass(programClassId);
490
+ }
491
+ this.classProgramTermForm.get('acapt_class_program_branch_id_acabrn')?.updateValueAndValidity();
492
+ }, 300);
493
+ }
494
+ else {
495
+ this.error.set('Term data not found');
496
+ }
497
+ },
498
+ error: (err) => {
499
+ console.error('❌ Error loading term for edit:', err);
500
+ this.loading.set(false);
501
+ this.error.set('Failed to load term data');
502
+ this.notificationService.error('Failed to load term data for editing');
503
+ }
504
+ });
505
+ }
506
+ /**
507
+ * Load dropdown options
508
+ */
509
+ loadDropdownOptions() {
510
+ // Load program classes
511
+ this.loadProgramClasses();
512
+ // Load branches
513
+ this.loadClassProgramBranches();
514
+ }
515
+ /**
516
+ * Load program classes
517
+ */
518
+ loadProgramClasses() {
519
+ console.log('🔍 loadProgramClasses() CALLED');
520
+ console.log('🔍 Current acacpmId signal value:', this.acacpmId());
521
+ this.programClassService.getProgramClassList({ pagination: false })
522
+ .pipe(takeUntilDestroyed(this.destroyRef))
523
+ .subscribe({
524
+ next: (response) => {
525
+ console.log('✅ Program classes API response:', response);
526
+ if (response?.success && response.data) {
527
+ // Set options first
528
+ this.programClassOptions.set(response.data);
529
+ console.log('✅ Program class options set:', response.data.length, 'items');
530
+ // Pre-select program class if provided in route
531
+ const acacpmId = this.acacpmId();
532
+ console.log('🔍🔍🔍 CHECKING Program class ID from signal:', acacpmId);
533
+ if (acacpmId) {
534
+ // Verify the ID exists in the options
535
+ const exists = response.data.find(p => p._id === acacpmId);
536
+ console.log('🔍 Does acacpmId exist in options?', exists ? 'YES' : 'NO', exists);
537
+ // Wait for Angular to update the DOM with options, then set the value
538
+ setTimeout(() => {
539
+ const programClassControl = this.classProgramTermForm.get('acapt_class_program_id_acacpm');
540
+ console.log('📝📝📝 SETTING program class value to:', acacpmId);
541
+ console.log('📝 Current form control value BEFORE:', programClassControl?.value);
542
+ // Find and set selected program class
543
+ const selectedProgram = response.data.find(p => p._id === acacpmId);
544
+ this.selectedProgramClass.set(selectedProgram || null);
545
+ programClassControl?.setValue(acacpmId);
546
+ console.log('✅✅✅ Program class form control value AFTER:', programClassControl?.value);
547
+ console.log('✅ Form object:', this.classProgramTermForm.value);
548
+ console.log('✅ Form valid:', this.classProgramTermForm.valid);
549
+ // Load branches only if branchType is true
550
+ if (this.showBranchDropdown()) {
551
+ this.loadBranchesForProgramClass(acacpmId);
552
+ }
553
+ else {
554
+ // If no branchType, load parent terms directly using program class
555
+ this.loadParentTermsForProgramClass(acacpmId);
556
+ }
557
+ }, 50);
558
+ }
559
+ else {
560
+ console.log('⚠️⚠️⚠️ NO program class ID in acacpmId signal');
561
+ }
562
+ }
563
+ else {
564
+ console.warn('⚠️ No program class data received');
565
+ this.programClassOptions.set([]);
566
+ }
567
+ },
568
+ error: (error) => {
569
+ console.error('❌ Error loading program classes:', error);
570
+ this.programClassOptions.set([]);
571
+ }
572
+ });
573
+ }
574
+ /**
575
+ * Load class program branches
576
+ */
577
+ loadClassProgramBranches() {
578
+ const acacpmId = this.acacpmId();
579
+ if (acacpmId) {
580
+ // Only load branches if branchType is true
581
+ if (this.showBranchDropdown()) {
582
+ this.loadBranchesForProgramClass(acacpmId);
583
+ }
584
+ else {
585
+ // If no branchType, load parent terms directly
586
+ this.loadParentTermsForProgramClass(acacpmId);
587
+ }
588
+ }
589
+ }
590
+ /**
591
+ * Load branches for a specific program class
592
+ */
593
+ loadBranchesForProgramClass(programClassId) {
594
+ const payload = {
595
+ pagination: false,
596
+ pageIndex: 0,
597
+ pageSize: 100,
598
+ acabrn_class_program_id_acacpm: programClassId
599
+ };
600
+ this.classProgramBranchService.getClassProgramBranchList(payload)
601
+ .pipe(takeUntilDestroyed(this.destroyRef))
602
+ .subscribe({
603
+ next: (response) => {
604
+ console.log('✅ Class program branches loaded for program class:', programClassId, response);
605
+ if (response?.success && response.data) {
606
+ this.branchOptions.set(response.data);
607
+ // Pre-select branch if provided in route and not already set
608
+ const acabrnId = this.acabrnId();
609
+ const currentBranchId = this.classProgramTermForm.get('acapt_class_program_branch_id_acabrn')?.value;
610
+ console.log('🔍 Checking branch pre-selection - acabrnId:', acabrnId, 'currentBranchId:', currentBranchId);
611
+ if (acabrnId && !currentBranchId) {
612
+ console.log('✅ Pre-selecting branch:', acabrnId);
613
+ // Use emitEvent: true to trigger valueChanges and load parent terms
614
+ this.classProgramTermForm.patchValue({
615
+ acapt_class_program_branch_id_acabrn: acabrnId
616
+ }, { emitEvent: true });
617
+ // Directly load parent terms after branch is set (in case valueChanges doesn't fire)
618
+ setTimeout(() => {
619
+ console.log('🔄 Directly loading parent terms for branch:', acabrnId);
620
+ this.loadParentTermsForBranch(acabrnId);
621
+ }, 150);
622
+ }
623
+ else if (acabrnId && currentBranchId !== acabrnId) {
624
+ // Branch ID exists but form has different value, update it
625
+ console.log('🔄 Updating branch selection from', currentBranchId, 'to', acabrnId);
626
+ this.classProgramTermForm.patchValue({
627
+ acapt_class_program_branch_id_acabrn: acabrnId
628
+ }, { emitEvent: true });
629
+ // Directly load parent terms after branch is updated
630
+ setTimeout(() => {
631
+ console.log('🔄 Directly loading parent terms for branch:', acabrnId);
632
+ this.loadParentTermsForBranch(acabrnId);
633
+ }, 150);
634
+ }
635
+ else if (!acabrnId) {
636
+ console.log('⚠️ No branch ID found in route parameters');
637
+ }
638
+ }
639
+ else {
640
+ console.warn('⚠️ No branch data received');
641
+ this.branchOptions.set([]);
642
+ }
643
+ },
644
+ error: (error) => {
645
+ console.error('❌ Error loading branches:', error);
646
+ this.branchOptions.set([]);
647
+ }
648
+ });
649
+ }
650
+ /**
651
+ * Determine parent term based on selected branch
652
+ * This method will be called internally when branch is selected
653
+ */
654
+ determineParentTerm(branchId) {
655
+ // Find the selected branch from the options
656
+ const selectedBranch = this.branchOptions().find(branch => branch._id === branchId);
657
+ if (selectedBranch) {
658
+ console.log('🏢 Determining parent term for branch:', selectedBranch.acabrn_name);
659
+ // Load existing terms for this branch to find potential parent terms
660
+ // This will also set the parent term from route if available
661
+ this.loadParentTermsForBranch(branchId);
662
+ }
663
+ else {
664
+ // Clear parent term options if branch not found
665
+ this.parentTermOptions.set([]);
666
+ }
667
+ }
668
+ /**
669
+ * Auto-select term for program when termType=true, termProgramLevelOneConnected=true, and termLevelUpTo <= 1
670
+ */
671
+ autoSelectTermForProgram(programClassId) {
672
+ console.log('🔄 Auto-selecting term for program:', programClassId);
673
+ // Build payload to get the term for this program
674
+ const branchId = this.classProgramTermForm.get('acapt_class_program_branch_id_acabrn')?.value;
675
+ const payload = new MClassProgramTerm({
676
+ pageIndex: 0,
677
+ pageSize: 1, // Only need one term
678
+ query: "",
679
+ sort: {
680
+ key: 'acapt_sequence',
681
+ order: 'asc'
682
+ },
683
+ acapt_class_program_id_acacpm: programClassId,
684
+ acapt_class_prg_branch_acabrn: branchId || ''
685
+ });
686
+ this.classProgramTermService.getClassProgramTermList(payload)
687
+ .pipe(takeUntilDestroyed(this.destroyRef))
688
+ .subscribe({
689
+ next: (response) => {
690
+ if (response?.success && response.data && response.data.length > 0) {
691
+ const term = response.data[0];
692
+ const termId = typeof term._id === 'string' ? term._id : term._id?._id || '';
693
+ if (termId) {
694
+ console.log('✅ Auto-selected term:', termId, term.acapt_name);
695
+ // Auto-select the term in the parent term field
696
+ this.classProgramTermForm.patchValue({
697
+ acapt_parent_class_prog_term_acapt: termId
698
+ }, { emitEvent: true });
699
+ }
700
+ }
701
+ else {
702
+ console.warn('⚠️ No term found for program:', programClassId);
703
+ }
704
+ },
705
+ error: (error) => {
706
+ console.error('❌ Error auto-selecting term:', error);
707
+ }
708
+ });
709
+ }
710
+ /**
711
+ * Load parent terms for a specific program class (when branchType is false)
712
+ */
713
+ loadParentTermsForProgramClass(programClassId) {
714
+ console.log('🏢🏢🏢 loadParentTermsForProgramClass CALLED with programClassId:', programClassId);
715
+ if (!programClassId) {
716
+ console.warn('⚠️ Missing programClassId');
717
+ this.parentTermOptions.set([]);
718
+ return;
719
+ }
720
+ console.log('🏢 Making API call for parent terms - program class:', programClassId);
721
+ const payload = new MClassProgramTerm({
722
+ pageIndex: 0,
723
+ pageSize: 1000,
724
+ query: "",
725
+ sort: {
726
+ key: 'acapt_name',
727
+ order: 'asc'
728
+ },
729
+ acapt_class_program_id_acacpm: programClassId,
730
+ acapt_class_prg_branch_acabrn: '' // Empty string when branchType is false
731
+ });
732
+ console.log('📤 API Payload for parent terms (no branch):', JSON.stringify(payload, null, 2));
733
+ this.classProgramTermService.getClassProgramTermList(payload)
734
+ .pipe(takeUntilDestroyed(this.destroyRef))
735
+ .subscribe({
736
+ next: (response) => {
737
+ console.log('✅ Parent terms loaded (no branch):', response);
738
+ if (response?.success && response.data) {
739
+ // All terms can be parent terms (for child term creation)
740
+ const parentTerms = response.data;
741
+ // Normalize parent field to string ID for tree view compatibility
742
+ const normalizedTerms = parentTerms.map(term => {
743
+ const normalized = { ...term };
744
+ // Normalize parent field - ensure it's always a string ID or empty string
745
+ if (normalized.acapt_parent_class_prog_term_acapt) {
746
+ if (typeof normalized.acapt_parent_class_prog_term_acapt === 'object') {
747
+ normalized.acapt_parent_class_prog_term_acapt = normalized.acapt_parent_class_prog_term_acapt?._id || '';
748
+ }
749
+ else if (typeof normalized.acapt_parent_class_prog_term_acapt === 'string') {
750
+ normalized.acapt_parent_class_prog_term_acapt = normalized.acapt_parent_class_prog_term_acapt.trim() || '';
751
+ }
752
+ }
753
+ else {
754
+ normalized.acapt_parent_class_prog_term_acapt = '';
755
+ }
756
+ return normalized;
757
+ });
758
+ // Set options directly - tree view will be handled by select component
759
+ this.parentTermOptions.set(normalizedTerms);
760
+ console.log('✅ Parent term options set (no branch):', normalizedTerms.length, 'options');
761
+ // Set parent term from route after options are loaded
762
+ const parentId = this.parentTermId();
763
+ if (parentId && !this.isEditMode() && !this.isViewMode()) {
764
+ setTimeout(() => {
765
+ const parentTermControl = this.classProgramTermForm.get('acapt_parent_class_prog_term_acapt');
766
+ if (parentTermControl) {
767
+ parentTermControl.setValue(parentId, { emitEvent: true });
768
+ this.cdr.detectChanges();
769
+ }
770
+ }, 200);
771
+ }
772
+ }
773
+ else {
774
+ console.warn('⚠️ No parent term data received');
775
+ this.parentTermOptions.set([]);
776
+ }
777
+ },
778
+ error: (error) => {
779
+ console.error('❌ Error loading parent terms:', error);
780
+ this.parentTermOptions.set([]);
781
+ }
782
+ });
783
+ }
784
+ /**
785
+ * Load parent terms for a specific branch
786
+ */
787
+ loadParentTermsForBranch(branchId) {
788
+ const programClassId = this.classProgramTermForm.get('acapt_class_program_id_acacpm')?.value;
789
+ console.log('🏢🏢🏢 loadParentTermsForBranch CALLED with branchId:', branchId, 'programClassId:', programClassId);
790
+ if (!programClassId || !branchId) {
791
+ console.warn('⚠️ Missing required IDs - programClassId:', programClassId, 'branchId:', branchId);
792
+ this.parentTermOptions.set([]);
793
+ return;
794
+ }
795
+ console.log('🏢 Making API call for parent terms - branch:', branchId, 'program class:', programClassId);
796
+ const payload = new MClassProgramTerm({
797
+ pageIndex: 0,
798
+ pageSize: 1000,
799
+ query: "",
800
+ sort: {
801
+ key: 'acapt_name',
802
+ order: 'asc'
803
+ },
804
+ acapt_class_program_id_acacpm: programClassId,
805
+ acapt_class_prg_branch_acabrn: branchId
806
+ });
807
+ console.log('📤 API Payload for parent terms:', JSON.stringify(payload, null, 2));
808
+ this.classProgramTermService.getClassProgramTermList(payload)
809
+ .pipe(takeUntilDestroyed(this.destroyRef))
810
+ .subscribe({
811
+ next: (response) => {
812
+ console.log('✅ Parent terms loaded:', response);
813
+ if (response?.success && response.data) {
814
+ // All terms can be parent terms (for child term creation)
815
+ const parentTerms = response.data;
816
+ // Normalize parent field to string ID for tree view compatibility
817
+ const normalizedTerms = parentTerms.map(term => {
818
+ const normalized = { ...term };
819
+ // Normalize parent field - ensure it's always a string ID or empty string
820
+ if (normalized.acapt_parent_class_prog_term_acapt) {
821
+ if (typeof normalized.acapt_parent_class_prog_term_acapt === 'object') {
822
+ // If it's an object, extract the _id
823
+ normalized.acapt_parent_class_prog_term_acapt = normalized.acapt_parent_class_prog_term_acapt?._id || '';
824
+ }
825
+ else if (typeof normalized.acapt_parent_class_prog_term_acapt === 'string') {
826
+ // Already a string, ensure it's not empty or null
827
+ normalized.acapt_parent_class_prog_term_acapt = normalized.acapt_parent_class_prog_term_acapt.trim() || '';
828
+ }
829
+ }
830
+ else {
831
+ // No parent - set to empty string for tree view
832
+ normalized.acapt_parent_class_prog_term_acapt = '';
833
+ }
834
+ return normalized;
835
+ });
836
+ // Set options directly - tree view will be handled by select component
837
+ this.parentTermOptions.set(normalizedTerms);
838
+ console.log('✅ Parent term options set:', normalizedTerms.length, 'options');
839
+ console.log('🌳 Tree view enabled - options will be displayed in tree structure');
840
+ console.log('🌳 Sample normalized term:', normalizedTerms[0] ? {
841
+ _id: normalizedTerms[0]._id,
842
+ name: normalizedTerms[0].acapt_name,
843
+ parent: normalizedTerms[0].acapt_parent_class_prog_term_acapt
844
+ } : 'No terms');
845
+ // Set parent term from route after options are loaded
846
+ const parentId = this.parentTermId();
847
+ console.log('🔍 Checking parent term pre-selection - parentId:', parentId);
848
+ if (parentId && !this.isEditMode() && !this.isViewMode()) {
849
+ // Check if the parent ID exists in the options
850
+ const parentExists = normalizedTerms.find(term => term._id === parentId);
851
+ console.log('🔍 Parent term exists in options:', !!parentExists, parentExists?.acapt_name);
852
+ if (parentExists) {
853
+ // Use longer timeout to ensure DOM is fully rendered
854
+ setTimeout(() => {
855
+ console.log('✅ Setting parent term to:', parentId);
856
+ const parentTermControl = this.classProgramTermForm.get('acapt_parent_class_prog_term_acapt');
857
+ if (parentTermControl) {
858
+ // Use setValue instead of patchValue for better control
859
+ parentTermControl.setValue(parentId, { emitEvent: true });
860
+ console.log('✅✅✅ Parent term form control value set to:', parentTermControl.value);
861
+ // Force change detection to update the view
862
+ this.cdr.detectChanges();
863
+ // Additional timeout to ensure dropdown displays the selected value
864
+ setTimeout(() => {
865
+ this.cdr.detectChanges();
866
+ console.log('✅✅✅ Change detection triggered again for parent term dropdown');
867
+ }, 50);
868
+ }
869
+ }, 200); // Increased timeout to 200ms for DOM rendering
870
+ }
871
+ else {
872
+ console.warn('⚠️ Parent term ID not found in options:', parentId);
873
+ }
874
+ }
875
+ else {
876
+ console.log('⚠️ Not pre-selecting parent term - parentId:', parentId, 'isEdit:', this.isEditMode(), 'isView:', this.isViewMode());
877
+ }
878
+ }
879
+ else {
880
+ console.warn('⚠️ No parent term data received');
881
+ this.parentTermOptions.set([]);
882
+ }
883
+ },
884
+ error: (error) => {
885
+ console.error('❌ Error loading parent terms:', error);
886
+ this.parentTermOptions.set([]);
887
+ }
888
+ });
889
+ }
890
+ /**
891
+ * Load parent term details for date validation
892
+ * This method will be called when a parent term is selected
893
+ */
894
+ loadParentTermDetails(parentTermId) {
895
+ if (!parentTermId) {
896
+ // Clear date constraints when no parent is selected
897
+ this.clearDateConstraints();
898
+ return;
899
+ }
900
+ // TODO: Implement API call to get parent term details
901
+ // For now, we'll use mock data or implement based on your API
902
+ console.log('🏢 Loading parent term details for ID:', parentTermId);
903
+ // Example implementation - replace with actual API call
904
+ // this.classProgramTermService.getClassProgramTermById({ _id: parentTermId })
905
+ // .pipe(takeUntilDestroyed(this.destroyRef))
906
+ // .subscribe({
907
+ // next: (response) => {
908
+ // if (response?.success && response.data) {
909
+ // const parentTerm = response.data;
910
+ // this.setDateConstraints(parentTerm.acapt_start_date, parentTerm.acapt_end_date);
911
+ // }
912
+ // },
913
+ // error: (error) => {
914
+ // console.error('❌ Error loading parent term details:', error);
915
+ // }
916
+ // });
917
+ }
918
+ /**
919
+ * Set date constraints based on parent term dates
920
+ */
921
+ setDateConstraints(parentStartDate, parentEndDate) {
922
+ console.log('🏢 Setting date constraints:', { parentStartDate, parentEndDate });
923
+ // Update form validation to ensure child dates are within parent range
924
+ const startDateControl = this.classProgramTermForm.get('acapt_start_date');
925
+ const endDateControl = this.classProgramTermForm.get('acapt_end_date');
926
+ if (startDateControl && endDateControl) {
927
+ // Add custom validators for date range
928
+ startDateControl.setValidators([
929
+ this.dateRangeValidator(parentStartDate, parentEndDate, 'start')
930
+ ]);
931
+ endDateControl.setValidators([
932
+ this.dateRangeValidator(parentStartDate, parentEndDate, 'end')
933
+ ]);
934
+ // Update validation
935
+ startDateControl.updateValueAndValidity();
936
+ endDateControl.updateValueAndValidity();
937
+ }
938
+ }
939
+ /**
940
+ * Clear date constraints when no parent is selected
941
+ */
942
+ clearDateConstraints() {
943
+ const startDateControl = this.classProgramTermForm.get('acapt_start_date');
944
+ const endDateControl = this.classProgramTermForm.get('acapt_end_date');
945
+ if (startDateControl && endDateControl) {
946
+ // Remove custom validators
947
+ startDateControl.clearValidators();
948
+ endDateControl.clearValidators();
949
+ // Update validation
950
+ startDateControl.updateValueAndValidity();
951
+ endDateControl.updateValueAndValidity();
952
+ }
953
+ }
954
+ /**
955
+ * Custom validator for date range constraints
956
+ */
957
+ dateRangeValidator(parentStartDate, parentEndDate, dateType) {
958
+ return (control) => {
959
+ if (!control.value || !parentStartDate || !parentEndDate) {
960
+ return null; // No validation if no date or parent dates
961
+ }
962
+ const selectedDate = new Date(control.value);
963
+ const parentStart = new Date(parentStartDate);
964
+ const parentEnd = new Date(parentEndDate);
965
+ if (dateType === 'start') {
966
+ // Start date should be >= parent start date and < parent end date
967
+ if (selectedDate < parentStart || selectedDate >= parentEnd) {
968
+ return {
969
+ dateRangeError: {
970
+ message: `Start date must be between ${parentStartDate} and ${parentEndDate}`
971
+ }
972
+ };
973
+ }
974
+ }
975
+ else if (dateType === 'end') {
976
+ // End date should be > parent start date and <= parent end date
977
+ if (selectedDate <= parentStart || selectedDate > parentEnd) {
978
+ return {
979
+ dateRangeError: {
980
+ message: `End date must be between ${parentStartDate} and ${parentEndDate}`
981
+ }
982
+ };
983
+ }
984
+ }
985
+ return null; // Valid
986
+ };
987
+ }
988
+ /**
989
+ * Update minimum date for end date based on start date
990
+ */
991
+ updateEndDateMinDate(startDate) {
992
+ if (startDate) {
993
+ // Set the minimum date for end date to be the start date
994
+ this.endDateMinDate.set(startDate);
995
+ // If end date is already set and is before the new start date, clear it
996
+ const endDate = this.classProgramTermForm.get('acapt_end_date')?.value;
997
+ if (endDate && endDate < startDate) {
998
+ this.classProgramTermForm.patchValue({
999
+ acapt_end_date: ''
1000
+ });
1001
+ }
1002
+ console.log('🏢 Updated end date minimum date to:', startDate);
1003
+ }
1004
+ else {
1005
+ // Clear minimum date constraint if no start date
1006
+ this.endDateMinDate.set('');
1007
+ }
1008
+ }
1009
+ onSubmit() {
1010
+ if (this.isViewMode()) {
1011
+ this.router.navigate(['/control-panel/program-term-management']);
1012
+ return;
1013
+ }
1014
+ if (this.classProgramTermForm.invalid) {
1015
+ this.notificationService.error('Please fill in all required fields correctly.');
1016
+ this.markFormGroupTouched();
1017
+ return;
1018
+ }
1019
+ this.loading.set(true);
1020
+ this.error.set(null);
1021
+ const formData = this.classProgramTermForm.value;
1022
+ console.log('Class Program Term Form Data:', formData);
1023
+ // Prepare payload for API call
1024
+ const payload = {
1025
+ acapt_code: formData.acapt_code,
1026
+ acapt_name: formData.acapt_name,
1027
+ acapt_class_program_id_acacpm: formData.acapt_class_program_id_acacpm,
1028
+ acapt_class_prg_branch_acabrn: formData.acapt_class_program_branch_id_acabrn,
1029
+ acapt_parent_class_prog_term_acapt: formData.acapt_parent_class_prog_term_acapt || null,
1030
+ acapt_start_date: formData.acapt_start_date,
1031
+ acapt_end_date: formData.acapt_end_date,
1032
+ acapt_isactive: formData.acapt_isactive,
1033
+ acapt_islocked: formData.acapt_islocked
1034
+ };
1035
+ // Add _id for edit mode
1036
+ if (this.isEditMode() && this.classProgramTermId()) {
1037
+ payload._id = this.classProgramTermId();
1038
+ }
1039
+ console.log('API Payload:', payload);
1040
+ // Make API call
1041
+ this.classProgramTermService.saveClassProgramTerm(payload)
1042
+ .pipe(takeUntilDestroyed(this.destroyRef))
1043
+ .subscribe({
1044
+ next: (response) => {
1045
+ console.log('✅ Class program term saved successfully:', response);
1046
+ if (response?.success) {
1047
+ const action = this.isEditMode() ? 'updated' : 'created';
1048
+ this.notificationService.success(`Class program term has been ${action} successfully.`);
1049
+ // Navigate back to program term listing page (not section listing)
1050
+ // The listing page will auto-reload via router events subscription
1051
+ this.router.navigate(['/control-panel/program-term-management']);
1052
+ }
1053
+ else {
1054
+ this.error.set(response?.message || 'Failed to save class program term');
1055
+ this.notificationService.error(response?.message || 'Failed to save class program term');
1056
+ }
1057
+ this.loading.set(false);
1058
+ },
1059
+ error: (error) => {
1060
+ console.error('❌ Error saving class program term:', error);
1061
+ this.error.set('Failed to save class program term');
1062
+ this.notificationService.error('Failed to save class program term. Please try again.');
1063
+ this.loading.set(false);
1064
+ }
1065
+ });
1066
+ }
1067
+ /**
1068
+ * Mark all form controls as touched to trigger validation display
1069
+ */
1070
+ markFormGroupTouched() {
1071
+ Object.keys(this.classProgramTermForm.controls).forEach(key => {
1072
+ const control = this.classProgramTermForm.get(key);
1073
+ control?.markAsTouched();
1074
+ });
1075
+ }
1076
+ resetForm() {
1077
+ this.classProgramTermForm.reset({
1078
+ acapt_isactive: true,
1079
+ acapt_islocked: false
1080
+ });
1081
+ // Clear options when form is reset
1082
+ this.branchOptions.set([]);
1083
+ this.parentTermOptions.set([]);
1084
+ // Clear date constraints
1085
+ this.clearDateConstraints();
1086
+ this.endDateMinDate.set('');
1087
+ }
1088
+ /**
1089
+ * Reset only Term Code, Term Name, and Description fields after successful save
1090
+ */
1091
+ resetFormFields() {
1092
+ // Get current values to preserve
1093
+ const currentProgramClass = this.classProgramTermForm.get('acapt_class_program_id_acacpm')?.value;
1094
+ const currentBranch = this.classProgramTermForm.get('acapt_class_program_branch_id_acabrn')?.value;
1095
+ const currentStartDate = this.classProgramTermForm.get('acapt_start_date')?.value;
1096
+ const currentEndDate = this.classProgramTermForm.get('acapt_end_date')?.value;
1097
+ const currentIsActive = this.classProgramTermForm.get('acapt_isactive')?.value;
1098
+ const currentIsLocked = this.classProgramTermForm.get('acapt_islocked')?.value;
1099
+ // Reset only the specified fields
1100
+ this.classProgramTermForm.patchValue({
1101
+ acapt_code: '',
1102
+ acapt_name: '',
1103
+ acapt_description: '',
1104
+ // Preserve other fields
1105
+ acapt_class_program_id_acacpm: currentProgramClass,
1106
+ acapt_class_program_branch_id_acabrn: currentBranch,
1107
+ acapt_start_date: currentStartDate,
1108
+ acapt_end_date: currentEndDate,
1109
+ acapt_isactive: currentIsActive,
1110
+ acapt_islocked: currentIsLocked
1111
+ });
1112
+ // Clear validation errors for reset fields
1113
+ this.classProgramTermForm.get('acapt_code')?.setErrors(null);
1114
+ this.classProgramTermForm.get('acapt_name')?.setErrors(null);
1115
+ this.classProgramTermForm.get('acapt_description')?.setErrors(null);
1116
+ }
1117
+ /**
1118
+ * Go back to class program term list
1119
+ */
1120
+ goBackToClassProgramTermList() {
1121
+ this.router.navigate(['/control-panel/program-term-management']);
1122
+ }
1123
+ /**
1124
+ * Cancel form and navigate back to listing page
1125
+ */
1126
+ cancelForm() {
1127
+ this.goBackToClassProgramTermList();
1128
+ }
1129
+ /**
1130
+ * Get page title based on mode
1131
+ */
1132
+ getPageTitle() {
1133
+ if (this.isViewMode())
1134
+ return 'View Class Program Term';
1135
+ return this.isEditMode() ? 'Edit Class Program Term' : 'Create New Class Program Term';
1136
+ }
1137
+ /**
1138
+ * Handle Active card click to toggle checkbox
1139
+ */
1140
+ onActiveCardClick() {
1141
+ if (this.isViewMode()) {
1142
+ return; // Don't allow changes in view mode
1143
+ }
1144
+ const currentValue = this.classProgramTermForm.get('acapt_isactive')?.value;
1145
+ this.classProgramTermForm.patchValue({
1146
+ acapt_isactive: !currentValue
1147
+ });
1148
+ }
1149
+ /**
1150
+ * Handle Locked card click to toggle checkbox
1151
+ */
1152
+ onLockedCardClick() {
1153
+ if (this.isViewMode()) {
1154
+ return; // Don't allow changes in view mode
1155
+ }
1156
+ const currentValue = this.classProgramTermForm.get('acapt_islocked')?.value;
1157
+ this.classProgramTermForm.patchValue({
1158
+ acapt_islocked: !currentValue
1159
+ });
1160
+ }
1161
+ /**
1162
+ * Cleanup when component is destroyed
1163
+ */
1164
+ ngOnDestroy() {
1165
+ console.log('🧹 ClassProgramTermCreateComponent: Cleaning up component state');
1166
+ // Reset all signals to their initial state
1167
+ this.loading.set(false);
1168
+ this.error.set(null);
1169
+ this.classProgramTermId.set('');
1170
+ this.isEditMode.set(false);
1171
+ this.programClassOptions.set([]);
1172
+ this.branchOptions.set([]);
1173
+ this.parentTermOptions.set([]);
1174
+ // Reset form to initial state
1175
+ this.resetForm();
1176
+ console.log('🧹 ClassProgramTermCreateComponent: Component state cleaned up');
1177
+ }
1178
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: ClassProgramTermCreateComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1179
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.7", type: ClassProgramTermCreateComponent, isStandalone: true, selector: "cide-academics-class-program-term-create", ngImport: i0, template: "<!-- \n CLASS PROGRAM TERM MASTER FORM\n \n Enterprise-Level Styling with Tailwind CSS\n Features: Responsive grids, proper typography, enhanced user experience\n-->\n\n<cide-lyt-shared-wrapper [shared_wrapper_setup_param]=\"{ sypg_page_code: 'class_program_term' }\"\n [breadcrumb_data]=\"breadcrumbData()\">\n \n <form class=\"tw-w-full tw-table tw-h-full tw-bg-transparent\" [formGroup]=\"classProgramTermForm\"\n [class.tw-opacity-60]=\"loading()\" (ngSubmit)=\"onSubmit()\">\n\n <!-- Form Content -->\n <div class=\"tw-table-row tw-h-0\">\n <div class=\"tw-table-cell tw-w-full tw-px-6 tw-py-6 tw-overflow-y-auto tw-h-full\">\n <div class=\"tw-transition-opacity tw-duration-300\" [class.tw-opacity-60]=\"loading()\">\n <!-- Class Program Term Information -->\n <div class=\"tw-space-y-6\">\n <!-- Program Class, Branch, and Parent Term at the top -->\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-3 tw-gap-6\"\n [class.md:tw-grid-cols-2]=\"!showBranchDropdown()\">\n <div class=\"tw-space-y-2\">\n <label class=\"tw-text-sm tw-font-medium tw-text-gray-700\">Program Class *</label>\n <cide-ele-select \n formControlName=\"acapt_class_program_id_acacpm\" \n placeholder=\"Select program class\"\n [disabled]=\"isViewMode()\" \n valueKey=\"_id\" \n labelKey=\"acacpm_alise_title\" \n [options]=\"programClassOptions()\">\n </cide-ele-select>\n </div>\n\n @if (showBranchDropdown()) {\n <div class=\"tw-space-y-2\">\n <label class=\"tw-text-sm tw-font-medium tw-text-gray-700\">Specialization *</label>\n <cide-ele-select \n formControlName=\"acapt_class_program_branch_id_acabrn\" \n placeholder=\"Select specialization\"\n [disabled]=\"isViewMode()\" \n valueKey=\"_id\" \n labelKey=\"acabrn_name\" \n [options]=\"branchOptions()\">\n </cide-ele-select>\n </div>\n }\n\n @if (showTermDropdown()) {\n <div class=\"tw-space-y-2\">\n <label class=\"tw-text-sm tw-font-medium tw-text-gray-700\">Parent Term (Optional)</label>\n <cide-ele-select \n formControlName=\"acapt_parent_class_prog_term_acapt\" \n placeholder=\"Select parent term\"\n [disabled]=\"isViewMode()\" \n valueKey=\"_id\" \n labelKey=\"acapt_name\" \n [options]=\"parentTermOptions()\"\n [treeView]=\"{ enabled: true, primaryKey: '_id', foreignKey: 'acapt_parent_class_prog_term_acapt' }\">\n </cide-ele-select>\n </div>\n }\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=\"Term Code *\" formControlName=\"acapt_code\" placeholder=\"e.g., T1, T2, T3\"\n size=\"md\" leadingIcon=\"code\">\n </cide-ele-input>\n\n <cide-ele-input label=\"Term Name *\" formControlName=\"acapt_name\"\n placeholder=\"e.g., First Term, Second Term\" size=\"md\" leadingIcon=\"schedule\">\n </cide-ele-input>\n </div>\n\n <div>\n <cide-ele-textarea label=\"Description\" formControlName=\"acapt_description\"\n placeholder=\"Enter detailed description of the term...\" 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 id=\"acapt_start_date\" label=\"Start Date\" formControlName=\"acapt_start_date\" type=\"date\"\n size=\"md\" leadingIcon=\"event\">\n </cide-ele-input>\n\n <cide-ele-input id=\"acapt_end_date\" label=\"End Date\" formControlName=\"acapt_end_date\" type=\"date\"\n [min]=\"endDateMinDate()\" size=\"md\" leadingIcon=\"event\">\n </cide-ele-input>\n </div>\n\n <div class=\"tw-p-3 tw-bg-blue-50 tw-border tw-border-blue-200 tw-rounded-lg\">\n <div class=\"tw-flex tw-items-center tw-gap-2\">\n <cide-ele-icon name=\"info\" class=\"tw-w-4 tw-h-4 tw-text-blue-500\"></cide-ele-icon>\n <span class=\"tw-text-sm tw-text-blue-700\">\n Sequence will be automatically managed through drag-and-drop on the listing page\n </span>\n </div>\n </div>\n\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-6\">\n <div\n 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\"\n [class.tw-cursor-not-allowed]=\"isViewMode()\"\n [class.tw-opacity-60]=\"isViewMode()\"\n (click)=\"onActiveCardClick()\">\n <cide-ele-input formControlName=\"acapt_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 term</span>\n </div>\n </div>\n\n <div\n 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\"\n [class.tw-cursor-not-allowed]=\"isViewMode()\"\n [class.tw-opacity-60]=\"isViewMode()\"\n (click)=\"onLockedCardClick()\">\n <cide-ele-input formControlName=\"acapt_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 </div>\n\n <!-- Error Display -->\n @if (error()) {\n <div class=\"tw-mt-6 tw-p-4 tw-bg-red-50 tw-border tw-border-red-200 tw-rounded-lg\">\n <div class=\"tw-flex tw-items-center tw-gap-2\">\n <cide-ele-icon variant=\"red\" size=\"sm\">error</cide-ele-icon>\n <span class=\"tw-text-sm tw-font-medium tw-text-red-800\">{{ error() }}</span>\n </div>\n </div>\n }\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-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() || classProgramTermForm.invalid\"\n [loading]=\"loading()\" leftIcon=\"save\">\n {{ isEditMode() ? 'Update Class Program Term' : 'Create Class Program Term' }}\n </button>\n </div>\n </div>\n </div>\n </form>\n</cide-lyt-shared-wrapper>\n\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: 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], cide-ele-button", 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", "size", "fill", "labelPlacement", "labelDir", "leadingIcon", "trailingIcon", "clearInput", "options", "multiple", "searchable", "showSearchInput", "loading", "valueKey", "labelKey", "treeView"], outputs: ["ngModelChange", "change", "searchChange"] }, { kind: "component", type: CideLytSharedWrapperComponent, selector: "cide-lyt-shared-wrapper", inputs: ["shared_wrapper_setup_param", "breadcrumb_data"] }] });
1180
+ }
1181
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: ClassProgramTermCreateComponent, decorators: [{
1182
+ type: Component,
1183
+ args: [{ selector: 'cide-academics-class-program-term-create', standalone: true, imports: [
1184
+ CommonModule,
1185
+ ReactiveFormsModule,
1186
+ CideInputComponent,
1187
+ CideTextareaComponent,
1188
+ CideEleButtonComponent,
1189
+ CideIconComponent,
1190
+ CideSelectComponent,
1191
+ CideLytSharedWrapperComponent
1192
+ ], template: "<!-- \n CLASS PROGRAM TERM MASTER FORM\n \n Enterprise-Level Styling with Tailwind CSS\n Features: Responsive grids, proper typography, enhanced user experience\n-->\n\n<cide-lyt-shared-wrapper [shared_wrapper_setup_param]=\"{ sypg_page_code: 'class_program_term' }\"\n [breadcrumb_data]=\"breadcrumbData()\">\n \n <form class=\"tw-w-full tw-table tw-h-full tw-bg-transparent\" [formGroup]=\"classProgramTermForm\"\n [class.tw-opacity-60]=\"loading()\" (ngSubmit)=\"onSubmit()\">\n\n <!-- Form Content -->\n <div class=\"tw-table-row tw-h-0\">\n <div class=\"tw-table-cell tw-w-full tw-px-6 tw-py-6 tw-overflow-y-auto tw-h-full\">\n <div class=\"tw-transition-opacity tw-duration-300\" [class.tw-opacity-60]=\"loading()\">\n <!-- Class Program Term Information -->\n <div class=\"tw-space-y-6\">\n <!-- Program Class, Branch, and Parent Term at the top -->\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-3 tw-gap-6\"\n [class.md:tw-grid-cols-2]=\"!showBranchDropdown()\">\n <div class=\"tw-space-y-2\">\n <label class=\"tw-text-sm tw-font-medium tw-text-gray-700\">Program Class *</label>\n <cide-ele-select \n formControlName=\"acapt_class_program_id_acacpm\" \n placeholder=\"Select program class\"\n [disabled]=\"isViewMode()\" \n valueKey=\"_id\" \n labelKey=\"acacpm_alise_title\" \n [options]=\"programClassOptions()\">\n </cide-ele-select>\n </div>\n\n @if (showBranchDropdown()) {\n <div class=\"tw-space-y-2\">\n <label class=\"tw-text-sm tw-font-medium tw-text-gray-700\">Specialization *</label>\n <cide-ele-select \n formControlName=\"acapt_class_program_branch_id_acabrn\" \n placeholder=\"Select specialization\"\n [disabled]=\"isViewMode()\" \n valueKey=\"_id\" \n labelKey=\"acabrn_name\" \n [options]=\"branchOptions()\">\n </cide-ele-select>\n </div>\n }\n\n @if (showTermDropdown()) {\n <div class=\"tw-space-y-2\">\n <label class=\"tw-text-sm tw-font-medium tw-text-gray-700\">Parent Term (Optional)</label>\n <cide-ele-select \n formControlName=\"acapt_parent_class_prog_term_acapt\" \n placeholder=\"Select parent term\"\n [disabled]=\"isViewMode()\" \n valueKey=\"_id\" \n labelKey=\"acapt_name\" \n [options]=\"parentTermOptions()\"\n [treeView]=\"{ enabled: true, primaryKey: '_id', foreignKey: 'acapt_parent_class_prog_term_acapt' }\">\n </cide-ele-select>\n </div>\n }\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=\"Term Code *\" formControlName=\"acapt_code\" placeholder=\"e.g., T1, T2, T3\"\n size=\"md\" leadingIcon=\"code\">\n </cide-ele-input>\n\n <cide-ele-input label=\"Term Name *\" formControlName=\"acapt_name\"\n placeholder=\"e.g., First Term, Second Term\" size=\"md\" leadingIcon=\"schedule\">\n </cide-ele-input>\n </div>\n\n <div>\n <cide-ele-textarea label=\"Description\" formControlName=\"acapt_description\"\n placeholder=\"Enter detailed description of the term...\" 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 id=\"acapt_start_date\" label=\"Start Date\" formControlName=\"acapt_start_date\" type=\"date\"\n size=\"md\" leadingIcon=\"event\">\n </cide-ele-input>\n\n <cide-ele-input id=\"acapt_end_date\" label=\"End Date\" formControlName=\"acapt_end_date\" type=\"date\"\n [min]=\"endDateMinDate()\" size=\"md\" leadingIcon=\"event\">\n </cide-ele-input>\n </div>\n\n <div class=\"tw-p-3 tw-bg-blue-50 tw-border tw-border-blue-200 tw-rounded-lg\">\n <div class=\"tw-flex tw-items-center tw-gap-2\">\n <cide-ele-icon name=\"info\" class=\"tw-w-4 tw-h-4 tw-text-blue-500\"></cide-ele-icon>\n <span class=\"tw-text-sm tw-text-blue-700\">\n Sequence will be automatically managed through drag-and-drop on the listing page\n </span>\n </div>\n </div>\n\n <div class=\"tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-6\">\n <div\n 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\"\n [class.tw-cursor-not-allowed]=\"isViewMode()\"\n [class.tw-opacity-60]=\"isViewMode()\"\n (click)=\"onActiveCardClick()\">\n <cide-ele-input formControlName=\"acapt_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 term</span>\n </div>\n </div>\n\n <div\n 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\"\n [class.tw-cursor-not-allowed]=\"isViewMode()\"\n [class.tw-opacity-60]=\"isViewMode()\"\n (click)=\"onLockedCardClick()\">\n <cide-ele-input formControlName=\"acapt_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 </div>\n\n <!-- Error Display -->\n @if (error()) {\n <div class=\"tw-mt-6 tw-p-4 tw-bg-red-50 tw-border tw-border-red-200 tw-rounded-lg\">\n <div class=\"tw-flex tw-items-center tw-gap-2\">\n <cide-ele-icon variant=\"red\" size=\"sm\">error</cide-ele-icon>\n <span class=\"tw-text-sm tw-font-medium tw-text-red-800\">{{ error() }}</span>\n </div>\n </div>\n }\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-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() || classProgramTermForm.invalid\"\n [loading]=\"loading()\" leftIcon=\"save\">\n {{ isEditMode() ? 'Update Class Program Term' : 'Create Class Program Term' }}\n </button>\n </div>\n </div>\n </div>\n </form>\n</cide-lyt-shared-wrapper>\n\n" }]
1193
+ }], ctorParameters: () => [] });
1194
+
1195
+ export { ClassProgramTermCreateComponent };
1196
+ //# sourceMappingURL=cloud-ide-academics-class-program-term-create.component-B-7JRpVE.mjs.map