//html
<div class="register-wrapper d-flex justify-content-center align-items-center">
<div class="card box">
<div class="card-header text-center">
<h4 class="card-title">Sign-up</h4>
</div>
<form class="form" [formGroup]="registerFormGroup" (ngSubmit)="RegisterUser()">
<div class="card-body">
<div class="row">
<div class="col-md-6">
<div class="form-group">
<label for="name" class="form-label">Name</label>
<input type="text" class="form-control" id="name" placeholder="Enter your Name" formControlName="name">
<div *ngIf="registerFormGroup.controls['name'].invalid && (registerFormGroup.controls['name'].dirty || registerFormGroup.controls['name'].touched)" class="text-danger">
<div *ngIf="registerFormGroup.controls['name'].errors?.['required']">Name is required.</div>
<div *ngIf="registerFormGroup.controls['name'].errors?.['minlength']">Name must be at least 2 characters long.</div>
<div *ngIf="registerFormGroup.controls['name'].errors?.['maxlength']">Name must be at most 20 characters long.</div>
</div>
</div>
<div class="form-group">
<label for="surname" class="form-label">Surname</label>
<input type="text" class="form-control" id="surname" placeholder="Enter your Surname" formControlName="surname">
<div *ngIf="registerFormGroup.controls['surname'].invalid && (registerFormGroup.controls['surname'].dirty || registerFormGroup.controls['surname'].touched)" class="text-danger">
<div *ngIf="registerFormGroup.controls['surname'].errors?.['required']">Surname is required.</div>
<div *ngIf="registerFormGroup.controls['surname'].errors?.['minlength']">Surname must be at least 2 characters long.</div>
<div *ngIf="registerFormGroup.controls['surname'].errors?.['maxlength']">Surname must be at most 20 characters long.</div>
</div>
</div>
<div class="form-group">
<label for="email" class="form-label">Email Address</label>
<input type="email" class="form-control" id="email" placeholder="Enter a valid Email address" formControlName="email">
<div *ngIf="registerFormGroup.controls['email'].invalid && (registerFormGroup.controls['email'].dirty || registerFormGroup.controls['email'].touched)" class="text-danger">
<div *ngIf="registerFormGroup.controls['email'].errors?.['required']">Email is required.</div>
<div *ngIf="registerFormGroup.controls['email'].errors?.['email']">Email is invalid.</div>
</div>
</div>
<div class="form-group">
<label for="password" class="form-label">Password</label>
<input type="password" class="form-control" id="password" placeholder="Enter between 8 to 15 characters" formControlName="password">
<div *ngIf="registerFormGroup.controls['password'].invalid && (registerFormGroup.controls['password'].dirty || registerFormGroup.controls['password'].touched)" class="text-danger">
<div *ngIf="registerFormGroup.controls['password'].errors?.['required']">Password is required.</div>
<div *ngIf="registerFormGroup.controls['password'].errors?.['minlength']">Password must be at least 8 characters.</div>
<div *ngIf="registerFormGroup.controls['password'].errors?.['maxlength']">Password cannot be more than 15 characters.</div>
</div>
</div>
<div class="form-group">
<label for="PhoneNumber" class="form-label">Phone Number</label>
<input type="text" class="form-control" id="PhoneNumber" placeholder="Enter your Phone Number" formControlName="PhoneNumber">
<div *ngIf="registerFormGroup.controls['PhoneNumber'].invalid && (registerFormGroup.controls['PhoneNumber'].dirty || registerFormGroup.controls['PhoneNumber'].touched)" class="text-danger">
<div *ngIf="registerFormGroup.controls['PhoneNumber'].errors?.['required']">Phone Number is required.</div>
<div *ngIf="registerFormGroup.controls['PhoneNumber'].errors?.['minlength']">Phone Number must be 10 digits.</div>
<div *ngIf="registerFormGroup.controls['PhoneNumber'].errors?.['maxlength']">Phone Number must be 10 digits.</div>
</div>
</div>
</div>
<div class="col-md-6">
<div class="form-group">
<label for="Date_of_Birth" class="form-label">Date of Birth</label>
<input type="date" class="form-control" id="Date_of_Birth" placeholder="Enter your Date of Birth" formControlName="Date_of_Birth">
<div *ngIf="registerFormGroup.controls['Date_of_Birth'].invalid && (registerFormGroup.controls['Date_of_Birth'].dirty || registerFormGroup.controls['Date_of_Birth'].touched)" class="text-danger">
<div *ngIf="registerFormGroup.controls['Date_of_Birth'].errors?.['required']">Date of Birth is required.</div>
<div *ngIf="registerFormGroup.controls['Date_of_Birth'].errors?.['futureDate']">Date of birth cannot be a future date.</div>
<div *ngIf="registerFormGroup.controls['Date_of_Birth'].errors?.['olderThan100']">Date of birth cannot be more than 100 years ago.</div>
<div *ngIf="registerFormGroup.controls['Date_of_Birth'].errors?.['futureYear']">User cannot be younger than 16.</div>
</div>
</div>
<div class="form-group">
<label for="Id_Number" class="form-label">ID Number</label>
<input type="text" class="form-control" id="Id_Number" placeholder="Enter your ID Number" formControlName="Id_Number">
<div *ngIf="registerFormGroup.controls['Id_Number'].invalid && (registerFormGroup.controls['Id_Number'].dirty || registerFormGroup.controls['Id_Number'].touched)" class="text-danger">
<div *ngIf="registerFormGroup.controls['Id_Number'].errors?.['required']">ID Number is required.</div>
<div *ngIf="registerFormGroup.controls['Id_Number'].errors?.['minlength']">ID Number must be 13 digits.</div>
<div *ngIf="registerFormGroup.controls['Id_Number'].errors?.['maxlength']">ID Number must be 13 digits.</div>
</div>
</div>
<div class="form-group">
<label for="Physical_Address" class="form-label">Physical Address</label>
<input type="text" class="form-control" id="Physical_Address" placeholder="Enter your Physical Address" formControlName="Physical_Address">
<div *ngIf="registerFormGroup.controls['Physical_Address'].invalid && (registerFormGroup.controls['Physical_Address'].dirty || registerFormGroup.controls['Physical_Address'].touched)" class="text-danger">
<div *ngIf="registerFormGroup.controls['Physical_Address'].errors?.['required']">Physical Address is required.</div>
<div *ngIf="registerFormGroup.controls['Physical_Address'].errors?.['minlength']">Physical Address must be at least 7 characters long.</div>
<div *ngIf="registerFormGroup.controls['Physical_Address'].errors?.['maxlength']">Physical Address must be at most 100 characters long.</div>
</div>
</div>
<div class="form-group">
<label for="Photo" class="form-label">Photo</label>
<input type="file" class="form-control" id="Photo" (change)="onFileSelected($event)">
<div *ngIf="registerFormGroup.controls['Photo'].invalid && (registerFormGroup.controls['Photo'].dirty || registerFormGroup.controls['Photo'].touched)" class="text-danger">
<div *ngIf="registerFormGroup.controls['Photo'].errors?.['required']">Photo is required.</div>
</div>
</div>
<div class="form-group">
<label for="User_Type_ID" class="form-label">User Type</label>
<select class="form-control" id="User_Type_ID" formControlName="User_Type_ID">
<option value="1">Owner</option>
<option value="2">Employee</option>
<option value="3">Member</option>
</select>
<div *ngIf="registerFormGroup.controls['User_Type_ID'].invalid && (registerFormGroup.controls['User_Type_ID'].dirty || registerFormGroup.controls['User_Type_ID'].touched)" class="text-danger">
<div *ngIf="registerFormGroup.controls['User_Type_ID'].errors?.['required']">User Type is required.</div>
</div>
</div>
</div>
</div>
</div>
<div class="card-footer d-flex justify-content-between">
<button type="submit" class="btn btn-primary">Sign-up</button>
<button type="button" class="btn btn-secondary" (click)="resetForm()">Cancel</button>
</div>
</form>
</div>
</div>
//ts
import { Component } from '@angular/core';
import { FormBuilder, FormGroup, ReactiveFormsModule, Validators } from '@angular/forms';
import { Router } from '@angular/router';
import { MatSnackBar } from '@angular/material/snack-bar';
import { UserService } from '../../Services/userprofile.service';
import { FlexLayoutModule } from '@angular/flex-layout';
import { CommonModule } from '@angular/common';
@Component({
selector: 'app-register',
standalone: true,
imports: [ReactiveFormsModule, CommonModule, FlexLayoutModule],
templateUrl: './register.component.html',
styleUrls: ['./register.component.css']
})
export class RegisterComponent {
submitted = false;
registerFormGroup: FormGroup;
selectedFile: File | null = null;
constructor(
private router: Router,
private userService: UserService,
private fb: FormBuilder,
private snackBar: MatSnackBar
) {
this.registerFormGroup = this.fb.group({
// email: ['', [Validators.required, Validators.email, Validators.pattern(/^[a-z0-9._%+-]+@gmail\.com$/), Validators.minLength(3), Validators.maxLength(50)]],
email: ['', [Validators.required, Validators.email]],
password: ['', [Validators.required, Validators.minLength(8), Validators.maxLength(15)]],
name: ['', [Validators.required, Validators.minLength(2), Validators.maxLength(20)]],
surname: ['', [Validators.required, Validators.minLength(2), Validators.maxLength(20)]],
// PhoneNumber: ['', [Validators.required, Validators.pattern(/^0\d{9}$/)]],
PhoneNumber: ['', [Validators.required, Validators.minLength(10), Validators.maxLength(10)]],
Date_of_Birth: ['', [Validators.required, this.validateDateOfBirth]],
// Id_Number: ['', [Validators.required, Validators.pattern(/^\d{2}(0[1-9]|1[0-2])(0[1-9]|[12][0-9]|3[01])\d{7}$/)]],
Id_Number: ['', [Validators.required, Validators.minLength(13), Validators.maxLength(13)]],
Physical_Address: ['', [Validators.required, Validators.minLength(7), Validators.maxLength(100)]],
Photo: ['', Validators.required],
// User_Status_ID: [1, [Validators.required, Validators.min(1), Validators.max(2)]],
// User_Type_ID: ['', [Validators.required, Validators.min(1), Validators.max(3)]]
User_Status_ID: [1, Validators.required],
User_Type_ID: ['', Validators.required]
});
}
ngOnInit() { }
validateDateOfBirth(control: any): { [key: string]: any } | null {
const selectedDate = new Date(control.value);
const currentDate = new Date();
const minDate = new Date(currentDate.getFullYear() - 100, currentDate.getMonth(), currentDate.getDate());
const maxDate = new Date(currentDate.getFullYear() - 16, currentDate.getMonth(), currentDate.getDate());
if (selectedDate > currentDate) {
return { 'futureDate': true };
}
if (selectedDate < minDate) {
return { 'olderThan100': true };
}
if (selectedDate > maxDate) {
return { 'futureYear': true };
}
return null;
}
onFileSelected(event: any) {
const file = event.target.files[0];
if (file) {
this.selectedFile = file;
this.registerFormGroup.patchValue({ Photo: file });
} else {
this.selectedFile = null;
}
}
RegisterUser() {
this.submitted = true;
if (this.registerFormGroup.valid && this.selectedFile) {
console.log('Form is valid');
console.log('Selected file:', this.selectedFile);
const emailLowerCase = this.registerFormGroup.value.email.toLowerCase();
this.registerFormGroup.patchValue({ email: emailLowerCase });
const formData: FormData = new FormData();
formData.append('name', this.registerFormGroup.value.name);
formData.append('surname', this.registerFormGroup.value.surname);
formData.append('email', this.registerFormGroup.value.email);
formData.append('password', this.registerFormGroup.value.password);
formData.append('PhoneNumber', this.registerFormGroup.value.PhoneNumber);
formData.append('Date_of_Birth', this.registerFormGroup.value.Date_of_Birth);
formData.append('Id_Number', this.registerFormGroup.value.Id_Number);
formData.append('Physical_Address', this.registerFormGroup.value.Physical_Address);
formData.append('Photo', this.selectedFile, this.selectedFile.name);
formData.append('User_Status_ID', this.registerFormGroup.value.User_Status_ID);
formData.append('User_Type_ID', this.registerFormGroup.value.User_Type_ID);
this.userService.RegisterUser(formData).subscribe({
next: (response) => {
console.log('Registration Success:', response);
this.registerFormGroup.reset();
this.openSnackbar('Your user profile has been created', 'success');
this.router.navigate(['/login']);
},
error: (error) => {
console.log('Registration Error:', error);
let errorMessage = 'Registration failed: ';
if (error.error === 'DuplicateEmail') {
errorMessage += 'This email address is already registered.';
} else if (error.error === 'DuplicatePhoneNumber') {
errorMessage += 'This phone number is already registered.';
} else if (error.error === 'DuplicateDateOfBirth') {
errorMessage += 'This date of birth is already registered.';
} else if (error.error === 'DuplicateIdNumber') {
errorMessage += 'This ID number is already registered.';
} else if (error.error === 'DuplicatePhoto') {
errorMessage += 'This photo is already associated with another user.';
} else {
errorMessage += 'Unknown error. Please try again later.';
}
this.openSnackbar(errorMessage, 'danger');
}
});
} else {
console.log('Form is not valid or file is not selected');
console.log(this.registerFormGroup.errors);
console.log(this.registerFormGroup.controls);
this.openSnackbar('Form is not filled in correctly', 'danger');
}
}
openSnackbar(message: string, type: 'success' | 'danger') {
this.snackBar.open(message, 'Close', {
duration: 5000,
panelClass: type === 'success' ? 'snackbar-success' : 'snackbar-danger'
});
}
get f() {
return this.registerFormGroup.controls;
}
resetForm() {
this.registerFormGroup.reset({
user_status_id: 1 // Reset user_status_id to default value of 1 (Active)
});
this.router.navigate(['/login']);
}
}
//css
.register-wrapper {
height: 100%;
display: flex;
justify-content: center;
align-items: center;
background: #f0f4f7; /* Light blue background */
}
.box {
padding: 60px 50px 40px;
width: 100%;
max-width: 800px;
background: #fff;
border-radius: 10px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
}
.card-header {
text-align: center;
font-weight: 700;
color: #000; /* Blue color for header text */
}
.card-title {
font-size: 30px;
margin: 0;
}
.form-group label {
color: #000; /* Blue color for form labels */
}
.form-control {
border: 1px solid #ccc;
padding: 10px;
border-radius: 5px;
transition: border-color 0.3s ease-in-out;
}
.form-control:focus {
border-color: #000; /* Blue border on focus */
box-shadow: 0 0 5px rgba(63, 81, 181, 0.2); /* Light blue shadow on focus */
}
.text-danger {
color: #f44336; /* Red color for error messages */
}
.btn-primary {
background-color: #4caf50; /* Green background for primary button */
border-color: #4caf50; /* Green border for primary button */
color: #fff; /* White text for primary button */
}
.btn-secondary {
background-color: #f44336; /* Red background for secondary button */
border-color: #f44336; /* Red border for secondary button */
color: #fff; /* White text for secondary button */
}
.card-footer {
display: flex;
justify-content: space-between;
padding: 20px;
}
.card-footer .btn {
width: 48%;
}
/* Snackbar Styles */
.snackbar {
visibility: visible;
min-width: 250px;
margin-left: -125px;
background-color: #333;
color: #fff;
text-align: center;
border-radius: 2px;
padding: 16px;
position: fixed;
z-index: 1;
left: 50%;
bottom: 30px;
font-size: 17px;
}
.snackbar-success {
background-color: #4caf50; /* Green for success */
}
.snackbar-danger {
background-color: #f44336; /* Red for error */
}
.close-snackbar {
color: white;
font-weight: bold;
float: right;
font-size: 22px;
line-height: 20px;
cursor: pointer;
background: none;
border: none;
}