added forgot pw component

This commit is contained in:
Chneemann 2024-05-20 13:46:48 +02:00
parent 8e48a3b3a3
commit a23f81a47f
14 changed files with 573 additions and 3 deletions

View file

@ -10,6 +10,7 @@ import { TaskOverlayComponent } from './shared/components/overlay/task-overlay/t
import { TaskEditOverlayComponent } from './shared/components/overlay/task-edit-overlay/task-edit-overlay.component'; import { TaskEditOverlayComponent } from './shared/components/overlay/task-edit-overlay/task-edit-overlay.component';
import { LoginComponent } from './components/login/login.component'; import { LoginComponent } from './components/login/login.component';
import { RegisterComponent } from './components/login/register/register.component'; import { RegisterComponent } from './components/login/register/register.component';
import { ForgotPwComponent } from './components/login/forgot-pw/forgot-pw.component';
export const routes: Routes = [ export const routes: Routes = [
{ path: '', component: SummaryComponent }, { path: '', component: SummaryComponent },
@ -17,6 +18,7 @@ export const routes: Routes = [
{ path: 'login/imprint', component: ImprintComponent }, { path: 'login/imprint', component: ImprintComponent },
{ path: 'login/privacy-policy', component: PrivacyPolicyComponent }, { path: 'login/privacy-policy', component: PrivacyPolicyComponent },
{ path: 'register', component: RegisterComponent }, { path: 'register', component: RegisterComponent },
{ path: 'forgot-pw', component: ForgotPwComponent },
{ path: 'summary', component: SummaryComponent }, { path: 'summary', component: SummaryComponent },
{ path: 'add-task', component: AddTaskComponent }, { path: 'add-task', component: AddTaskComponent },
{ path: 'add-task/:id', component: AddTaskComponent }, { path: 'add-task/:id', component: AddTaskComponent },

View file

@ -0,0 +1,63 @@
<section>
<app-header [signUpBtn]="true"></app-header>
<form
id="form"
#taskForm="ngForm"
(ngSubmit)="onSubmit(taskForm)"
onsubmit="return false"
>
<div class="content">
<div class="headline">{{ "forgotPW.forgot" | translate }}</div>
<div class="line">
<img src="./../../../assets/img/login/blue-line.svg" alt="" />
</div>
<div class="input-fields">
<input
type="mail"
id="mail"
name="mail"
#mail="ngModel"
placeholder="{{ 'login.email' | translate }}"
class="custom-input"
autocomplete="email"
[(ngModel)]="pwResetData.mail"
required
/>
@if(!pwResetData.mail) {
<img
class="custom-img"
src="./../../../assets/img/login/mail.svg"
alt=""
/>
} @else {
<img class="custom-img" alt="" />
}
<div class="error-msg">
@if (!mail.valid && mail.touched) {
<p>{{ "forgotPW.errorMail0" | translate }}</p>
} @if (loginSerivce.errorCode == 'auth/invalid-email') {
<p>{{ "forgotPW.errorMail1" | translate }}</p>
}
</div>
</div>
<div class="notice">
<p>{{ "forgotPW.notice" | translate }}</p>
</div>
<div class="form-buttons">
<app-form-btn
[class]="'btn-login'"
[type]="'submit'"
[value]="'forgotPW.sendMail' | translate"
[disabled]="
mail.invalid ||
!pwResetData.mail ||
sharedService.isBtnDisabled ||
!checkIfUserEmailIsValid(pwResetData.mail)
"
></app-form-btn>
</div>
</div>
</form>
<app-footer></app-footer>
</section>
<app-loading-dialog></app-loading-dialog>

View file

@ -0,0 +1,219 @@
section {
width: 100vw;
height: 100vh;
}
.content {
display: flex;
flex-direction: column;
align-items: center;
position: fixed;
top: 50%;
right: 50%;
transform: translate(50%, -50%);
width: 722px;
height: fit-content;
background: var(--white);
box-shadow: 0px 0px 12px 3px rgba(0, 0, 0, 0.05);
border-radius: 30px;
padding: 48px 64px;
.headline {
text-align: center;
font-size: 61px;
font-weight: 700;
}
img {
padding: 12px 0 24px 0;
}
}
.input-fields {
display: flex;
flex-direction: column;
align-items: center;
position: relative;
width: 90%;
.custom-input::-webkit-contacts-auto-fill-button {
visibility: hidden;
}
.custom-input {
font-size: 20px;
font-weight: 400;
width: 100%;
border-radius: 10px;
border: 1px solid var(--light-gray);
padding: 12px 16px;
}
.custom-img {
&:nth-child(2) {
position: absolute;
right: 0;
top: 5px;
}
&:nth-child(5) {
position: absolute;
right: 0;
top: 88px;
}
}
.passwordEye {
position: absolute;
right: -5px;
top: 88px;
}
.custom-input:focus + .custom-img {
display: none;
}
}
.error-msg {
display: flex;
align-items: center;
justify-content: center;
height: 24px;
padding: 6px;
width: 120%;
p {
color: var(--red);
font-size: 12px !important;
font-weight: 400 !important;
}
}
.form-buttons {
display: flex;
justify-content: end;
padding: 12px 0;
}
.notice {
text-align: center;
padding: 12px;
p {
color: var(--gray);
font-size: 21px;
font-weight: 400;
}
}
/*------------- RESPONSIVE -------------*/
@media (max-height: 800px) {
.content {
top: 40%;
}
}
@media screen and (max-width: 850px) {
.content {
width: 552px;
height: fit-content;
padding: 24px 36px;
.headline {
font-size: 47px;
}
.line {
img {
width: 120px;
}
}
}
}
@media screen and (max-width: 650px) {
.content {
width: 352px;
height: fit-content;
padding: 24px 36px;
.headline {
font-size: 36px;
}
.line {
img {
width: 100px;
}
}
}
.notice {
p {
font-size: 18px;
}
}
}
@media screen and (max-width: 450px) {
.content {
width: calc(100vw - 96px);
padding: 24px 36px;
.headline {
font-size: 36px;
}
.line {
img {
width: 100px;
}
}
}
.loading-text {
margin-top: 180px;
p {
font-size: 18px;
font-weight: 400px;
}
}
.error-msg {
height: 21px;
p {
font-size: 11px !important;
}
}
}
@media screen and (max-width: 360px) {
.content {
width: calc(100vw - 72px);
padding: 12px 24px;
.headline {
font-size: 32px;
}
.line {
img {
width: 80px;
}
}
}
.input-fields {
.custom-input {
font-size: 16px;
padding: 12px;
}
.custom-img {
&:nth-child(2) {
top: 2px;
}
&:nth-child(5) {
top: 73px;
}
}
.passwordEye {
top: 76px;
}
}
.error-msg {
height: 18px;
p {
font-size: 10px !important;
}
}
.notice {
p {
font-size: 16px;
}
}
}

View file

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

View file

@ -0,0 +1,57 @@
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 { FooterComponent } from '../footer/footer.component';
import { HeaderComponent } from '../header/header.component';
import { TranslateModule } from '@ngx-translate/core';
import { LoadingDialogComponent } from '../loading-dialog/loading-dialog.component';
import { FirebaseService } from '../../../services/firebase.service';
import { LoginService } from '../../../services/login.service';
import { SharedService } from '../../../services/shared.service';
import { Router } from '@angular/router';
@Component({
selector: 'app-forgot-pw',
standalone: true,
imports: [
FormsModule,
CommonModule,
FormBtnComponent,
FooterComponent,
HeaderComponent,
TranslateModule,
LoadingDialogComponent,
],
templateUrl: './forgot-pw.component.html',
styleUrl: './forgot-pw.component.scss',
})
export class ForgotPwComponent {
pwResetData = {
mail: '',
};
constructor(
private firebaseService: FirebaseService,
public loginSerivce: LoginService,
public sharedService: SharedService,
private router: Router
) {}
onSubmit(ngForm: NgForm) {
this.sharedService.isBtnDisabled = true;
if (ngForm.submitted && ngForm.form.valid) {
// this.loginSerivce.login(this.pwResetData);
}
}
checkIfUserEmailIsValid(emailValue: string) {
const channelNameLenght = emailValue.length;
const emailRegex = /^[\w.%+-]+@[\w.-]+\.[a-zA-Z]{2,}$/;
if (emailRegex.test(emailValue)) {
return true;
} else {
return false;
}
}
}

View file

@ -0,0 +1,99 @@
<section>
<app-header [signUpBtn]="true"></app-header>
<form
id="form"
#taskForm="ngForm"
(ngSubmit)="onSubmit(taskForm)"
onsubmit="return false"
>
<div class="content">
<p>{{ "login.login" | translate }}</p>
<div class="line">
<img src="./../../../assets/img/login/blue-line.svg" alt="" />
</div>
<div class="input-fields">
<input
type="password"
id="password"
name="password"
#password="ngModel"
[type]="loginSerivce.passwordFieldType"
placeholder="{{ 'register.password' | translate }}"
class="custom-input"
autocomplete="new-password"
[(ngModel)]="pwResetData.password"
required
/>
@if(!pwResetData.password) {
<img
class="custom-img"
src="./../../../assets/img/login/lock.svg"
alt=""
/>
} @else {
<img
class="passwordEye"
(click)="loginSerivce.togglePasswordVisibility()"
[src]="loginSerivce.passwordIcon"
/>
}
<div class="error-msg">
@if (!password.valid && password.touched) {
<p>{{ "register.errorPassword0" | translate }}</p>
} @else { @if (pwResetData.password.length < 6 && password.touched) {
<p>{{ "register.errorPassword1" | translate }}</p>
} }
</div>
<input
type="passwordConfirm"
id="passwordConfirm"
name="passwordConfirm"
#passwordConfirm="ngModel"
[type]="loginSerivce.passwordFieldType"
placeholder="{{ 'register.passwordConfirm' | translate }}"
class="custom-input"
autocomplete="new-password"
[(ngModel)]="pwResetData.passwordConfirm"
required
/>
@if(!pwResetData.passwordConfirm) {
<img
class="custom-img"
src="./../../../assets/img/login/lock.svg"
alt=""
/>
} @else {
<img
class="passwordEyeConfirm"
(click)="loginSerivce.togglePasswordVisibility()"
[src]="loginSerivce.passwordIcon"
/>
}
<div class="error-msg">
@if (!passwordConfirm.valid && passwordConfirm.touched) {
<p>{{ "register.errorPassword0" | translate }}</p>
} @if (pwResetData.password !== pwResetData.passwordConfirm &&
pwResetData.password !== "" && pwResetData.passwordConfirm !== "") {
<p>{{ "register.errorPassword2" | translate }}</p>
}
</div>
</div>
<div class="form-buttons">
<app-form-btn
[class]="'btn-login'"
[type]="'submit'"
[value]="'register.signup' | translate"
[disabled]="
password.invalid ||
!pwResetData.password ||
sharedService.isBtnDisabled ||
pwResetData.password.length < 6 ||
pwResetData.password !== pwResetData.passwordConfirm
"
></app-form-btn>
</div>
</div>
</form>
<app-footer></app-footer>
</section>
<app-loading-dialog></app-loading-dialog>

View file

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

View file

@ -0,0 +1,48 @@
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 { FooterComponent } from '../../footer/footer.component';
import { HeaderComponent } from '../../header/header.component';
import { TranslateModule } from '@ngx-translate/core';
import { LoadingDialogComponent } from '../../loading-dialog/loading-dialog.component';
import { FirebaseService } from '../../../../services/firebase.service';
import { LoginService } from '../../../../services/login.service';
import { Router } from '@angular/router';
import { SharedService } from '../../../../services/shared.service';
@Component({
selector: 'app-pw-reset',
standalone: true,
imports: [
FormsModule,
CommonModule,
FormBtnComponent,
FooterComponent,
HeaderComponent,
TranslateModule,
LoadingDialogComponent,
],
templateUrl: './pw-reset.component.html',
styleUrl: './pw-reset.component.scss',
})
export class PwResetComponent {
pwResetData = {
password: '',
passwordConfirm: '',
};
constructor(
private firebaseService: FirebaseService,
public loginSerivce: LoginService,
public sharedService: SharedService,
private router: Router
) {}
onSubmit(ngForm: NgForm) {
this.sharedService.isBtnDisabled = true;
if (ngForm.submitted && ngForm.form.valid) {
// this.loginSerivce.login(this.pwResetData);
}
}
}

View file

@ -72,6 +72,9 @@
<p>{{ "login.errorPassword1" | translate }}</p> <p>{{ "login.errorPassword1" | translate }}</p>
} }
</div> </div>
<div class="forgot-pw">
<a routerLink="/forgot-pw">Passwort vergessen?</a>
</div>
</div> </div>
<div class="google-button"> <div class="google-button">
<app-form-btn <app-form-btn

View file

@ -3,8 +3,6 @@ section {
height: 100vh; height: 100vh;
} }
// LOGIN
.content { .content {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
@ -87,6 +85,24 @@ section {
padding: 12px 0; padding: 12px 0;
} }
.forgot-pw {
padding-bottom: 24px;
a {
text-align: center;
font-size: 16px;
font-weight: 400;
color: var(--gray);
cursor: pointer;
width: fit-content;
text-decoration: none;
cursor: pointer;
&:hover {
color: var(--light-blue);
font-weight: 600;
}
}
}
/*------------- RESPONSIVE -------------*/ /*------------- RESPONSIVE -------------*/
@media (max-height: 800px) { @media (max-height: 800px) {

View file

@ -3,7 +3,7 @@ import { Component } from '@angular/core';
import { FormsModule, NgForm } from '@angular/forms'; import { FormsModule, NgForm } from '@angular/forms';
import { FormBtnComponent } from '../../shared/components/buttons/form-btn/form-btn.component'; import { FormBtnComponent } from '../../shared/components/buttons/form-btn/form-btn.component';
import { FirebaseService } from '../../services/firebase.service'; import { FirebaseService } from '../../services/firebase.service';
import { Router } from '@angular/router'; import { Router, RouterLink } from '@angular/router';
import { LoginService } from '../../services/login.service'; import { LoginService } from '../../services/login.service';
import { SharedService } from '../../services/shared.service'; import { SharedService } from '../../services/shared.service';
import { FooterComponent } from './footer/footer.component'; import { FooterComponent } from './footer/footer.component';
@ -22,6 +22,7 @@ import { LoadingDialogComponent } from './loading-dialog/loading-dialog.componen
HeaderComponent, HeaderComponent,
TranslateModule, TranslateModule,
LoadingDialogComponent, LoadingDialogComponent,
RouterLink,
], ],
templateUrl: './login.component.html', templateUrl: './login.component.html',
styleUrl: './login.component.scss', styleUrl: './login.component.scss',

View file

@ -12,6 +12,14 @@
"loginDialog0": "Einloggen", "loginDialog0": "Einloggen",
"loginDialog1": "Bitte warten..." "loginDialog1": "Bitte warten..."
}, },
"forgotPW": {
"forgot": "Passwort zurücksetzen",
"email": "Ihre E-Mail",
"sendMail": "E-Mail senden",
"errorMail0": "Sie müssen eine E-Mail Adresse eingeben!",
"errorMail1": "Diese E-Mail Adresse existiert nicht!",
"notice": "Wir senden Ihnen eine E-Mail, über die Sie Ihr Passwort ändern können"
},
"register": { "register": {
"signup": "Registrieren", "signup": "Registrieren",
"name": "Name", "name": "Name",

View file

@ -12,6 +12,14 @@
"loginDialog0": "Logging in", "loginDialog0": "Logging in",
"loginDialog1": "Please wait..." "loginDialog1": "Please wait..."
}, },
"forgotPW": {
"forgot": "Reset Password",
"email": "Your Email",
"sendMail": "Send Mail",
"errorMail0": "You must enter a mail!",
"errorMail1": "This email address does not exist!",
"notice": "We will send you an email to change your password."
},
"register": { "register": {
"signup": "Sign up", "signup": "Sign up",
"name": "Name", "name": "Name",