Update with new components

This commit is contained in:
2025-09-23 19:41:25 +05:30
parent cfe68a276f
commit bd2f5b95ce
129 changed files with 5849 additions and 1169 deletions

View File

@ -24,6 +24,16 @@
<label for="subTitle" class="form-label text-primary">Subtitle</label>
<input id="subTitle" formControlName="subTitle" class="form-control" />
</div>
<div class="form-group mb-3">
<label for="description" class="form-label text-primary">Description</label>
<textarea id="description" formControlName="description" class="form-control" rows="3"
placeholder="Brief description for the event card"></textarea>
</div>
<div class="form-group mb-3">
<label for="detail" class="form-label text-primary">Detail</label>
<textarea id="detail" formControlName="detail" class="form-control" rows="3"
placeholder="Detailed information about the event"></textarea>
</div>
<div class="form-group mb-3">
<label for="date" class="form-label text-primary">Date</label>
<input id="date" formControlName="date" class="form-control" />
@ -43,6 +53,119 @@
</div>
<div class="col-md-6">
<!-- Main Image Section -->
<div class="form-group mb-3">
<label class="form-label text-primary">Main Image</label>
<!-- Image Upload Section -->
<div class="card mb-2">
<div class="card-body">
<h6 class="card-title">Upload Image File</h6>
<div class="row">
<div class="col-8">
<input type="file"
class="form-control"
accept="image/*"
(change)="onMainImageFileSelected($event)"
#mainImageFile>
</div>
<div class="col-4">
<button type="button"
class="btn btn-primary btn-sm w-100"
(click)="uploadMainImage()"
[disabled]="!selectedMainImageFile || mainImageUploading">
<span *ngIf="mainImageUploading" class="spinner-border spinner-border-sm me-1"></span>
{{ mainImageUploading ? 'Uploading...' : 'Upload' }}
</button>
</div>
</div>
</div>
</div>
<!-- URL Input Section -->
<div class="card mb-2">
<div class="card-body">
<h6 class="card-title">Or Enter Image URL</h6>
<input id="mainImage"
formControlName="mainImage"
class="form-control"
placeholder="https://images.unsplash.com/..." />
</div>
</div>
<!-- Image Preview -->
<div *ngIf="eventForm.get('mainImage')?.value" class="mt-2">
<img [src]="eventForm.get('mainImage')?.value"
alt="Main Image Preview"
class="img-thumbnail"
style="max-width: 200px; max-height: 150px;">
</div>
<small class="form-text text-muted">This will be the primary image displayed for the event</small>
</div>
<!-- Gallery Images Section -->
<div class="form-group mb-3">
<label class="form-label text-primary">Gallery Images</label>
<!-- Gallery Upload Section -->
<div class="card mb-2">
<div class="card-body">
<h6 class="card-title">Upload Gallery Images</h6>
<div class="row">
<div class="col-8">
<input type="file"
class="form-control"
accept="image/*"
multiple
(change)="onGalleryImagesSelected($event)"
#galleryImageFiles>
</div>
<div class="col-4">
<button type="button"
class="btn btn-primary btn-sm w-100"
(click)="uploadGalleryImages()"
[disabled]="!selectedGalleryImageFiles?.length || galleryImagesUploading">
<span *ngIf="galleryImagesUploading" class="spinner-border spinner-border-sm me-1"></span>
{{ galleryImagesUploading ? 'Uploading...' : 'Upload' }}
</button>
</div>
</div>
</div>
</div>
<!-- Manual Gallery URL Entry -->
<div class="card mb-2">
<div class="card-body">
<h6 class="card-title">Or Add Gallery URLs</h6>
<div formArrayName="galleryImages">
<div *ngFor="let image of galleryImages.controls; let i = index" class="row mb-2">
<div class="col-8">
<input [formControlName]="i" class="form-control" placeholder="https://images.unsplash.com/..." />
</div>
<div class="col-4">
<button type="button" class="btn btn-danger btn-sm w-100" (click)="removeGalleryImage(i)">
Remove
</button>
</div>
<!-- Image Preview -->
<div class="col-12" *ngIf="galleryImages.at(i).value">
<img [src]="galleryImages.at(i).value"
alt="Gallery Preview"
class="img-thumbnail mt-2"
style="max-width: 100px; max-height: 80px;">
</div>
</div>
<button type="button" class="btn btn-outline-primary btn-sm" (click)="addGalleryImage()">
Add Gallery URL
</button>
</div>
</div>
</div>
<small class="form-text text-muted">Add up to 4 gallery images for the event grid</small>
</div>
<div class="form-group mb-3">
<label class="form-label text-primary">Venues</label>
<div formArrayName="venues">
@ -69,7 +192,7 @@
</div>
</div>
<button type="button" class="btn btn-danger btn-sm float-end" (click)="removeVenue(i)">
<!-- <i class="bi bi-trash"></i> -->X
X
</button>
</div>
</div>
@ -86,7 +209,7 @@
<div class="card-body">
<input [formControlName]="i" class="form-control" placeholder="Highlight" />
<button type="button" class="btn btn-danger btn-sm float-end mt-2" (click)="removeHighlight(i)">
<!-- <i class="bi bi-trash"></i> -->X
X
</button>
</div>
</div>
@ -103,7 +226,7 @@
<div class="card-body">
<input [formControlName]="i" class="form-control" placeholder="Organiser" />
<button type="button" class="btn btn-danger btn-sm float-end mt-2" (click)="removeOrganiser(i)">
<!-- <i class="bi bi-trash"></i> -->X
X
</button>
</div>
</div>
@ -121,7 +244,7 @@
<div [formGroupName]="i">
<div class="row mb-2">
<div class="col-8">
<input formControlName="desc" placeholder="Description" class="form-control" />
<input formControlName="description" placeholder="Description" class="form-control" />
</div>
<div class="col-4">
<input formControlName="cost" placeholder="Cost" type="number" class="form-control" />
@ -129,7 +252,7 @@
</div>
</div>
<button type="button" class="btn btn-danger btn-sm float-end mt-2" (click)="removeFee(i)">
<!-- <i class="bi bi-trash"></i> -->X
X
</button>
</div>
</div>
@ -142,4 +265,4 @@
</div>
<button type="submit" class="btn btn-success">Submit</button>
</form>
</div>
</div>

