173 lines
6.1 KiB
TypeScript
173 lines
6.1 KiB
TypeScript
import { AfterViewInit, Component, ElementRef, inject, input, OnInit, QueryList, signal, ViewChildren } from '@angular/core';
|
|
import { FormBuilder, Validators, ReactiveFormsModule } from '@angular/forms';
|
|
import { CommonModule } from '@angular/common';
|
|
import { MatSnackBar, MatSnackBarModule } from '@angular/material/snack-bar';
|
|
import { MatInputModule } from '@angular/material/input';
|
|
import { MatButtonModule } from '@angular/material/button';
|
|
import { MatCardModule } from '@angular/material/card';
|
|
import { MatFormFieldModule } from '@angular/material/form-field';
|
|
import { ImageInputComponent } from "../image-input/image-input.component";
|
|
import { CandidateDataService } from '../../services/candidate-data.service';
|
|
import "@maptiler/leaflet-maptilersdk";
|
|
import { LeafletMapComponent } from "../leaflet-map/leaflet-map.component";
|
|
import { CITY_LIST } from '../../shared/cities';
|
|
import { cityValidator } from '../../validators/city.validator';
|
|
import { ActivatedRoute, Router, RouterLink } from '@angular/router';
|
|
import { SocketIOService } from '../../services/socket-io.service';
|
|
|
|
const CITY_NAMES = CITY_LIST.map(c => c.name).sort();
|
|
const israeliPhoneRegex = /^(?:(?:(\+?972|\(\+?972\)|\+?\(972\))(?:\s|\.|-)?([1-9]\d?))|(0[23489]{1})|(0[57]{1}[0-9]))(?:\s|\.|-)?([^0\D]{1}\d{2}(?:\s|\.|-)?\d{4})$/;
|
|
|
|
@Component({
|
|
selector: 'app-registration',
|
|
imports: [
|
|
CommonModule,
|
|
ReactiveFormsModule,
|
|
MatInputModule,
|
|
MatButtonModule,
|
|
MatCardModule,
|
|
MatFormFieldModule,
|
|
ImageInputComponent,
|
|
LeafletMapComponent,
|
|
MatSnackBarModule,
|
|
RouterLink
|
|
],
|
|
templateUrl: './registration.component.html',
|
|
styleUrls: ['./registration.component.scss'],
|
|
})
|
|
export class RegistrationComponent implements OnInit {
|
|
|
|
|
|
dataService = inject(CandidateDataService);
|
|
fb = inject(FormBuilder);
|
|
router = inject(Router);
|
|
activatedRoute = inject(ActivatedRoute);
|
|
snackBar = inject(MatSnackBar)
|
|
socketService = inject(SocketIOService);
|
|
previewUrl: string | ArrayBuffer | null = null;
|
|
|
|
editMode = signal(false);
|
|
applicationId = signal<number | null>(null);
|
|
|
|
|
|
form = this.fb.group({
|
|
fullName: ['', [Validators.required, Validators.minLength(3)]],
|
|
email: ['', [Validators.required, Validators.email]],
|
|
phoneNumber: ['', [Validators.required, Validators.pattern(israeliPhoneRegex)]],
|
|
age: [0, [Validators.required, Validators.min(18), Validators.max(70)]],
|
|
cityOrRegion: ['', [Validators.required, cityValidator(CITY_NAMES)]],
|
|
hobbies: ['', [Validators.maxLength(300)]],
|
|
justification: ['', [Validators.required, Validators.maxLength(300)]],
|
|
profileImage: this.fb.control<File | null>(null, Validators.required),
|
|
});
|
|
|
|
ngOnInit(): void {
|
|
const idParam = this.activatedRoute.snapshot.paramMap.get('id');
|
|
const url = this.activatedRoute.snapshot.url.map(s => s.path);
|
|
|
|
if (url.includes('edit') && idParam) {
|
|
this.editMode.set(true);
|
|
this.applicationId.set(+idParam);
|
|
this.loadCandidate(+idParam);
|
|
} else {
|
|
this.editMode.set(false);
|
|
this.applicationId.set(null);
|
|
}
|
|
}
|
|
|
|
loadCandidate(id: number) {
|
|
this.dataService.getApplicationDetails(id).subscribe({
|
|
next: (candidate: any) => {
|
|
this.form.patchValue({
|
|
fullName: candidate.fullName,
|
|
email: candidate.email,
|
|
phoneNumber: candidate.phoneNumber,
|
|
age: candidate.age,
|
|
cityOrRegion: candidate.cityOrRegion,
|
|
hobbies: candidate.hobbies,
|
|
justification: candidate.justification,
|
|
});
|
|
|
|
if (candidate.profileImageUrl) {
|
|
this.previewUrl = candidate.profileImageUrl;
|
|
this.form.get('profileImage')?.clearValidators();
|
|
this.form.get('profileImage')?.updateValueAndValidity();
|
|
}
|
|
},
|
|
error: err => console.error('Failed to load candidate', err),
|
|
});
|
|
}
|
|
|
|
|
|
scrollToFirstInvalidField() {
|
|
for (const key of Object.keys(this.form.controls)) {
|
|
const control = this.form.get(key);
|
|
if (control && control.invalid) {
|
|
const element = document.querySelector(
|
|
`[formControlName="${key}"]`
|
|
) as HTMLElement;
|
|
if (element) {
|
|
element.scrollIntoView({ behavior: 'smooth', block: 'center' });
|
|
element.focus();
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
onSubmit() {
|
|
if (!this.form.valid) {
|
|
this.scrollToFirstInvalidField();
|
|
return;
|
|
}
|
|
|
|
const formData = new FormData();
|
|
|
|
const value = this.form.value;
|
|
|
|
if (value.fullName) formData.append('fullName', value.fullName);
|
|
if (value.email) formData.append('email', value.email);
|
|
if (value.phoneNumber) formData.append('phoneNumber', value.phoneNumber);
|
|
if (value.age !== null && value.age !== undefined) formData.append('age', value.age.toString());
|
|
if (value.cityOrRegion) formData.append('cityOrRegion', value.cityOrRegion);
|
|
if (value.hobbies) formData.append('hobbies', value.hobbies);
|
|
if (value.justification) formData.append('justification', value.justification);
|
|
|
|
const imageFile = this.form.get('profileImage')?.value;
|
|
|
|
if (imageFile) {
|
|
formData.append('profileImage', imageFile);
|
|
}
|
|
|
|
if (this.editMode() && this.applicationId()) {
|
|
this.dataService.updateCandidateForm(this.applicationId()!, formData).subscribe({
|
|
next: (updatedCandidate) => {
|
|
this.snackBar.open('✅ Application updated!', 'Close', {
|
|
duration: 5000,
|
|
horizontalPosition: 'center',
|
|
verticalPosition: 'top',
|
|
});
|
|
this.socketService.socket.emit('candidateUpdated', updatedCandidate);
|
|
this.router.navigate(['/application-list']);
|
|
},
|
|
error: err => console.error('Error updating application', err),
|
|
});
|
|
} else {
|
|
this.dataService.submitCandidateForm(formData).subscribe({
|
|
next: (newCandidate) => {
|
|
this.snackBar.open('✅ Application saved!', 'Close', {
|
|
duration: 5000,
|
|
horizontalPosition: 'center',
|
|
verticalPosition: 'top',
|
|
});
|
|
this.socketService.socket.emit('candidateRegistered', newCandidate);
|
|
this.form.reset();
|
|
},
|
|
error: err => console.error('Error submitting form', err),
|
|
});
|
|
}
|
|
}
|
|
|
|
|
|
}
|