refactor: SharedService refactored and dissolved, created ButtonStateService, renamed ContactEditDialog to ContactOverlay and moved to Overlays

This commit is contained in:
Chneemann 2025-03-30 19:29:24 +02:00
parent 8659c16517
commit db242700e0
44 changed files with 209 additions and 726 deletions

View file

@ -1 +1 @@
<router-outlet></router-outlet> <app-overlay></app-overlay>
<router-outlet></router-outlet>

View file

@ -1,11 +1,10 @@
import { Component } from '@angular/core';
import { RouterOutlet } from '@angular/router';
import { OverlayComponent } from './shared/components/overlay/overlay.component';
@Component({
selector: 'app-root',
standalone: true,
imports: [RouterOutlet, OverlayComponent],
imports: [RouterOutlet],
templateUrl: './app.component.html',
styleUrl: './app.component.scss',
})

View file

@ -9,7 +9,6 @@ import { OverlayService } from '../../services/overlay.service';
import { FormBtnComponent } from '../../shared/components/buttons/form-btn/form-btn.component';
import { ActivatedRoute, Router } from '@angular/router';
import { TranslateModule } from '@ngx-translate/core';
import { SharedService } from '../../services/shared.service';
import { AuthService } from '../../services/auth.service';
import { firstValueFrom, map } from 'rxjs';
import { TaskService } from '../../services/task.service';
@ -49,7 +48,6 @@ export class AddTaskComponent implements OnInit {
constructor(
public firebaseService: FirebaseService,
private overlayService: OverlayService,
private sharedService: SharedService,
private taskService: TaskService,
private apiService: ApiService,
private authService: AuthService,

View file

@ -1,19 +0,0 @@
<section>
<div class="dialog">
<p>
{{ "contactDeleteDialog.deleteContact" | translate }}
</p>
<div class="btns">
<div class="btn">
<div class="btn-cancel" (click)="cancelDeleteContact()">
{{ "contactDeleteDialog.btnCancel" | translate }}
</div>
</div>
<div class="btn">
<div class="btn-delete-contact" (click)="deleteContact()">
{{ "contactDeleteDialog.btnDelete" | translate }}
</div>
</div>
</div>
</div>
</section>

View file

@ -1,109 +0,0 @@
section {
width: 100vw;
height: 100vh;
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
display: flex;
justify-content: center;
align-items: center;
}
.dialog {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
background-color: var(--white);
width: 600px;
height: 200px;
border-radius: 26px;
margin: 24px;
border: 2px solid rgba($color: #000000, $alpha: 0.1);
p {
text-align: center;
font-size: 27px;
font-weight: 500;
margin-bottom: 12px;
padding: 0 12px;
}
}
.btns {
display: flex;
justify-content: center;
align-items: center;
}
.btn {
display: flex;
flex-direction: column;
align-items: center;
width: 111px;
height: 57px;
margin: 0 24px;
}
.btn-cancel {
padding: 12px;
margin: 12px 12px;
border-radius: 10px;
border-color: var(--black);
background-color: var(--dark-blue);
color: var(--white);
font-size: 23px;
font-weight: 400;
transition: 125ms ease-in-out;
cursor: pointer;
&:hover {
background-color: var(--light-blue);
box-shadow: 2px 2px 2px 0px rgba(0, 0, 0, 0.3);
}
}
.btn-delete-contact {
padding: 12px;
margin: 12px 12px;
border-radius: 10px;
color: var(--red);
background-color: var(--white);
border: 1px solid var(--red);
font-size: 23px;
font-weight: 400;
transition: 125ms ease-in-out;
cursor: pointer;
&:hover {
color: var(--white);
background-color: var(--red);
border-color: var(--black);
box-shadow: 2px 2px 2px 0px rgba(0, 0, 0, 0.3);
}
}
@media screen and (max-width: 450px) {
.dialog {
p {
font-size: 22px;
}
}
}
@media screen and (max-width: 350px) {
.dialog {
width: 280px;
p {
font-size: 22px;
}
}
.btn {
width: 100px;
}
.btn-delete-contact,
.btn-cancel {
font-size: 18px;
}
}

View file

@ -1,23 +0,0 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { ContactDeleteComponent } from './contact-delete.component';
describe('ContactDeleteComponent', () => {
let component: ContactDeleteComponent;
let fixture: ComponentFixture<ContactDeleteComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [ContactDeleteComponent]
})
.compileComponents();
fixture = TestBed.createComponent(ContactDeleteComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View file

@ -1,69 +0,0 @@
import { Component, Input } from '@angular/core';
import { SharedService } from '../../../services/shared.service';
import { TranslateModule } from '@ngx-translate/core';
import { Router } from '@angular/router';
import { FirebaseService } from '../../../services/firebase.service';
@Component({
selector: 'app-contact-delete',
standalone: true,
imports: [TranslateModule],
templateUrl: './contact-delete.component.html',
styleUrl: './contact-delete.component.scss',
})
export class ContactDeleteComponent {
@Input() currentUserId: string = '';
constructor(
private sharedService: SharedService,
private firebaseService: FirebaseService,
private router: Router
) {}
/**
* Deletes the current user and performs cleanup operations.
* This method deletes the user with the current user ID from the database,
* navigates to the contacts page, and closes any open dialog flags in the shared service.
* It also checks if the deleted contact was assigned to any tasks and removes them.
*/
deleteContact() {
this.firebaseService.deleteUser(this.currentUserId);
this.router.navigate(['contacts']);
this.sharedService.isDeleteContactDialogOpen = false;
this.sharedService.isAnyDialogOpen = false;
this.checkIfContactAnAssigned();
}
/**
* Checks if the deleted contact was assigned to any tasks and removes them.
* This method retrieves all tasks from the database, iterates over them,
* and checks if the current user ID is in the task's assigned array.
* If the ID is found, it is removed from the array and the modified task
* is updated in the database.
*/
checkIfContactAnAssigned() {
const tasks = this.firebaseService.getAllTasks();
tasks.forEach((task) => {
const index = task.assigned.indexOf(this.currentUserId);
if (index !== -1) {
task.assigned.splice(index, 1);
const { id, ...taskWithoutIds } = task;
if (task.id) {
this.firebaseService.replaceTaskData(task.id, taskWithoutIds);
}
}
});
}
/**
* Closes the delete contact dialog by setting the appropriate flags in the shared service.
* If the edit contact dialog is not open, it also closes any open dialog flags in the shared service.
*/
cancelDeleteContact() {
this.sharedService.isDeleteContactDialogOpen = false;
if (!this.sharedService.isEditContactDialogOpen) {
this.sharedService.isAnyDialogOpen = false;
}
}
}

View file

@ -49,17 +49,17 @@
@if(selectedUser.isContactOnly || currentUser && selectedUser.id ===
currentUser.id) {
<div class="btns">
<div class="btn btn-edit">
<div class="btn btn-edit" (click)="editContact(selectedUser)">
<img src="./../../../../assets/img/contact/edit.svg" alt="" />
<p (click)="openEditDialog()">
<p>
{{ "contacts.btnEdit0" | translate }}
</p>
</div>
@if (selectedUser.isContactOnly || currentUser && selectedUser.id !==
currentUser.id) {
<div class="btn btn-delete">
<div class="btn btn-delete" (click)="openDeleteContactDialog()">
<img src="./../../../../assets/img/contact/delete.svg" alt="" />
<p (click)="deleteContact()">
<p>
{{ "contacts.btnDelete0" | translate }}
</p>
</div>
@ -96,10 +96,7 @@
</div>
</div>
</div>
} @if (sharedService.isMobileNavbarOpen) {
<app-contact-nav
[deleteContact]="deleteContact"
[openEditDialog]="openEditDialog"
></app-contact-nav>
} @if (isMobileNavbarOpen) {
<!-- TODO -->
}
</section>

View file

@ -1,26 +1,22 @@
import {
Component,
EventEmitter,
HostListener,
Input,
Output,
SimpleChanges,
} from '@angular/core';
import { CommonModule } from '@angular/common';
import { Router } from '@angular/router';
import { SharedService } from '../../../services/shared.service';
import { ContactNavComponent } from '../contact-nav/contact-nav.component';
import { FirebaseService } from '../../../services/firebase.service';
import { LanguageService } from '../../../services/language.service';
import { TranslateModule } from '@ngx-translate/core';
import { UserService } from '../../../services/user.service';
import { finalize } from 'rxjs';
import { User } from '../../../interfaces/user.interface';
import { OverlayService } from '../../../services/overlay.service';
@Component({
selector: 'app-contact-detail',
standalone: true,
imports: [CommonModule, TranslateModule, ContactNavComponent],
imports: [CommonModule, TranslateModule],
templateUrl: './contact-detail.component.html',
styleUrl: './contact-detail.component.scss',
})
@ -31,10 +27,11 @@ export class ContactDetailComponent {
isLoading: boolean = false;
selectedUser: User | null = null;
isMobileNavbarOpen: boolean = false;
constructor(
public sharedService: SharedService,
public firebaseService: FirebaseService,
private overlayService: OverlayService,
private userService: UserService
) {}
@ -84,68 +81,24 @@ export class ContactDetailComponent {
* the mobile navigation bar when the user clicks the three points icon.
*/
toggleNav() {
this.sharedService.isMobileNavbarOpen =
!this.sharedService.isMobileNavbarOpen;
this.isMobileNavbarOpen = !this.isMobileNavbarOpen;
}
/**
* Opens the edit contact dialog by setting the appropriate flags in the shared service.
* This method is used by the contact details component to open the edit contact dialog when the user clicks the edit button.
*/
openEditDialog() {
this.sharedService.isAnyDialogOpen = true;
this.sharedService.isEditContactDialogOpen = true;
this.sharedService.isMobileNavbarOpen = false;
editContact(userData: User) {
this.overlayService.setOverlayData('contactOverlay', userData);
this.isMobileNavbarOpen = false;
}
/**
* Opens the delete contact dialog by setting the appropriate flags in the shared service.
* This method is used by the contact details component to open the delete contact dialog when the user clicks the delete button.
*/
deleteContact() {
this.sharedService.isAnyDialogOpen = true;
this.sharedService.isDeleteContactDialogOpen = true;
this.sharedService.isMobileNavbarOpen = false;
}
@HostListener('document:click', ['$event'])
/**
* Handles the opening of the contact edit, new contact, and delete contact
* dialogs when the respective buttons are clicked.
*
* @param event The MouseEvent that was triggered.
*/
checkOpenContactEdit(event: MouseEvent) {
const targetElement = event.target as HTMLElement;
if (targetElement.closest('.btn-edit')) {
this.setDialogStatus(true, true, false, false);
} else if (targetElement.closest('.btn-new')) {
this.setDialogStatus(true, false, true, false);
} else if (targetElement.closest('.btn-delete')) {
this.setDialogStatus(true, false, false, true);
} else if (!targetElement.closest('.dialog')) {
this.setDialogStatus(false, false, false, false);
}
}
/**
* Updates the dialog status flags in the shared service.
*
* @param anyOpen - Indicates if any dialog is open.
* @param editOpen - Indicates if the edit contact dialog is open.
* @param newOpen - Indicates if the new contact dialog is open.
* @param deleteOpen - Indicates if the delete contact dialog is open.
*/
private setDialogStatus(
anyOpen: boolean,
editOpen: boolean,
newOpen: boolean,
deleteOpen: boolean
) {
this.sharedService.isAnyDialogOpen = anyOpen;
this.sharedService.isEditContactDialogOpen = editOpen;
this.sharedService.isNewContactDialogOpen = newOpen;
this.sharedService.isDeleteContactDialogOpen = deleteOpen;
openDeleteContactDialog() {
// TODO
this.isMobileNavbarOpen = false;
}
}

View file

@ -1,12 +0,0 @@
<nav class="navbar">
<div class="link btn-edit">
<span (click)="openEditDialog()">{{
"contacts.btnEdit1" | translate
}}</span>
</div>
<div class="link btn-delete">
<span (click)="deleteContact()">{{
"contacts.btnDelete1" | translate
}}</span>
</div>
</nav>

View file

@ -1,37 +0,0 @@
.navbar {
position: fixed;
display: flex;
flex-direction: column;
bottom: 146px;
right: 80px;
width: 110px;
height: 108px;
background-color: var(--bgSidebar);
border-radius: 20px 20px 0 20px;
box-shadow: 0px 0px 4px 0px rgba(0, 0, 0, 0.1);
padding: 10px;
z-index: 5;
}
.link {
display: flex;
align-items: center;
height: 46px;
padding: 8px 16px;
border-radius: 8px;
color: var(--white);
cursor: pointer;
span {
text-align: center;
width: 118px;
word-wrap: break-word;
overflow-wrap: break-word;
white-space: normal;
}
&:hover {
background-color: var(--very-dark-blue);
span {
color: var(--light-blue);
}
}
}

View file

@ -1,23 +0,0 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { ContactNavComponent } from './contact-nav.component';
describe('ContactNavComponent', () => {
let component: ContactNavComponent;
let fixture: ComponentFixture<ContactNavComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [ContactNavComponent]
})
.compileComponents();
fixture = TestBed.createComponent(ContactNavComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View file

@ -1,17 +0,0 @@
import { Component, Input } from '@angular/core';
import { SharedService } from '../../../services/shared.service';
import { TranslateModule } from '@ngx-translate/core';
@Component({
selector: 'app-contact-nav',
standalone: true,
imports: [TranslateModule],
templateUrl: './contact-nav.component.html',
styleUrl: './contact-nav.component.scss',
})
export class ContactNavComponent {
@Input() deleteContact!: () => any;
@Input() openEditDialog!: () => any;
constructor(public sharedService: SharedService) {}
}

View file

@ -5,7 +5,7 @@
'd-none': !showAllUsers && selectedUserId != null
}"
>
<button class="btn-new" type="submit" (click)="openNewContactDialog()">
<button class="btn-new" type="submit" (click)="addNewContact()">
<div class="btn-inside">
<span>{{ "contacts.btnNew" | translate }}</span>
<img src="./../../../assets/img/contact/add.svg" alt="check" />

View file

@ -1,14 +1,12 @@
import { Component, HostListener } from '@angular/core';
import { User } from '../../interfaces/user.interface';
import { CommonModule } from '@angular/common';
import { ActivatedRoute, RouterLink } from '@angular/router';
import { ContactDetailComponent } from './contact-detail/contact-detail.component';
import { SharedService } from '../../services/shared.service';
import { FirebaseService } from '../../services/firebase.service';
import { TranslateModule } from '@ngx-translate/core';
import { ApiService } from '../../services/api.service';
import { UserService } from '../../services/user.service';
import { finalize } from 'rxjs';
import { OverlayService } from '../../services/overlay.service';
@Component({
selector: 'app-contacts',
@ -27,7 +25,7 @@ export class ContactsComponent {
constructor(
public firebaseService: FirebaseService,
private userService: UserService,
public sharedService: SharedService
private overlayService: OverlayService
) {}
/**
@ -95,15 +93,8 @@ export class ContactsComponent {
return uniqueFirstLetters;
}
/**
* Opens the new contact dialog.
* This function sets the isAnyDialogOpen and isNewContactDialogOpen
* properties of the shared service to true, which will open the new contact
* dialog.
*/
openNewContactDialog() {
this.sharedService.isAnyDialogOpen = true;
this.sharedService.isNewContactDialogOpen = true;
addNewContact() {
this.overlayService.setOverlayData('contactOverlay', 'new');
}
@HostListener('window:resize', ['$event'])

View file

@ -57,7 +57,7 @@
[disabled]="
mail.invalid ||
!pwResetData.mail ||
sharedService.isBtnDisabled ||
isButtonDisabled() ||
!checkIfUserEmailIsValid(pwResetData.mail)
"
></app-form-btn>

View file

@ -6,8 +6,8 @@ import { FooterComponent } from '../footer/footer.component';
import { HeaderComponent } from '../header/header.component';
import { TranslateModule } from '@ngx-translate/core';
import { LoginService } from '../../../services/login.service';
import { SharedService } from '../../../services/shared.service';
import { BtnBackComponent } from '../../../shared/components/buttons/btn-back/btn-back.component';
import { ButtonStateService } from '../../../services/button-state.service';
@Component({
selector: 'app-forgot-pw',
@ -31,16 +31,20 @@ export class ForgotPwComponent {
constructor(
public loginService: LoginService,
public sharedService: SharedService
private buttonStateService: ButtonStateService
) {}
onSubmit(ngForm: NgForm) {
this.sharedService.isBtnDisabled = true;
this.buttonStateService.enableButton();
if (ngForm.submitted && ngForm.form.valid) {
this.loginService.passwordReset(this.pwResetData.mail.toLowerCase());
}
}
isButtonDisabled() {
return this.buttonStateService.isButtonDisabled;
}
checkIfUserEmailIsValid(emailValue: string) {
const emailRegex = /^[\w.%+-]+@[\w.-]+\.[a-zA-Z]{2,}$/;
if (emailRegex.test(emailValue)) {

View file

@ -92,7 +92,7 @@
!pwResetData.password ||
passwordConfirm.invalid ||
!pwResetData.passwordConfirm ||
sharedService.isBtnDisabled ||
isButtonDisabled() ||
pwResetData.password.length < 6 ||
pwResetData.password !== pwResetData.passwordConfirm
"

View file

@ -5,11 +5,10 @@ import { FormBtnComponent } from '../../../../shared/components/buttons/form-btn
import { FooterComponent } from '../../footer/footer.component';
import { HeaderComponent } from '../../header/header.component';
import { TranslateModule } from '@ngx-translate/core';
import { FirebaseService } from '../../../../services/firebase.service';
import { LoginService } from '../../../../services/login.service';
import { ActivatedRoute, Router } from '@angular/router';
import { SharedService } from '../../../../services/shared.service';
import { ActivatedRoute } from '@angular/router';
import { Subscription } from 'rxjs';
import { ButtonStateService } from '../../../../services/button-state.service';
@Component({
selector: 'app-pw-reset',
@ -35,11 +34,9 @@ export class PwResetComponent {
};
constructor(
private firebaseService: FirebaseService,
public loginService: LoginService,
public sharedService: SharedService,
private route: ActivatedRoute,
private router: Router
private buttonStateService: ButtonStateService,
private route: ActivatedRoute
) {}
ngOnInit(): void {
@ -50,8 +47,12 @@ export class PwResetComponent {
);
}
isButtonDisabled() {
return this.buttonStateService.isButtonDisabled;
}
onSubmit(ngForm: NgForm) {
this.sharedService.isBtnDisabled = true;
this.buttonStateService.enableButton();
if (ngForm.submitted && ngForm.form.valid) {
this.loginService.newPassword(this.pwResetData.password, this.oobCode);
}

View file

@ -1,4 +1,4 @@
@if (sharedService.isBtnDisabled) {
@if (isButtonDisabled()) {
<div class="loading-dialog">
<div id="loading" class="loader"></div>
<div id="loadingText" class="loading-text">

View file

@ -1,6 +1,6 @@
import { Component } from '@angular/core';
import { SharedService } from '../../../services/shared.service';
import { TranslateModule } from '@ngx-translate/core';
import { ButtonStateService } from '../../../services/button-state.service';
@Component({
selector: 'app-loading-dialog',
@ -10,5 +10,9 @@ import { TranslateModule } from '@ngx-translate/core';
styleUrl: './loading-dialog.component.scss',
})
export class LoadingDialogComponent {
constructor(public sharedService: SharedService) {}
constructor(private buttonStateService: ButtonStateService) {}
isButtonDisabled() {
return this.buttonStateService.isButtonDisabled;
}
}

View file

@ -33,14 +33,14 @@
<img class="custom-img" alt="" />
}
<div class="error-msg">
@if (!mail.valid && mail.touched && !sharedService.isBtnDisabled) {
@if (!mail.valid && mail.touched && !isButtonDisabled()) {
<p>{{ "login.errorMail0" | translate }}</p>
} @if (loginService.errorCode == 'auth/invalid-email' &&
!sharedService.isBtnDisabled) {
!isButtonDisabled()) {
<p>{{ "login.errorMail1" | translate }}</p>
} @if (mail.valid && mail.touched &&
!checkIfUserEmailIsValid(loginData.email.toLowerCase()) &&
!sharedService.isBtnDisabled) {
!isButtonDisabled()) {
<p>{{ "login.errorMail2" | translate }}</p>
}
</div>
@ -73,11 +73,10 @@
/>
}
<div class="error-msg">
@if (!password.valid && password.touched &&
!sharedService.isBtnDisabled) {
@if (!password.valid && password.touched && !isButtonDisabled()) {
<p>{{ "login.errorPassword0" | translate }}</p>
} @if (loginService.errorCode == 'auth/invalid-credential' &&
!sharedService.isBtnDisabled) {
!isButtonDisabled()) {
<p>{{ "login.errorPassword1" | translate }}</p>
}
</div>
@ -120,7 +119,7 @@
!loginData.email ||
password.invalid ||
!loginData.password ||
sharedService.isBtnDisabled ||
isButtonDisabled() ||
!checkIfUserEmailIsValid(loginData.email)
"
></app-form-btn>
@ -128,7 +127,7 @@
[class]="'btn-guest-login'"
[type]="'button'"
[value]="'login.guest' | translate"
[disabled]="sharedService.isBtnDisabled"
[disabled]="isButtonDisabled()"
(click)="guestLogin()"
></app-form-btn>
</div>

View file

@ -2,10 +2,8 @@ import { CommonModule } from '@angular/common';
import { Component } from '@angular/core';
import { FormsModule, NgForm } from '@angular/forms';
import { FormBtnComponent } from '../../shared/components/buttons/form-btn/form-btn.component';
import { FirebaseService } from '../../services/firebase.service';
import { ActivatedRoute, Router, RouterLink } from '@angular/router';
import { LoginService } from '../../services/login.service';
import { SharedService } from '../../services/shared.service';
import { FooterComponent } from './footer/footer.component';
import { HeaderComponent } from './header/header.component';
import { TranslateModule } from '@ngx-translate/core';
@ -13,6 +11,7 @@ import { LoadingDialogComponent } from './loading-dialog/loading-dialog.componen
import { OverlayService } from '../../services/overlay.service';
import { AuthService } from '../../services/auth.service';
import { TokenService } from '../../services/token.service';
import { ButtonStateService } from '../../services/button-state.service';
@Component({
selector: 'app-login',
@ -43,8 +42,8 @@ export class LoginComponent {
private authService: AuthService,
public loginService: LoginService,
private tokenService: TokenService,
public sharedService: SharedService,
private overlayService: OverlayService,
private buttonStateService: ButtonStateService,
private route: ActivatedRoute,
private router: Router
) {}
@ -65,26 +64,30 @@ export class LoginComponent {
});
}
isButtonDisabled() {
return this.buttonStateService.isButtonDisabled;
}
deleteTokens() {
this.tokenService.deleteAuthToken();
this.tokenService.deleteUserId();
}
async onSubmit(ngForm: NgForm) {
this.sharedService.isBtnDisabled = true;
this.buttonStateService.enableButton();
if (ngForm.submitted && ngForm.form.valid) {
try {
await this.authService.login(this.loginData, this.checkboxRememberMe);
this.router.navigate(['/summary']);
this.sharedService.isBtnDisabled = false;
this.buttonStateService.disableButton();
} catch (error) {
this.sharedService.isBtnDisabled = false;
this.buttonStateService.disableButton();
}
}
}
guestLogin() {
this.sharedService.isBtnDisabled = true;
this.buttonStateService.enableButton();
this.loginData.email = 'guest@guestaccount.com';
this.loginData.password = 'guest@guestaccount.com';
this.isPasswordIconVisible = !this.isPasswordIconVisible;

View file

@ -39,11 +39,10 @@
<img class="custom-img" alt="" />
}
<div class="error-msg">
@if (name.hasError('pattern') && name.touched &&
!sharedService.isBtnDisabled) {
@if (name.hasError('pattern') && name.touched && !isButtonDisabled())
{
<p>{{ "register.errorPattern" | translate }}</p>
} @else { @if (!name.valid && name.touched &&
!sharedService.isBtnDisabled) {
} @else { @if (!name.valid && name.touched && !isButtonDisabled()) {
<p>{{ "register.errorName" | translate }}</p>
}}
</div>
@ -70,15 +69,15 @@
<div class="error-msg">
@if(!mail.valid && mail.touched &&
!checkIfUserEmailIsValid(registerData.mail.toLowerCase()) &&
!sharedService.isBtnDisabled) {
!isButtonDisabled()) {
<p>{{ "register.errorMail0" | translate }}</p>
} @else { @if (mail.touched &&
!checkIfUserEmailIsValid(registerData.mail.toLowerCase()) &&
!sharedService.isBtnDisabled) {
!isButtonDisabled()) {
<p>{{ "register.errorMail1" | translate }}</p>
} @else { @if
(existEmailOnServer(registerData.mail.toLowerCase()).length > 0 &&
!sharedService.isBtnDisabled) {
!isButtonDisabled()) {
<p>{{ "register.errorMail2" | translate }}</p>
} } }
</div>
@ -109,11 +108,10 @@
/>
}
<div class="error-msg">
@if (!password.valid && password.touched &&
!sharedService.isBtnDisabled) {
@if (!password.valid && password.touched && !isButtonDisabled()) {
<p>{{ "register.errorPassword0" | translate }}</p>
} @else { @if (registerData.password.length < 6 && password.touched &&
!sharedService.isBtnDisabled) {
!isButtonDisabled()) {
<p>{{ "register.errorPassword1" | translate }}</p>
} }
</div>
@ -145,11 +143,11 @@
}
<div class="error-msg">
@if (!passwordConfirm.valid && passwordConfirm.touched &&
!sharedService.isBtnDisabled) {
!isButtonDisabled()) {
<p>{{ "register.errorPassword0" | translate }}</p>
} @if (registerData.password !== registerData.passwordConfirm &&
registerData.password !== "" && registerData.passwordConfirm !== "" &&
!sharedService.isBtnDisabled) {
!isButtonDisabled()) {
<p>{{ "register.errorPassword2" | translate }}</p>
}
</div>
@ -188,7 +186,7 @@
password.invalid ||
!registerData.password ||
!checkbox.valid ||
sharedService.isBtnDisabled ||
isButtonDisabled() ||
registerData.password.length < 6 ||
registerData.password !== registerData.passwordConfirm ||
!checkIfUserEmailIsValid(registerData.mail)

View file

@ -6,11 +6,11 @@ import { CommonModule } from '@angular/common';
import { FormBtnComponent } from '../../../shared/components/buttons/form-btn/form-btn.component';
import { FirebaseService } from '../../../services/firebase.service';
import { LoginService } from '../../../services/login.service';
import { SharedService } from '../../../services/shared.service';
import { BtnBackComponent } from '../../../shared/components/buttons/btn-back/btn-back.component';
import { RouterModule } from '@angular/router';
import { TranslateModule, TranslateService } from '@ngx-translate/core';
import { LoadingDialogComponent } from '../loading-dialog/loading-dialog.component';
import { ButtonStateService } from '../../../services/button-state.service';
@Component({
selector: 'app-register',
@ -43,18 +43,22 @@ export class RegisterComponent {
constructor(
private firebaseService: FirebaseService,
public loginService: LoginService,
public sharedService: SharedService,
public translateService: TranslateService
public translateService: TranslateService,
private buttonStateService: ButtonStateService
) {}
onSubmit(ngForm: NgForm) {
this.sharedService.isBtnDisabled = true;
this.buttonStateService.enableButton();
if (ngForm.submitted && ngForm.form.valid) {
this.splitName();
this.loginService.register(this.registerData);
}
}
isButtonDisabled() {
return this.buttonStateService.isButtonDisabled;
}
splitName() {
const names = this.registerData.name.split(' ');
this.registerData.firstName = names[0];

View file

@ -1,8 +1,4 @@
<div
[ngClass]="{
'blur-background': sharedService.isAnyDialogOpen
}"
>
<div>
<div class="container">
<app-sidebar></app-sidebar>
<app-header></app-header>
@ -12,23 +8,4 @@
</div>
<app-sidebar-mobile></app-sidebar-mobile>
</div>
@if (sharedService.isNewContactDialogOpen) {
<app-contact-edit
[ngClass]="{
'blur-background': sharedService.isDeleteContactDialogOpen,
'd-none': sharedService.isDeleteContactDialogOpen
}"
></app-contact-edit>
} @if (sharedService.isEditContactDialogOpen) {
<app-contact-edit
[currentUserId]="sharedService.currentUserId"
[ngClass]="{
'blur-background': sharedService.isDeleteContactDialogOpen,
'd-none': sharedService.isDeleteContactDialogOpen
}"
></app-contact-edit>
} @if (sharedService.isDeleteContactDialogOpen) {
<app-contact-delete
[currentUserId]="sharedService.currentUserId"
></app-contact-delete>
}
<app-overlay></app-overlay>

View file

@ -1,15 +1,14 @@
import { Component } from '@angular/core';
import { NavigationEnd, Router, RouterOutlet } from '@angular/router';
import { RouterOutlet } from '@angular/router';
import { CommonModule } from '@angular/common';
import { filter } from 'rxjs';
import { FirebaseService } from '../../services/firebase.service';
import { LanguageService } from '../../services/language.service';
import { SharedService } from '../../services/shared.service';
import { SidebarMobileComponent } from '../../shared/components/sidebar/sidebar-mobile/sidebar-mobile.component';
import { SidebarComponent } from '../../shared/components/sidebar/sidebar.component';
import { ContactDeleteComponent } from '../contacts/contact-delete/contact-delete.component';
import { ContactEditNewComponent } from '../contacts/contact-edit-new/contact-edit-new.component';
import { HeaderComponent } from '../../shared/components/header/header.component';
import { UserService } from '../../services/user.service';
import { User } from '../../interfaces/user.interface';
import { OverlayComponent } from '../../shared/components/overlay/overlay.component';
@Component({
selector: 'app-main-layout',
@ -19,83 +18,27 @@ import { HeaderComponent } from '../../shared/components/header/header.component
HeaderComponent,
SidebarComponent,
SidebarMobileComponent,
ContactEditNewComponent,
ContactDeleteComponent,
CommonModule,
OverlayComponent,
],
templateUrl: './main-layout.component.html',
styleUrl: './main-layout.component.scss',
})
export class MainLayoutComponent {
isLoggedIn: string = '';
currentUser: User | null = null;
constructor(
public langService: LanguageService,
public sharedService: SharedService,
private firebaseService: FirebaseService,
private router: Router
) {
this.checkAndClearLocalStorage();
this.isLoggedIn = this.firebaseService.getCurrentUserId();
private userService: UserService
) {}
ngOnInit(): void {
this.loadCurrentUser();
}
/**
* Lifecycle hook that is called after the component has been initialized.
*
* Checks if the user is logged in by verifying the `isLoggedIn` property.
*/
ngOnInit() {
if (this.isLoggedIn === null) {
this.checkPwResetRoute();
} else {
this.router.navigate(['/summary']);
this.sharedService.isBtnDisabled = false;
}
}
/**
* Clears the local storage after a certain time period (12h) has
* passed since the last login.
*/
checkAndClearLocalStorage() {
const startTime = localStorage.getItem('sessionTimeJOIN');
if (startTime) {
const startTimeMills = parseInt(startTime);
const currentTime = new Date().getTime();
const timeDifference = 12 * 60 * 60 * 1000; // 12h
if (currentTime - startTimeMills > timeDifference) {
localStorage.clear();
}
}
}
/**
* Listens to router events and checks if the current route is one of the
* allowed routes for password reset, registration, forgotten password,
* or login. If it is not, it navigates to the login page.
*/
checkPwResetRoute() {
this.router.events
.pipe(filter((event) => event instanceof NavigationEnd))
.subscribe(() => {
const urlTree = this.router.parseUrl(this.router.url);
const firstSegment = this.getFirstSegment(urlTree);
const allowedRoutes = ['pw-reset', 'register', 'forgot-pw', 'login'];
if (!allowedRoutes.includes(firstSegment)) {
this.router.navigate(['/login']);
}
loadCurrentUser(): void {
this.userService.getCurrentUser().subscribe((userData) => {
this.currentUser = userData;
});
}
/**
* Returns the first segment of the current URL or an empty string if it does not exist.
*
* @param urlTree The current URL tree.
* @returns The first segment of the current URL or an empty string if it does not exist.
*/
private getFirstSegment(urlTree: any): string {
return urlTree.root.children['primary']?.segments[0]?.path || '';
}
}

View file

@ -0,0 +1,16 @@
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root',
})
export class ButtonStateService {
isButtonDisabled: boolean = false;
disableButton() {
this.isButtonDisabled = true;
}
enableButton() {
this.isButtonDisabled = false;
}
}

View file

@ -1,34 +0,0 @@
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root',
})
export class ColorService {
generateRandomColor(): string {
const letters = '0123456789ABCDEF';
let color = '#';
let isGrayScale = true;
while (isGrayScale) {
for (let i = 0; i < 6; i++) {
color += letters[Math.floor(Math.random() * 16)];
}
const rgb = this.hexToRgb(color);
if (rgb.r !== rgb.g || rgb.g !== rgb.b) {
isGrayScale = false;
} else {
color = '#';
}
}
return color;
}
hexToRgb(hex: string): { r: number; g: number; b: number } {
const bigint = parseInt(hex.substring(1), 16);
const r = (bigint >> 16) & 255;
const g = (bigint >> 8) & 255;
const b = bigint & 255;
return { r, g, b };
}
}

View file

@ -19,13 +19,12 @@ import {
updateDoc,
where,
} from '@angular/fire/firestore';
import { SharedService } from './shared.service';
import { User } from '../interfaces/user.interface';
import { Router } from '@angular/router';
import CryptoES from 'crypto-es';
import { CryptoESSecretKey } from '../environments/config';
import { catchError, map, Observable, of } from 'rxjs';
import { ColorService } from './color.service';
import { ButtonStateService } from './button-state.service';
@Injectable({
providedIn: 'root',
@ -40,8 +39,7 @@ export class LoginService {
constructor(
private firebaseService: FirebaseService,
private colorService: ColorService,
public sharedService: SharedService,
private buttonStateService: ButtonStateService,
private router: Router
) {}
@ -83,7 +81,7 @@ export class LoginService {
})
.catch((error) => {
this.errorCode = error.code;
this.sharedService.isBtnDisabled = false;
this.buttonStateService.disableButton();
});
}
@ -126,13 +124,13 @@ export class LoginService {
? registerData.firstName.slice(0, 1).toUpperCase() +
registerData.lastName.slice(0, 1).toUpperCase()
: '',
color: this.colorService.generateRandomColor(),
color: '',
lastLogin: new Date().getTime(),
};
this.createUserInFirestore(userDataToSave);
})
.catch((error) => {
this.sharedService.isBtnDisabled = false;
this.buttonStateService.disableButton();
});
}
@ -171,7 +169,7 @@ export class LoginService {
isOnline: true,
phone: '',
initials: firstName.slice(0, 1) + lastName.slice(0, 1),
color: this.colorService.generateRandomColor(),
color: '',
lastLogin: 0,
});
} else {
@ -180,7 +178,7 @@ export class LoginService {
});
})
.catch((error) => {
this.sharedService.isBtnDisabled = false;
this.buttonStateService.disableButton();
});
}
@ -333,10 +331,10 @@ export class LoginService {
sendPasswordResetEmail(auth, email, actionCodeSettings)
.then(() => {
this.router.navigate(['/login/notice/pw-send']);
this.sharedService.isBtnDisabled = false;
this.buttonStateService.disableButton();
})
.catch((error) => {
this.sharedService.isBtnDisabled = false;
this.buttonStateService.disableButton();
});
}
@ -357,10 +355,10 @@ export class LoginService {
confirmPasswordReset(auth, oobCode, newPW)
.then(() => {
this.router.navigate(['/login/notice/pw-change']);
this.sharedService.isBtnDisabled = false;
this.buttonStateService.disableButton();
})
.catch((error) => {
this.sharedService.isBtnDisabled = false;
this.buttonStateService.disableButton();
});
}
}

View file

@ -1,14 +0,0 @@
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root',
})
export class SharedService {
isBtnDisabled: boolean = false;
isAnyDialogOpen: boolean = false;
isMobileNavbarOpen: boolean = false;
isNewContactDialogOpen: boolean = false;
isEditContactDialogOpen: boolean = false;
isDeleteContactDialogOpen: boolean = false;
currentUserId: string = '';
}

View file

@ -1,3 +1,3 @@
<div class="btn" (click)="closeClicked()">
<div class="btn">
<img src="./../../../../assets/img/close.svg" />
</div>

View file

@ -1,5 +1,4 @@
import { Component, Input } from '@angular/core';
import { SharedService } from '../../../../services/shared.service';
@Component({
selector: 'app-btn-close',
@ -9,19 +8,5 @@ import { SharedService } from '../../../../services/shared.service';
styleUrl: './btn-close.component.scss',
})
export class BtnCloseComponent {
@Input() isContactDialogOpen: boolean = false;
constructor(private sharedService: SharedService) {}
/**
* Called when the close button is clicked.
* Sets isAnyDialogOpen to false and sets
* isEditContactDialogOpen and isNewContactDialogOpen
* to the value of isContactDialogOpen.
*/
closeClicked() {
this.sharedService.isAnyDialogOpen = false;
this.sharedService.isEditContactDialogOpen = this.isContactDialogOpen;
this.sharedService.isNewContactDialogOpen = this.isContactDialogOpen;
}
constructor() {}
}

View file

@ -121,13 +121,12 @@
}
</div>
<div class="btns">
@if (currentUserId && currentUserId !==
firebaseService.getCurrentUserId()){
@if (selectedUser && selectedUser !== firebaseService.getCurrentUserId()){
<app-form-btn
class="btn-delete"
type="button"
value="{{ 'contactDialogForm.btnDelete' | translate }}"
(click)="deleteContact()"
(click)="closeDialog()"
></app-form-btn>
} @else {
<app-form-btn

View file

@ -9,12 +9,10 @@ import {
} from '@angular/core';
import { FormsModule, NgForm } from '@angular/forms';
import { TranslateModule } from '@ngx-translate/core';
import { SharedService } from '../../../../services/shared.service';
import { FirebaseService } from '../../../../services/firebase.service';
import { FormBtnComponent } from '../../../../shared/components/buttons/form-btn/form-btn.component';
import { User } from '../../../../interfaces/user.interface';
import { Router } from '@angular/router';
import { ResizeService } from '../../../../services/resize.service';
import { FormBtnComponent } from '../../../buttons/form-btn/form-btn.component';
import { User } from '@sentry/angular';
import { FirebaseService } from '../../../../../services/firebase.service';
import { ResizeService } from '../../../../../services/resize.service';
@Component({
selector: 'app-contact-form',
@ -24,20 +22,17 @@ import { ResizeService } from '../../../../services/resize.service';
styleUrl: './contact-form.component.scss',
})
export class ContactFormComponent implements OnInit, OnChanges {
@Input() currentUserId: string = '';
@Input() selectedUser: any = [];
@Input() randomColor: string = '';
@Input() newColor: string = '';
@Input() currentColor: string = '';
@Output() initialsEmitter = new EventEmitter<string>();
@Output() closeDialogEmitter = new EventEmitter<string>();
constructor(
private router: Router,
public firebaseService: FirebaseService,
public resizeService: ResizeService,
public sharedService: SharedService
) {
this.updateContactData();
}
public resizeService: ResizeService
) {}
contactData = {
firstName: '',
@ -68,7 +63,8 @@ export class ContactFormComponent implements OnInit, OnChanges {
* properties of the userData object.
*/
ngOnInit() {
if (!this.currentUserId) {
this.updateContactData();
if (!this.selectedUser) {
this.userData = {
...this.userData,
color: this.randomColor,
@ -84,7 +80,7 @@ export class ContactFormComponent implements OnInit, OnChanges {
* @param changes an object containing the changed input properties
*/
ngOnChanges(changes: SimpleChanges) {
if (changes['currentUserId']) {
if (changes['selectedUser']) {
this.updateContactData();
}
}
@ -109,7 +105,7 @@ export class ContactFormComponent implements OnInit, OnChanges {
? this.contactData.firstName.slice(0, 1).toUpperCase() +
this.contactData.lastName.slice(0, 1).toUpperCase()
: '';
if (!this.currentUserId) {
if (!this.selectedUser) {
this.userData = {
...this.userData,
initials: initials,
@ -130,7 +126,7 @@ export class ContactFormComponent implements OnInit, OnChanges {
* object. Otherwise, it updates the contactData object.
*/
updateUserData() {
if (!this.currentUserId) {
if (!this.selectedUser) {
this.userData = {
...this.userData,
firstName: this.capitalizeFirstLetter(this.contactData.firstName),
@ -193,21 +189,11 @@ export class ContactFormComponent implements OnInit, OnChanges {
* joined into strings using a comma separator.
*/
private updateContactData() {
this.contactData.firstName = this.firebaseService
.getUserDetails(this.currentUserId, 'firstName')
.join(', ');
this.contactData.lastName = this.firebaseService
.getUserDetails(this.currentUserId, 'lastName')
.join(', ');
this.contactData.email = this.firebaseService
.getUserDetails(this.currentUserId, 'email')
.join(', ');
this.contactData.phone = this.firebaseService
.getUserDetails(this.currentUserId, 'phone')
.join(', ');
this.contactData.initials = this.firebaseService
.getUserDetails(this.currentUserId, 'initials')
.join(', ');
this.contactData.firstName = this.selectedUser.firstName;
this.contactData.lastName = this.selectedUser.lastName;
this.contactData.email = this.selectedUser.email;
this.contactData.phone = this.selectedUser.phone;
this.contactData.initials = this.selectedUser.initials;
}
/**
@ -220,45 +206,15 @@ export class ContactFormComponent implements OnInit, OnChanges {
*/
onSubmit(ngForm: NgForm) {
if (ngForm.submitted && ngForm.form.valid) {
if (this.currentUserId) {
console.log(this.newColor, this.currentColor);
this.newColor !== ''
? (this.contactData.color = this.newColor)
: (this.contactData.color = this.currentColor);
this.firebaseService.updateUserData(
this.currentUserId,
this.contactData
);
} else {
this.newColor !== ''
? (this.userData.color = this.newColor)
: (this.userData.color = this.randomColor);
const { id, ...taskWithoutIds } = this.userData;
this.firebaseService.addNewUser(taskWithoutIds).then((docRef) => {
this.router.navigate([`/contacts/${docRef.id}`]);
});
}
console.log('Save');
this.closeDialog();
}
}
/**
* Closes the delete contact dialog and the main dialog overlay.
*/
deleteContact() {
this.sharedService.isDeleteContactDialogOpen = false;
this.sharedService.isAnyDialogOpen = false;
}
/**
* Closes the contact dialog by updating the shared service flags
* to indicate that no dialog, edit contact dialog, or new contact dialog
* is currently open.
*/
closeDialog() {
this.sharedService.isAnyDialogOpen = false;
this.sharedService.isEditContactDialogOpen = false;
this.sharedService.isNewContactDialogOpen = false;
this.closeDialogEmitter.emit('');
}
}

View file

@ -1,23 +1,22 @@
@if (currentUserId) { @for (user of
firebaseService.getUserDataFromId(currentUserId); track user) {
@if (overlayData !== "new") {
<section>
<div class="dialog">
<div class="header">
<img src="./../../../../assets/img/logo.svg" alt="" />
<p>{{ "contacts.editContact" | translate }}</p>
<app-btn-close [isContactDialogOpen]="false"></app-btn-close>
<app-btn-close (click)="closeDialog()"></app-btn-close>
</div>
<div class="content">
<div class="badge">
<div class="picker">
<input
[(colorPicker)]="currentColor"
[style.background]="newColor === '' ? user.color : newColor"
[(colorPicker)]="overlayData.color"
[style.background]="newColor === '' ? overlayData.color : newColor"
(colorPickerChange)="updateColor($event)"
/>
<div class="initials">
@if (!userInitials) {
{{ user.initials }} } @else {
{{ overlayData.initials }} } @else {
{{ userInitials }}
}
</div>
@ -26,22 +25,23 @@ firebaseService.getUserDataFromId(currentUserId); track user) {
<div class="form">
<app-contact-form
(initialsEmitter)="initialsEmitter($event)"
[currentUserId]="currentUserId"
(closeDialogEmitter)="closeDialog()"
[selectedUser]="overlayData"
[newColor]="newColor"
[currentColor]="user.color"
[currentColor]="overlayData.color"
></app-contact-form>
</div>
</div>
<div class="notice">{{ "contacts.notice" | translate }}</div>
</div>
</section>
} } @else {
} @else {
<section>
<div class="dialog">
<div class="header">
<img src="./../../../../assets/img/logo.svg" alt="" />
<p>{{ "contacts.addContact" | translate }}</p>
<app-btn-close [isContactDialogOpen]="false"></app-btn-close>
<app-btn-close (click)="closeDialog()"></app-btn-close>
</div>
<div class="content">
<div class="badge">

View file

@ -1,16 +1,16 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { ContactEditNewComponent } from './contact-edit-new.component';
import { ContactOverlayComponent } from './contact-overlay.component';
describe('ContactEditComponent', () => {
let component: ContactEditNewComponent;
let fixture: ComponentFixture<ContactEditNewComponent>;
describe('ContactOverlayComponent', () => {
let component: ContactOverlayComponent;
let fixture: ComponentFixture<ContactOverlayComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [ContactEditNewComponent],
imports: [ContactOverlayComponent],
}).compileComponents();
fixture = TestBed.createComponent(ContactEditNewComponent);
fixture = TestBed.createComponent(ContactOverlayComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

View file

@ -1,15 +1,13 @@
import { Component, Input, OnInit } from '@angular/core';
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
import { CommonModule } from '@angular/common';
import { BtnCloseComponent } from '../../../shared/components/buttons/btn-close/btn-close.component';
import { FirebaseService } from '../../../services/firebase.service';
import { TranslateModule } from '@ngx-translate/core';
import { ContactFormComponent } from './contact-form/contact-form.component';
import { SharedService } from '../../../services/shared.service';
import { BtnCloseComponent } from '../../buttons/btn-close/btn-close.component';
import { TranslateModule } from '@ngx-translate/core';
import { ColorPickerModule } from 'ngx-color-picker';
import { ColorService } from '../../../services/color.service';
import { FirebaseService } from '../../../../services/firebase.service';
@Component({
selector: 'app-contact-edit',
selector: 'app-contact-overlay',
standalone: true,
imports: [
CommonModule,
@ -18,22 +16,19 @@ import { ColorService } from '../../../services/color.service';
TranslateModule,
ColorPickerModule,
],
templateUrl: './contact-edit-new.component.html',
styleUrl: './contact-edit-new.component.scss',
templateUrl: './contact-overlay.component.html',
styleUrl: './contact-overlay.component.scss',
})
export class ContactEditNewComponent implements OnInit {
@Input() currentUserId: string = '';
@Input() currentColor: string = '';
export class ContactOverlayComponent implements OnInit {
@Input() overlayData: any = [];
@Input() overlayType: string = '';
@Output() closeDialogEmitter = new EventEmitter<string>();
randomColor: string = '';
userInitials: string = '';
newColor: string = '';
constructor(
public firebaseService: FirebaseService,
public sharedService: SharedService,
private colorService: ColorService
) {}
constructor(public firebaseService: FirebaseService) {}
/**
* Lifecycle hook that is called after data-bound properties of a directive are
@ -41,7 +36,16 @@ export class ContactEditNewComponent implements OnInit {
* This method sets a random color for the user to be edited.
*/
ngOnInit() {
this.randomColor = this.colorService.generateRandomColor();
this.randomColor = this.getRandomColor();
}
getRandomColor(): string {
const letters = '0123456789ABCDEF';
let color = '#';
for (let i = 0; i < 6; i++) {
color += letters[Math.floor(Math.random() * 16)];
}
return color;
}
/**
@ -55,6 +59,10 @@ export class ContactEditNewComponent implements OnInit {
this.userInitials = emitter;
}
closeDialog() {
this.closeDialogEmitter.emit('');
}
/**
* Updates the newColor variable with the newly selected color.
*

View file

@ -1,5 +1,4 @@
import { Component, EventEmitter, Input, Output } from '@angular/core';
import { SharedService } from '../../../../services/shared.service';
import { BtnCloseComponent } from '../../buttons/btn-close/btn-close.component';
import { Router } from '@angular/router';
import { TranslateModule } from '@ngx-translate/core';
@ -16,7 +15,7 @@ export class DialogOverlayComponent {
@Input() overlayType: string = '';
@Output() closeDialogEmitter = new EventEmitter<string>();
constructor(public sharedService: SharedService, private router: Router) {}
constructor(private router: Router) {}
/**
* Navigates to the login route and emits an empty string via the

View file

@ -18,12 +18,18 @@
[overlayType]="overlayType"
(closeDialogEmitter)="onCloseOverlay($event)"
></app-task-edit-overlay>
}@if (overlayType === "dialog") {
} @if (overlayType === "dialog") {
<app-dialog-overlay
[overlayData]="overlayData"
[overlayType]="overlayType"
(closeDialogEmitter)="onCloseOverlay($event)"
></app-dialog-overlay>
} @if (overlayType === "contactOverlay") {
<app-contact-overlay
[overlayData]="overlayData"
[overlayType]="overlayType"
(closeDialogEmitter)="onCloseOverlay($event)"
></app-contact-overlay>
}
</div>
</div>

View file

@ -5,6 +5,7 @@ import { TaskOverlayComponent } from './task-overlay/task-overlay.component';
import { TaskEditOverlayComponent } from './task-edit-overlay/task-edit-overlay.component';
import { Router } from '@angular/router';
import { DialogOverlayComponent } from './dialog-overlay/dialog-overlay.component';
import { ContactOverlayComponent } from './contact-overlay/contact-overlay.component';
@Component({
selector: 'app-overlay',
@ -14,6 +15,7 @@ import { DialogOverlayComponent } from './dialog-overlay/dialog-overlay.componen
TaskOverlayComponent,
TaskEditOverlayComponent,
DialogOverlayComponent,
ContactOverlayComponent,
],
templateUrl: './overlay.component.html',
styleUrl: './overlay.component.scss',