WIP
This commit is contained in:
@@ -1,7 +1,15 @@
|
||||
import { Routes } from '@angular/router';
|
||||
import { RegistrationComponent } from './registration/registration.component';
|
||||
import { LandingComponent } from './landing/landing.component';
|
||||
import { ApplicationListComponent } from './application-list/application-list.component';
|
||||
import { ApplicationComponent } from './application/application.component';
|
||||
|
||||
export const routes: Routes = [
|
||||
{ path: 'register', component: RegistrationComponent },
|
||||
{ path: '', redirectTo: '/register', pathMatch: 'full' },
|
||||
{ path: 'landing', component: LandingComponent },
|
||||
{ path: 'registration', component: RegistrationComponent },
|
||||
{ path: 'application-list', component: ApplicationListComponent },
|
||||
{ path: 'application/:id', component: ApplicationComponent },
|
||||
{ path: '', redirectTo: '/landing', pathMatch: 'full' },
|
||||
{ path: '**', redirectTo: '/landing' },
|
||||
// component: PageNotFoundComponent
|
||||
];
|
||||
|
||||
5
src/app/application-list/application-list.component.html
Normal file
5
src/app/application-list/application-list.component.html
Normal file
@@ -0,0 +1,5 @@
|
||||
@for(application of this.applicationList; track application.id){
|
||||
<div class="listItem" [routerLink]="'/application/'+ application.id">
|
||||
<p>{{application.fullName}}</p>
|
||||
</div>
|
||||
}
|
||||
9
src/app/application-list/application-list.component.scss
Normal file
9
src/app/application-list/application-list.component.scss
Normal file
@@ -0,0 +1,9 @@
|
||||
.listItem {
|
||||
margin: 2rem;
|
||||
background-color: aquamarine;
|
||||
padding: 1rem;
|
||||
&:hover{
|
||||
cursor: pointer;
|
||||
background-color: aqua;
|
||||
}
|
||||
}
|
||||
23
src/app/application-list/application-list.component.ts
Normal file
23
src/app/application-list/application-list.component.ts
Normal file
@@ -0,0 +1,23 @@
|
||||
import { Component, inject, OnInit } from '@angular/core';
|
||||
import { CandidateDataService } from '../candidate-data.service';
|
||||
import { RouterLink } from '@angular/router';
|
||||
|
||||
@Component({
|
||||
selector: 'app-application-list',
|
||||
imports: [RouterLink],
|
||||
templateUrl: './application-list.component.html',
|
||||
styleUrl: './application-list.component.scss'
|
||||
})
|
||||
export class ApplicationListComponent implements OnInit {
|
||||
|
||||
dataService = inject(CandidateDataService);
|
||||
applicationList: any[] = [];
|
||||
|
||||
ngOnInit(): void {
|
||||
this.dataService.loadCandidateList().subscribe((data) => {
|
||||
this.applicationList = data;
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
1
src/app/application/application.component.html
Normal file
1
src/app/application/application.component.html
Normal file
@@ -0,0 +1 @@
|
||||
{{this.application}}
|
||||
0
src/app/application/application.component.scss
Normal file
0
src/app/application/application.component.scss
Normal file
28
src/app/application/application.component.ts
Normal file
28
src/app/application/application.component.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
import { Component, inject, OnInit } from '@angular/core';
|
||||
import { CandidateDataService } from '../candidate-data.service';
|
||||
import { ActivatedRoute, RouterModule } from '@angular/router';
|
||||
|
||||
@Component({
|
||||
selector: 'app-application',
|
||||
imports: [RouterModule],
|
||||
templateUrl: './application.component.html',
|
||||
styleUrl: './application.component.scss'
|
||||
})
|
||||
export class ApplicationComponent implements OnInit {
|
||||
dataService = inject(CandidateDataService);
|
||||
activatedRoute = inject(ActivatedRoute);
|
||||
application: any = {};
|
||||
|
||||
ngOnInit(): void {
|
||||
const id = this.activatedRoute.snapshot.paramMap.get('id');
|
||||
if (!id) {
|
||||
alert('invalid route');
|
||||
return;
|
||||
}
|
||||
const applicationId = Number.parseInt(id, 10);
|
||||
this.dataService.getApplicationDetails(applicationId).subscribe((data) => {
|
||||
this.application = JSON.stringify(data);
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
import { HttpClient } from "@angular/common/http";
|
||||
import { inject, Injectable } from "@angular/core";
|
||||
import { environment } from "../environments/environment.development";
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
@@ -7,13 +8,16 @@ import { inject, Injectable } from "@angular/core";
|
||||
export class CandidateDataService {
|
||||
httpClient = inject(HttpClient)
|
||||
|
||||
response: any | null = null;
|
||||
error: any | null = null;
|
||||
|
||||
sendRequest() {
|
||||
this.httpClient.get('http://localhost:3000/app/candidates').subscribe({
|
||||
next: (res) => this.response = JSON.stringify(res),
|
||||
error: err => this.error = JSON.stringify(err)
|
||||
})
|
||||
loadCandidateList() {
|
||||
return this.httpClient.get<any>(`${environment.hostUrl}/app/candidates`);
|
||||
}
|
||||
getApplicationDetails(id: number) {
|
||||
return this.httpClient.get(`${environment.hostUrl}/app/candidate/${id}`)
|
||||
}
|
||||
submitCandidateForm(formData: Object) {
|
||||
return this.httpClient.post(`${environment.hostUrl}/app/register`, formData);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
7
src/app/landing/landing.component.html
Normal file
7
src/app/landing/landing.component.html
Normal file
@@ -0,0 +1,7 @@
|
||||
<p>landing works!</p>
|
||||
<button mat-button routerLink="/registration">
|
||||
to registration
|
||||
</button>
|
||||
<button mat-button routerLink="/application-list">
|
||||
to application list
|
||||
</button>
|
||||
0
src/app/landing/landing.component.scss
Normal file
0
src/app/landing/landing.component.scss
Normal file
15
src/app/landing/landing.component.ts
Normal file
15
src/app/landing/landing.component.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { RouterLink } from '@angular/router';
|
||||
import { RouterLinkActive } from "../../../node_modules/@angular/router/router_module.d-Bx9ArA6K";
|
||||
|
||||
@Component({
|
||||
selector: 'app-landing',
|
||||
imports: [MatButtonModule, RouterLink,],
|
||||
templateUrl: './landing.component.html',
|
||||
styleUrl: './landing.component.scss'
|
||||
})
|
||||
export class LandingComponent {
|
||||
|
||||
|
||||
}
|
||||
@@ -13,7 +13,7 @@
|
||||
<img [src]="previewUrl" alt="Preview" />
|
||||
</div>
|
||||
</div> -->
|
||||
<app-image-input></app-image-input>
|
||||
<!-- <app-image-input></app-image-input> -->
|
||||
|
||||
<mat-form-field appearance="outline" class="full-width">
|
||||
<mat-label>Full Name</mat-label>
|
||||
@@ -37,13 +37,13 @@
|
||||
|
||||
<mat-form-field appearance="outline" class="full-width">
|
||||
<mat-label>Phone Number</mat-label>
|
||||
<input matInput formControlName="phone" placeholder="+972-XXXXXXX"/>
|
||||
@if (form.get('phone')?.hasError('required')) {
|
||||
<input matInput formControlName="phoneNumber" placeholder="+972-XXXXXXX"/>
|
||||
@if (form.get('phoneNumber')?.hasError('required')) {
|
||||
<mat-error>
|
||||
Phone number is required
|
||||
</mat-error>
|
||||
}
|
||||
@if (form.get('phone')?.hasError('pattern')){
|
||||
@if (form.get('phoneNumber')?.hasError('pattern')){
|
||||
<mat-error>
|
||||
Invalid phone number
|
||||
</mat-error>
|
||||
@@ -62,8 +62,8 @@
|
||||
|
||||
<mat-form-field appearance="outline" class="full-width">
|
||||
<mat-label>City / Region</mat-label>
|
||||
<input matInput formControlName="city" />
|
||||
@if (form.get('city')?.hasError('required')) {
|
||||
<input matInput formControlName="cityOrRegion" />
|
||||
@if (form.get('cityOrRegion')?.hasError('required')) {
|
||||
<mat-error>
|
||||
Field is required
|
||||
</mat-error>
|
||||
@@ -82,13 +82,13 @@
|
||||
|
||||
<mat-form-field appearance="outline" class="full-width">
|
||||
<mat-label>Why I am the perfect candidate</mat-label>
|
||||
<textarea matInput rows="4" formControlName="reason"></textarea>
|
||||
@if (form.get('reason')?.hasError('required')) {
|
||||
<textarea matInput rows="4" formControlName="justification"></textarea>
|
||||
@if (form.get('justification')?.hasError('required')) {
|
||||
<mat-error>
|
||||
Field is required
|
||||
</mat-error>
|
||||
}
|
||||
@if (form.get('reason')?.hasError('maxLength')) {
|
||||
@if (form.get('justification')?.hasError('maxLength')) {
|
||||
<mat-error>
|
||||
Maximum length is 300 characters
|
||||
</mat-error>
|
||||
|
||||
@@ -7,6 +7,7 @@ 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 '../candidate-data.service';
|
||||
|
||||
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({
|
||||
@@ -19,24 +20,24 @@ const israeliPhoneRegex = /^(?:(?:(\+?972|\(\+?972\)|\+?\(972\))(?:\s|\.|-)?([1-
|
||||
MatCardModule,
|
||||
MatFormFieldModule,
|
||||
ImageInputComponent
|
||||
],
|
||||
],
|
||||
templateUrl: './registration.component.html',
|
||||
styleUrls: ['./registration.component.scss'],
|
||||
})
|
||||
export class RegistrationComponent implements OnInit {
|
||||
|
||||
dataService = inject(CandidateDataService);
|
||||
fb = inject(FormBuilder);
|
||||
previewUrl: string | ArrayBuffer | null = null;
|
||||
|
||||
form = this.fb.group({
|
||||
fullName: ['', [Validators.required, Validators.minLength(3)]],
|
||||
email: ['', [Validators.required, Validators.email]],
|
||||
phone: ['', [Validators.required, Validators.pattern(israeliPhoneRegex)]],
|
||||
phoneNumber: ['', [Validators.required, Validators.pattern(israeliPhoneRegex)]],
|
||||
age: [0, [Validators.required, Validators.min(18), Validators.max(70)]],
|
||||
city: ['', Validators.required],
|
||||
cityOrRegion: ['', Validators.required],
|
||||
hobbies: ['', [Validators.maxLength(300)]],
|
||||
reason: ['', [Validators.required, Validators.maxLength(300)]],
|
||||
profileImage: this.fb.control<string | null>(null, Validators.required),
|
||||
justification: ['', [Validators.required, Validators.maxLength(300)]],
|
||||
// profileImage: this.fb.control<string | null>(null, Validators.required),
|
||||
});
|
||||
|
||||
ngOnInit(): void {
|
||||
@@ -53,31 +54,29 @@ export class RegistrationComponent implements OnInit {
|
||||
}
|
||||
}
|
||||
|
||||
onFileSelected(event: any) {
|
||||
const file = event.target.files[0];
|
||||
if (file) {
|
||||
const reader = new FileReader();
|
||||
reader.onload = () => {
|
||||
if (typeof reader.result === 'string') {
|
||||
this.previewUrl = reader.result;
|
||||
this.form.patchValue({ profileImage: reader.result });
|
||||
}
|
||||
};
|
||||
reader.readAsDataURL(file);
|
||||
}
|
||||
}
|
||||
// onFileSelected(event: any) {
|
||||
// const file = event.target.files[0];
|
||||
// if (file) {
|
||||
// const reader = new FileReader();
|
||||
// reader.onload = () => {
|
||||
// if (typeof reader.result === 'string') {
|
||||
// this.previewUrl = reader.result;
|
||||
// this.form.patchValue({ profileImage: reader.result });
|
||||
// }
|
||||
// };
|
||||
// reader.readAsDataURL(file);
|
||||
// }
|
||||
// }
|
||||
|
||||
onSubmit() {
|
||||
if (this.form.valid) {
|
||||
localStorage.setItem(
|
||||
'registration',
|
||||
JSON.stringify({
|
||||
data: this.form.value,
|
||||
timestamp: Date.now(),
|
||||
})
|
||||
);
|
||||
alert('✅ Application saved! You can re-edit within 3 days.');
|
||||
if (!this.form.valid) {
|
||||
alert("Invalid Form");
|
||||
return;
|
||||
}
|
||||
console.log(JSON.stringify(this.form.value));
|
||||
this.dataService.submitCandidateForm(this.form.value).subscribe(() => {
|
||||
alert('✅ Application saved! You can re-edit within 3 days.')
|
||||
});
|
||||
}
|
||||
|
||||
onCheckErrors() {
|
||||
|
||||
Reference in New Issue
Block a user