View File

@ -1,4 +1,3 @@
import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, FormArray, Validators } from '@angular/forms';
import { ActivatedRoute, Router } from '@angular/router';
@ -11,125 +10,334 @@ import { EventService } from 'src/app/service/event.service';
})
export class EventFormComponent implements OnInit {
eventForm: FormGroup;
eventId: number | null;
// File upload properties
selectedMainImageFile: File | null = null;
selectedGalleryImageFiles: File[] = [];
mainImageUploading = false;
galleryImagesUploading = false;
eventForm: FormGroup;
constructor(
private fb: FormBuilder,
private eventService: EventService,
private route: ActivatedRoute,
private router: Router
) {}
eventId: number | null;
ngOnInit() {
this.eventForm = this.fb.group({
code: ['', Validators.required],
year: ['', Validators.required],
subject: ['', Validators.required],
title: ['', Validators.required],
subTitle: [''],
date: ['', Validators.required],
venues: this.fb.array([]),
highlights: this.fb.array([]),
organisers: this.fb.array([]),
fees: this.fb.array([]),
phone: ['', Validators.required],
email: ['', [Validators.required, Validators.email]],
isActive: [true]
});
this.route.paramMap.subscribe(params => {
const idParam = params.get('id');
this.eventId = idParam ? +idParam : null;
if (this.eventId !== null) {
this.loadEvent(this.eventId);
}
});
}
loadEvent(id: number): void {
this.eventService.getEvent(id).subscribe(event => {
this.eventForm.patchValue(event);
this.setArrayValues('venues', event.venues);
this.setArrayValues('highlights', event.highlights);
this.setArrayValues('organisers', event.organisers);
this.setArrayValues('fees', event.fees);
});
}
setArrayValues(controlName: string, values: any[]): void {
const array = this.eventForm.get(controlName) as FormArray;
values.forEach(value => array.push(this.fb.group(value)));
}
get venues(): FormArray {
return this.eventForm.get('venues') as FormArray;
}
get highlights(): FormArray {
return this.eventForm.get('highlights') as FormArray;
}
get organisers(): FormArray {
return this.eventForm.get('organisers') as FormArray;
}
get fees(): FormArray {
return this.eventForm.get('fees') as FormArray;
}
addVenue() {
this.venues.push(this.fb.group({
title: [''],
date: [''],
address: [''],
info: ['']
}));
}
removeVenue(index: number) {
this.venues.removeAt(index);
}
addHighlight() {
this.highlights.push(this.fb.control(''));
}
removeHighlight(index: number) {
this.highlights.removeAt(index);
}
addOrganiser() {
this.organisers.push(this.fb.control(''));
}
removeOrganiser(index: number) {
this.organisers.removeAt(index);
}
addFee() {
this.fees.push(this.fb.group({
desc: [''],
cost: ['']
}));
}
removeFee(index: number) {
this.fees.removeAt(index);
}
onSubmit(): void {
if (this.eventForm.valid) {
if (this.eventId) {
this.eventService.updateEvent(this.eventId, this.eventForm.value).subscribe(() => this.router.navigate(['/events']));
} else {
this.eventService.createEvent(this.eventForm.value).subscribe(() => this.router.navigate(['/events']));
}
constructor(
private fb: FormBuilder,
private eventService: EventService,
private route: ActivatedRoute,
private router: Router
) {}
ngOnInit() {
this.eventForm = this.fb.group({
code: ['', Validators.required],
year: ['', Validators.required],
subject: ['', Validators.required],
title: ['', Validators.required],
subTitle: [''],
description: ['', Validators.required],
detail: ['', Validators.required],
date: ['', Validators.required],
mainImage: [''],
galleryImages: this.fb.array([]),
venues: this.fb.array([]), // Form uses 'venues' (plural)
highlights: this.fb.array([]),
organisers: this.fb.array([]),
fees: this.fb.array([]), // Form uses 'fees' (plural)
phone: ['', Validators.required],
email: ['', [Validators.required, Validators.email]],
isActive: [true]
});
this.route.paramMap.subscribe(params => {
const idParam = params.get('id');
this.eventId = idParam ? +idParam : null;
if (this.eventId !== null) {
this.loadEvent(this.eventId);
}
});
}
// File selection methods
onMainImageFileSelected(event: any): void {
const file = event.target.files[0];
if (file) {
this.selectedMainImageFile = file;
console.log('Main image file selected:', file.name);
}
}
onGalleryImagesSelected(event: any): void {
const files = Array.from(event.target.files) as File[];
if (files.length > 0) {
this.selectedGalleryImageFiles = files;
console.log('Gallery image files selected:', files.map(f => f.name));
}
}
// Upload methods
uploadMainImage(): void {
if (!this.selectedMainImageFile) return;
this.mainImageUploading = true;
this.eventService.uploadImage(this.selectedMainImageFile).subscribe({
next: (response) => {
console.log('Main image uploaded:', response);
this.eventForm.patchValue({ mainImage: response.url });
this.selectedMainImageFile = null;
this.mainImageUploading = false;
// Clear the file input
const fileInput = document.querySelector('input[type="file"]') as HTMLInputElement;
if (fileInput) fileInput.value = '';
},
error: (error) => {
console.error('Error uploading main image:', error);
this.mainImageUploading = false;
alert('Error uploading image. Please try again.');
}
});
}
uploadGalleryImages(): void {
if (!this.selectedGalleryImageFiles || this.selectedGalleryImageFiles.length === 0) return;
this.galleryImagesUploading = true;
this.eventService.uploadMultipleImages(this.selectedGalleryImageFiles).subscribe({
next: (responses) => {
console.log('Gallery images uploaded:', responses);
// Add uploaded image URLs to the form array
const galleryArray = this.galleryImages;
responses.forEach((response: any) => {
if (response && response.url) {
galleryArray.push(this.fb.control(response.url));
}
});
this.selectedGalleryImageFiles = [];
this.galleryImagesUploading = false;
// Clear the file input
const fileInputs = document.querySelectorAll('input[type="file"]');
fileInputs.forEach((input: any) => {
if (input.multiple) input.value = '';
});
},
error: (error) => {
console.error('Error uploading gallery images:', error);
this.galleryImagesUploading = false;
alert('Error uploading gallery images. Please try again.');
}
});
}
loadEvent(id: number): void {
this.eventService.getEvent(id).subscribe(event => {
if (event) {
this.eventForm.patchValue({
code: event.code,
year: event.year,
subject: event.subject,
title: event.title,
subTitle: event.subTitle,
description: event.description,
detail: event.detail,
date: event.date,
mainImage: event.mainImage,
phone: event.phone,
email: event.email,
isActive: event.isActive
});
// Map backend 'venue' to form 'venues'
this.setArrayValues('venues', event.venue || []);
// Map backend 'fee' to form 'fees'
this.setArrayValues('fees', event.fee || []);
this.setArrayValues('highlights', event.highlights || []);
this.setArrayValues('organisers', event.organisers || []);
this.setStringArrayValues('galleryImages', event.galleryImages || []);
}
});
}
setArrayValues(controlName: string, values: any[]): void {
const array = this.eventForm.get(controlName) as FormArray;
array.clear();
if (values && values.length > 0) {
values.forEach(value => {
if (controlName === 'venues') {
array.push(this.fb.group({
title: [value.title || ''],
date: [value.date || ''],
address: [value.address || ''],
info: [value.info || '']
}));
} else if (controlName === 'fees') {
array.push(this.fb.group({
description: [value.description || ''], // Changed from 'desc' to 'description'
cost: [value.cost || '']
}));
} else {
array.push(this.fb.control(value));
}
});
}
}
setStringArrayValues(controlName: string, values: string[]): void {
const array = this.eventForm.get(controlName) as FormArray;
array.clear();
if (values && values.length > 0) {
values.forEach(value => array.push(this.fb.control(value)));
}
}
get venues(): FormArray {
return this.eventForm.get('venues') as FormArray;
}
get highlights(): FormArray {
return this.eventForm.get('highlights') as FormArray;
}
get organisers(): FormArray {
return this.eventForm.get('organisers') as FormArray;
}
get fees(): FormArray {
return this.eventForm.get('fees') as FormArray;
}
get galleryImages(): FormArray {
return this.eventForm.get('galleryImages') as FormArray;
}
addGalleryImage() {
this.galleryImages.push(this.fb.control(''));
}
removeGalleryImage(index: number) {
this.galleryImages.removeAt(index);
}
addVenue() {
this.venues.push(this.fb.group({
title: [''],
date: [''],
address: [''],
info: ['']
}));
}
removeVenue(index: number) {
this.venues.removeAt(index);
}
addHighlight() {
this.highlights.push(this.fb.control(''));
}
removeHighlight(index: number) {
this.highlights.removeAt(index);
}
addOrganiser() {
this.organisers.push(this.fb.control(''));
}
removeOrganiser(index: number) {
this.organisers.removeAt(index);
}
addFee() {
this.fees.push(this.fb.group({
description: [''], // Changed from 'desc' to 'description'
cost: ['']
}));
}
removeFee(index: number) {
this.fees.removeAt(index);
}
onSubmit(): void {
if (this.eventForm.valid) {
const formValue = this.eventForm.value;
// Transform form data to match backend structure
const eventData = {
...formValue,
venue: formValue.venues, // Map 'venues' to 'venue' for backend
fee: formValue.fees, // Map 'fees' to 'fee' for backend
galleryImages: formValue.galleryImages?.filter((img: string) => img?.trim() !== '') || [],
isDeleted: false // Add default value for isDeleted
};
// Remove the plural properties that don't exist in backend
delete eventData.venues;
delete eventData.fees;
console.log('Submitting event data:', eventData);
if (this.eventId) {
this.eventService.updateEvent(this.eventId, eventData).subscribe({
next: (response) => {
console.log('Event updated successfully:', response);
this.router.navigate(['/events']);
},
error: (error) => {
console.error('Error updating event:', error);
alert('Error updating event. Please check the console for details.');
}
});
} else {
this.eventService.createEvent(eventData).subscribe({
next: (response) => {
console.log('Event created successfully:', response);
this.router.navigate(['/events']);
},
error: (error) => {
console.error('Error creating event:', error);
alert('Error creating event. Please check the console for details.');
}
});
}
} else {
console.log('Form is invalid');
console.log('Form errors:', this.getFormValidationErrors());
// Mark all fields as touched to show validation errors
Object.keys(this.eventForm.controls).forEach(key => {
const control = this.eventForm.get(key);
if (control) {
control.markAsTouched();
if (control instanceof FormArray) {
control.controls.forEach(arrayControl => {
arrayControl.markAsTouched();
if (arrayControl instanceof FormGroup) {
Object.keys(arrayControl.controls).forEach(innerKey => {
arrayControl.get(innerKey)?.markAsTouched();
});
}
});
}
}
});
}
}
// Helper method to debug form validation errors
getFormValidationErrors() {
const formErrors: any = {};
Object.keys(this.eventForm.controls).forEach(key => {
const controlErrors = this.eventForm.get(key)?.errors;
if (controlErrors) {
formErrors[key] = controlErrors;
}
});
return formErrors;
}
}