/** * create-survey.page.ts * Page for creating a new survey or editing an existing one. * * When accessed via /create-survey → creates a new survey * When accessed via /create-survey/:id → loads and edits the existing survey */ import { Component, OnInit } from '@angular/core'; import { ActivatedRoute, Router } from '@angular/router'; import { ToastController } from '@ionic/angular'; import { SurveyService } from '../../services/survey.service'; import type { Survey, Question } from '../../shared/models/survey.models'; @Component({ selector: 'app-create-survey', templateUrl: './create-survey.page.html', styleUrls: ['./create-survey.page.scss'], standalone: false, }) export class CreateSurveyPage implements OnInit { /** True when editing an existing survey */ isEditMode = false; existingSurveyId?: string; // Form fields title = ''; description = ''; questions: Question[] = []; /** Track which question's options are being edited */ expandedQuestionIndex: number | null = null; constructor( private route: ActivatedRoute, private router: Router, private surveyService: SurveyService, private toastCtrl: ToastController ) {} async ngOnInit(): Promise { const id = this.route.snapshot.paramMap.get('id'); if (id) { this.isEditMode = true; this.existingSurveyId = id; await this.loadSurvey(id); } else { // Start with one empty question for a better UX this.addQuestion(); } } private async loadSurvey(id: string): Promise { const survey = await this.surveyService.getSurvey(id); if (!survey) { const toast = await this.toastCtrl.create({ message: 'Survey not found.', duration: 2000, color: 'danger', }); await toast.present(); this.router.navigate(['/home']); return; } this.title = survey.title; this.description = survey.description ?? ''; // Deep copy so edits don't mutate the original until saved this.questions = JSON.parse(JSON.stringify(survey.questions)); } // ------------------------------------------------------------------------- // Question management // ------------------------------------------------------------------------- addQuestion(): void { const question: Question = { id: crypto.randomUUID(), text: '', type: 'text', required: false, }; this.questions.push(question); this.expandedQuestionIndex = this.questions.length - 1; } removeQuestion(index: number): void { this.questions.splice(index, 1); if (this.expandedQuestionIndex === index) { this.expandedQuestionIndex = null; } } moveQuestionUp(index: number): void { if (index === 0) return; const temp = this.questions[index - 1]; this.questions[index - 1] = this.questions[index]; this.questions[index] = temp; } moveQuestionDown(index: number): void { if (index === this.questions.length - 1) return; const temp = this.questions[index + 1]; this.questions[index + 1] = this.questions[index]; this.questions[index] = temp; } toggleExpand(index: number): void { this.expandedQuestionIndex = this.expandedQuestionIndex === index ? null : index; } onTypeChange(question: Question): void { // Initialise options array when switching to multiple_choice if (question.type === 'multiple_choice' && !question.options?.length) { question.options = ['Option 1', 'Option 2']; } } addOption(question: Question): void { if (!question.options) question.options = []; question.options.push(`Option ${question.options.length + 1}`); } removeOption(question: Question, optIndex: number): void { question.options?.splice(optIndex, 1); } trackOption(index: number): number { return index; } trackQuestion(index: number): number { return index; } // ------------------------------------------------------------------------- // Validation // ------------------------------------------------------------------------- get isFormValid(): boolean { if (!this.title.trim()) return false; if (this.questions.length === 0) return false; return this.questions.every( (q) => q.text.trim() && (q.type !== 'multiple_choice' || (q.options && q.options.length >= 2)) ); } // ------------------------------------------------------------------------- // Save / Update // ------------------------------------------------------------------------- async save(): Promise { if (!this.isFormValid) return; const questionsToSave = this.questions.map((q) => ({ ...q, text: q.text.trim(), // Strip empty options for multiple_choice options: q.type === 'multiple_choice' ? q.options?.filter((o) => o.trim()) ?? [] : undefined, })); if (this.isEditMode && this.existingSurveyId) { await this.surveyService.updateSurvey(this.existingSurveyId, { title: this.title.trim(), description: this.description.trim() || undefined, questions: questionsToSave, }); const toast = await this.toastCtrl.create({ message: 'Survey updated.', duration: 2000, color: 'success', }); await toast.present(); this.router.navigate(['/survey', this.existingSurveyId]); } else { const survey = await this.surveyService.createSurvey({ title: this.title.trim(), description: this.description.trim() || undefined, questions: questionsToSave, }); const toast = await this.toastCtrl.create({ message: 'Survey created.', duration: 2000, color: 'success', }); await toast.present(); this.router.navigate(['/survey', survey.id]); } } cancel(): void { if (this.isEditMode && this.existingSurveyId) { this.router.navigate(['/survey', this.existingSurveyId]); } else { this.router.navigate(['/home']); } } }