/** * Copyright since 2025 Mifos Initiative * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /** Angular Imports */ import { Component, OnInit, inject } from '@angular/core'; import { UntypedFormGroup, UntypedFormBuilder, UntypedFormArray, Validators, ReactiveFormsModule } from '@angular/forms'; import { Router, ActivatedRoute, RouterLink } from '@angular/router'; import { MatDialog } from '@angular/material/dialog'; import { CdkDragDrop, moveItemInArray, CdkDropList, CdkDrag } from '@angular/cdk/drag-drop'; /** Custom Services */ import { SystemService } from '../../system.service'; /** Custom Components */ import { CancelDialogComponent } from '../../../shared/cancel-dialog/cancel-dialog.component'; import { CdkTextareaAutosize } from '@angular/cdk/text-field'; import { MatButton, MatIconButton } from '@angular/material/button'; import { FaIconComponent } from '@fortawesome/angular-fontawesome'; import { MatDivider } from '@angular/material/divider'; import { MatTooltip } from '@angular/material/tooltip'; import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module'; import { AlertService } from 'app/core/alert/alert.service'; /** * Create survey component. */ @Component({ selector: 'mifosx-create-survey', templateUrl: './create-survey.component.html', styleUrls: ['./create-survey.component.scss'], imports: [ ...STANDALONE_SHARED_IMPORTS, CdkTextareaAutosize, CdkDropList, CdkDrag, FaIconComponent, MatDivider, MatIconButton, MatTooltip ] }) export class CreateSurveyComponent implements OnInit { private formBuilder = inject(UntypedFormBuilder); private systemService = inject(SystemService); private route = inject(ActivatedRoute); private router = inject(Router); dialog = inject(MatDialog); private alertService = inject(AlertService); /** Survey form. */ surveyForm: UntypedFormGroup; /** * Creates the survey form. */ ngOnInit() { this.createSurveyForm(); } /** * Creates the survey form. */ createSurveyForm() { this.surveyForm = this.formBuilder.group({ key: [ '', Validators.required ], name: [ '', Validators.required ], countryCode: [ '', [ Validators.required, Validators.pattern('^\\s*([A-Za-z]{2})?\\s*$') ] ], description: [''], questionDatas: this.formBuilder.array([]) }); } /** * Gets the questions form array. * @returns {FormArray} Questions form array. */ get questionDatas(): UntypedFormArray { return this.surveyForm.get('questionDatas') as UntypedFormArray; } /** * Gets the responses form array. * @param {number} questionIndex Index of question to retrieve responses from. * @returns {FormArray} Responses form array. */ getResponseDatas(questionIndex: number): UntypedFormArray { return this.surveyForm.get([ 'questionDatas', questionIndex, 'responseDatas' ]) as UntypedFormArray; } /** * Creates a question form group * @returns {FormGroup} Question form group. */ createQuestionForm(): UntypedFormGroup { return this.formBuilder.group({ key: [ '', Validators.required ], text: [ '', Validators.required ], description: [''], responseDatas: this.formBuilder.array([this.createResponseForm()]), sequenceNo: [''] }); } /** * Adds a question to the questions form array */ addQuestion() { this.questionDatas.push(this.createQuestionForm()); this.updateSequenceNumber(); } /** * Removes the particular question form from the questions form array at given index. * @param {number} index Array index from where question form needs to be removed. */ removeQuestion(index: number) { this.questionDatas.removeAt(index); this.updateSequenceNumber(); } /** * Creates a response form group * @returns {FormGroup} Response form group. */ createResponseForm(): UntypedFormGroup { return this.formBuilder.group({ text: [ '', Validators.required ], value: [ '', [ Validators.required, Validators.pattern('^\\s*[-]?\\d{0,4}\\s*$') ] ], sequenceNo: [''] }); } /** * Adds a response to the responses form array of the question with the given Index * @param {number} questionIndex Index of question to add response to. */ addResponse(questionIndex: number) { this.getResponseDatas(questionIndex).push(this.createResponseForm()); this.updateSequenceNumber(); } /** * Removes the particular response form from the given responses form array at given index. * @param {FormArray} responseFormArray Given responses form array. * @param {number} index Array index from where response form needs to be removed. */ removeResponse(responseFormArray: UntypedFormArray, index: number) { responseFormArray.removeAt(index); this.updateSequenceNumber(); } /** * Updates the sequence numbers of questions and responses */ updateSequenceNumber() { for (let questionIndex = 0; questionIndex < this.questionDatas.length; questionIndex++) { this.questionDatas .at(questionIndex) .get('sequenceNo') .setValue(questionIndex + 1); for (let responseIndex = 0; responseIndex < this.getResponseDatas(questionIndex).length; responseIndex++) { this.getResponseDatas(questionIndex) .at(responseIndex) .get('sequenceNo') .setValue(responseIndex + 1); } } } /** * Cancels the survey and redirects to surveys. */ cancelSurvey() { const cancelSurveyDialogRef = this.dialog.open(CancelDialogComponent); cancelSurveyDialogRef.afterClosed().subscribe((response: any) => { if (response.cancel) { this.router.navigate(['../'], { relativeTo: this.route }); } }); } /** * Reorders the question order according to the user drop */ dropQuestion(event: CdkDragDrop) { moveItemInArray(this.questionDatas.controls, event.previousIndex, event.currentIndex); this.updateSequenceNumber(); } /** * Reorders the response order according to the user drop */ dropResponse(event: CdkDragDrop, questionIndex: number) { moveItemInArray(this.getResponseDatas(questionIndex).controls, event.previousIndex, event.currentIndex); this.updateSequenceNumber(); } /** * Submits the survey form and creates survey, * if successful redirects to surveys. */ submit() { this.surveyForm.patchValue({ countryCode: this.surveyForm.value.countryCode.toUpperCase() }); this.systemService.createSurvey(this.surveyForm.value).subscribe((response: any) => { if (response?.rollbackTransaction) { this.alertService.alert({ type: 'Success', message: 'Survey creation has been submitted for approval.' }); } this.router.navigate(['../'], { relativeTo: this.route }); }); } }