diff --git a/src/app/components/application-list/application-list.component.scss b/src/app/components/application-list/application-list.component.scss
index 18a305a..a0abbed 100644
--- a/src/app/components/application-list/application-list.component.scss
+++ b/src/app/components/application-list/application-list.component.scss
@@ -110,6 +110,7 @@ button.secondary-btn:hover {
/* Applicant card layout */
.listItem {
display: flex;
+ justify-content: space-between;
align-items: center;
gap: 1.2rem;
padding: 1rem 1.4rem;
@@ -149,7 +150,8 @@ button.secondary-btn:hover {
}
.delete-button {
- margin-left: 12px;
+ margin-left: auto;
+ margin-right: 1rem;
width: 40px;
height: 40px;
min-width: 40px;
diff --git a/src/app/components/application/application.component.ts b/src/app/components/application/application.component.ts
index 087bb84..f4d72f2 100644
--- a/src/app/components/application/application.component.ts
+++ b/src/app/components/application/application.component.ts
@@ -12,6 +12,7 @@ import { SocketIOService } from '../../services/socket-io.service';
import { MatSnackBar } from '@angular/material/snack-bar';
import { trigger, transition } from '@angular/animations';
import { slideLeft, slideRight } from './slide.animation';
+import { tap } from 'rxjs';
@Component({
selector: 'app-application',
@@ -68,21 +69,22 @@ export class ApplicationComponent implements OnInit {
ngOnInit(): void {
- if (this.dataService.cachedApplicationList.length > 0) {
- this.applicationList.set(this.dataService.cachedApplicationList);
+ if (this.dataService.cachedApplicationList().length > 0) {
+ this.applicationList.set(this.dataService.cachedApplicationList());
this.initializeApplication();
- } else {
- this.dataService.loadCandidateList().subscribe({
- next: (data) => {
- this.applicationList.set(data);
- this.initializeApplication();
- },
- error: (error) => {
- console.error('Error loading candidate list:', error);
- alert('Error loading candidate list');
- }
- });
+ return;
}
+ this.dataService.loadCandidateList().subscribe({
+ next: (data) => {
+ this.applicationList.set(data);
+ this.initializeApplication();
+ },
+ error: (error) => {
+ console.error('Error loading candidate list:', error);
+ alert('Error loading candidate list');
+ }
+ });
+
}
editApplication() {
@@ -108,7 +110,7 @@ export class ApplicationComponent implements OnInit {
if (this.currentIndex() !== foundIndex) {
this.currentIndex.set(foundIndex);
- this.loadApplication(applicationId);
+ this.loadApplication(applicationId)?.subscribe();
}
}
@@ -118,7 +120,7 @@ export class ApplicationComponent implements OnInit {
}
this.currentApplication.set(null);
- this.dataService.getApplicationDetails(id).subscribe({
+ return this.dataService.getApplicationDetails(id).pipe(tap({
next: (data) => {
this.currentApplication.set(data);
const currentRoute = this.router.url;
@@ -131,7 +133,7 @@ export class ApplicationComponent implements OnInit {
console.error('Error loading application details:', error);
alert('Error loading application details');
}
- });
+ }));
}
goToPrevious() {
@@ -139,7 +141,7 @@ export class ApplicationComponent implements OnInit {
const newIndex = this.currentIndex() - 1;
this.currentIndex.set(newIndex);
const prevId = this.applicationList()[newIndex].id;
- this.loadApplication(prevId);
+ this.loadApplication(prevId)?.subscribe();
}
}
@@ -148,7 +150,7 @@ export class ApplicationComponent implements OnInit {
const newIndex = this.currentIndex() + 1;
this.currentIndex.set(newIndex);
const nextId = this.applicationList()[newIndex].id;
- this.loadApplication(nextId);
+ this.loadApplication(nextId)?.subscribe();
}
}
diff --git a/src/app/components/image-input/image-input.component.html b/src/app/components/image-input/image-input.component.html
index eac9d09..f087b6d 100644
--- a/src/app/components/image-input/image-input.component.html
+++ b/src/app/components/image-input/image-input.component.html
@@ -1,5 +1,5 @@
-
Profile Photo
+
Profile Photo*
@@ -24,8 +24,7 @@
Drag and drop here
diff --git a/src/app/components/image-input/image-input.component.ts b/src/app/components/image-input/image-input.component.ts
index 6db9bb2..69ce39d 100644
--- a/src/app/components/image-input/image-input.component.ts
+++ b/src/app/components/image-input/image-input.component.ts
@@ -1,5 +1,5 @@
-import { Component, effect, forwardRef, inject, input } from '@angular/core';
-import { ControlValueAccessor, FormsModule, NG_VALUE_ACCESSOR, ReactiveFormsModule, UntypedFormBuilder } from '@angular/forms';
+import { Component, effect, forwardRef, inject, input, viewChild } from '@angular/core';
+import { ControlValueAccessor, FormsModule, NG_VALIDATORS, NG_VALUE_ACCESSOR, ReactiveFormsModule, UntypedFormBuilder } from '@angular/forms';
import { MatButtonModule } from '@angular/material/button';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatInputModule } from '@angular/material/input';
@@ -25,13 +25,15 @@ import { CommonModule } from '@angular/common';
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => ImageInputComponent),
multi: true
- }
+ },
],
templateUrl: './image-input.component.html',
styleUrl: './image-input.component.scss'
})
export class ImageInputComponent implements ControlValueAccessor {
+ fileInput = viewChild
('fileInput');
value: File | null = null;
+ touched = false;
disabled = false;
previewUrl: string | null = null;
src = input(null);
@@ -54,9 +56,10 @@ export class ImageInputComponent implements ControlValueAccessor {
if (value) {
this.previewUrl = URL.createObjectURL(value);
} else {
- this.previewUrl = null;
+ this.previewUrl = null;
}
}
+
registerOnChange(fn: any): void {
this.onChange = fn;
}
@@ -71,16 +74,21 @@ export class ImageInputComponent implements ControlValueAccessor {
setFileData(event: Event): void {
+ this.markAsTouched();
const input = event.target as HTMLInputElement;
if (input?.files?.[0]) {
this.value = input.files[0];
-
this.previewUrl = URL.createObjectURL(this.value);
- console.log(this.previewUrl)
this.onChange(this.value);
}
}
+ markAsTouched() {
+ if (this.touched) return;
+ this.onTouched();
+ this.touched = true;
+ }
+
clear() {
this.value = null;
this.isDisplayOnly = false;
diff --git a/src/app/components/leaflet-map/leaflet-map.component.ts b/src/app/components/leaflet-map/leaflet-map.component.ts
index 11acda6..4de9567 100644
--- a/src/app/components/leaflet-map/leaflet-map.component.ts
+++ b/src/app/components/leaflet-map/leaflet-map.component.ts
@@ -86,7 +86,6 @@ export class LeafletMapComponent implements AfterViewInit, ControlValueAccessor
if (exact) this.onSelectCity(exact.name);
else this.onTouched();
- console.log(this.marker);
}
diff --git a/src/app/components/registration/registration.component.html b/src/app/components/registration/registration.component.html
index 84ef5b5..f2ee90f 100644
--- a/src/app/components/registration/registration.component.html
+++ b/src/app/components/registration/registration.component.html
@@ -26,6 +26,9 @@
+ @if (form.get('profileImage')?.touched && form.get('profileImage')?.hasError('required')) {
+
Image is required
+ }
@@ -43,6 +46,9 @@
@if (form.get('email')?.hasError('email')) {
Invalid email
+ }
+ @if (form.get('email')?.hasError('required')) {
+ Email is required
}
@@ -105,7 +111,7 @@
-