added pw reset
This commit is contained in:
parent
7464e8e265
commit
d2e5d7bde4
10 changed files with 284 additions and 16 deletions
|
|
@ -1,5 +1,10 @@
|
||||||
import { Component } from '@angular/core';
|
import { Component } from '@angular/core';
|
||||||
import { Router, RouterOutlet } from '@angular/router';
|
import {
|
||||||
|
ActivatedRoute,
|
||||||
|
NavigationEnd,
|
||||||
|
Router,
|
||||||
|
RouterOutlet,
|
||||||
|
} from '@angular/router';
|
||||||
import { HeaderComponent } from './shared/components/header/header.component';
|
import { HeaderComponent } from './shared/components/header/header.component';
|
||||||
import { SidebarComponent } from './shared/components/sidebar/sidebar.component';
|
import { SidebarComponent } from './shared/components/sidebar/sidebar.component';
|
||||||
import { LanguageService } from './services/language.service';
|
import { LanguageService } from './services/language.service';
|
||||||
|
|
@ -10,6 +15,7 @@ import { SharedService } from './services/shared.service';
|
||||||
import { ContactDeleteComponent } from './components/contacts/contact-delete/contact-delete.component';
|
import { ContactDeleteComponent } from './components/contacts/contact-delete/contact-delete.component';
|
||||||
import { OverlayComponent } from './shared/components/overlay/overlay.component';
|
import { OverlayComponent } from './shared/components/overlay/overlay.component';
|
||||||
import { FirebaseService } from './services/firebase.service';
|
import { FirebaseService } from './services/firebase.service';
|
||||||
|
import { filter } from 'rxjs';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-root',
|
selector: 'app-root',
|
||||||
|
|
@ -35,6 +41,7 @@ export class AppComponent {
|
||||||
public langService: LanguageService,
|
public langService: LanguageService,
|
||||||
public sharedService: SharedService,
|
public sharedService: SharedService,
|
||||||
private firebaseService: FirebaseService,
|
private firebaseService: FirebaseService,
|
||||||
|
private route: ActivatedRoute,
|
||||||
private router: Router
|
private router: Router
|
||||||
) {
|
) {
|
||||||
this.isLoggedIn = this.firebaseService.getCurrentUserId();
|
this.isLoggedIn = this.firebaseService.getCurrentUserId();
|
||||||
|
|
@ -42,9 +49,23 @@ export class AppComponent {
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
if (this.isLoggedIn === undefined) {
|
if (this.isLoggedIn === undefined) {
|
||||||
this.router.navigate(['/login']);
|
this.checkPwResetRoute();
|
||||||
} else {
|
} else {
|
||||||
this.router.navigate(['/summary']);
|
this.router.navigate(['/summary']);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
checkPwResetRoute() {
|
||||||
|
this.router.events
|
||||||
|
.pipe(filter((event) => event instanceof NavigationEnd))
|
||||||
|
.subscribe(() => {
|
||||||
|
const urlTree = this.router.parseUrl(this.router.url);
|
||||||
|
|
||||||
|
if (
|
||||||
|
urlTree.root.children['primary']?.segments[0]?.path !== 'pw-reset'
|
||||||
|
) {
|
||||||
|
this.router.navigate(['/login']);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ import { TaskEditOverlayComponent } from './shared/components/overlay/task-edit-
|
||||||
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';
|
import { ForgotPwComponent } from './components/login/forgot-pw/forgot-pw.component';
|
||||||
|
import { PwResetComponent } from './components/login/forgot-pw/pw-reset/pw-reset.component';
|
||||||
|
|
||||||
export const routes: Routes = [
|
export const routes: Routes = [
|
||||||
{ path: '', component: SummaryComponent },
|
{ path: '', component: SummaryComponent },
|
||||||
|
|
@ -19,6 +20,7 @@ export const routes: Routes = [
|
||||||
{ 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: 'forgot-pw', component: ForgotPwComponent },
|
||||||
|
{ path: 'pw-reset', component: PwResetComponent },
|
||||||
{ 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 },
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,9 @@
|
||||||
onsubmit="return false"
|
onsubmit="return false"
|
||||||
>
|
>
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<p>{{ "login.login" | translate }}</p>
|
<div class="header">
|
||||||
|
<div class="headline">{{ "forgotPW.forgot" | translate }}</div>
|
||||||
|
</div>
|
||||||
<div class="line">
|
<div class="line">
|
||||||
<img src="./../../../assets/img/login/blue-line.svg" alt="" />
|
<img src="./../../../assets/img/login/blue-line.svg" alt="" />
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -17,7 +19,7 @@
|
||||||
id="password"
|
id="password"
|
||||||
name="password"
|
name="password"
|
||||||
#password="ngModel"
|
#password="ngModel"
|
||||||
[type]="loginSerivce.passwordFieldType"
|
[type]="loginService.passwordFieldType"
|
||||||
placeholder="{{ 'register.password' | translate }}"
|
placeholder="{{ 'register.password' | translate }}"
|
||||||
class="custom-input"
|
class="custom-input"
|
||||||
autocomplete="new-password"
|
autocomplete="new-password"
|
||||||
|
|
@ -33,8 +35,8 @@
|
||||||
} @else {
|
} @else {
|
||||||
<img
|
<img
|
||||||
class="passwordEye"
|
class="passwordEye"
|
||||||
(click)="loginSerivce.togglePasswordVisibility()"
|
(click)="loginService.togglePasswordVisibility()"
|
||||||
[src]="loginSerivce.passwordIcon"
|
[src]="loginService.passwordIcon"
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
<div class="error-msg">
|
<div class="error-msg">
|
||||||
|
|
@ -49,7 +51,7 @@
|
||||||
id="passwordConfirm"
|
id="passwordConfirm"
|
||||||
name="passwordConfirm"
|
name="passwordConfirm"
|
||||||
#passwordConfirm="ngModel"
|
#passwordConfirm="ngModel"
|
||||||
[type]="loginSerivce.passwordFieldType"
|
[type]="loginService.passwordFieldType"
|
||||||
placeholder="{{ 'register.passwordConfirm' | translate }}"
|
placeholder="{{ 'register.passwordConfirm' | translate }}"
|
||||||
class="custom-input"
|
class="custom-input"
|
||||||
autocomplete="new-password"
|
autocomplete="new-password"
|
||||||
|
|
@ -65,8 +67,8 @@
|
||||||
} @else {
|
} @else {
|
||||||
<img
|
<img
|
||||||
class="passwordEyeConfirm"
|
class="passwordEyeConfirm"
|
||||||
(click)="loginSerivce.togglePasswordVisibility()"
|
(click)="loginService.togglePasswordVisibility()"
|
||||||
[src]="loginSerivce.passwordIcon"
|
[src]="loginService.passwordIcon"
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
<div class="error-msg">
|
<div class="error-msg">
|
||||||
|
|
@ -82,10 +84,12 @@
|
||||||
<app-form-btn
|
<app-form-btn
|
||||||
[class]="'btn-login'"
|
[class]="'btn-login'"
|
||||||
[type]="'submit'"
|
[type]="'submit'"
|
||||||
[value]="'register.signup' | translate"
|
[value]="'forgotPW.pwChange' | translate"
|
||||||
[disabled]="
|
[disabled]="
|
||||||
password.invalid ||
|
password.invalid ||
|
||||||
!pwResetData.password ||
|
!pwResetData.password ||
|
||||||
|
passwordConfirm.invalid ||
|
||||||
|
!pwResetData.passwordConfirm ||
|
||||||
sharedService.isBtnDisabled ||
|
sharedService.isBtnDisabled ||
|
||||||
pwResetData.password.length < 6 ||
|
pwResetData.password.length < 6 ||
|
||||||
pwResetData.password !== pwResetData.passwordConfirm
|
pwResetData.password !== pwResetData.passwordConfirm
|
||||||
|
|
@ -96,4 +100,3 @@
|
||||||
</form>
|
</form>
|
||||||
<app-footer></app-footer>
|
<app-footer></app-footer>
|
||||||
</section>
|
</section>
|
||||||
<app-loading-dialog></app-loading-dialog>
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,212 @@
|
||||||
|
section {
|
||||||
|
width: 100vw;
|
||||||
|
height: 100vh;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
position: fixed;
|
||||||
|
top: 50%;
|
||||||
|
right: 50%;
|
||||||
|
transform: translate(50%, -50%);
|
||||||
|
width: 482px;
|
||||||
|
height: fit-content;
|
||||||
|
background: var(--white);
|
||||||
|
box-shadow: 0px 0px 12px 3px rgba(0, 0, 0, 0.05);
|
||||||
|
border-radius: 30px;
|
||||||
|
padding: 48px 64px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
width: 100%;
|
||||||
|
.headline {
|
||||||
|
text-align: center;
|
||||||
|
font-size: 61px;
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.line {
|
||||||
|
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: 15px;
|
||||||
|
}
|
||||||
|
&:nth-child(5) {
|
||||||
|
position: absolute;
|
||||||
|
right: 0;
|
||||||
|
top: 102px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.passwordEye {
|
||||||
|
position: absolute;
|
||||||
|
right: -5px;
|
||||||
|
top: 15px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.passwordEyeConfirm {
|
||||||
|
position: absolute;
|
||||||
|
right: -5px;
|
||||||
|
top: 102px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*------------- RESPONSIVE -------------*/
|
||||||
|
|
||||||
|
@media (max-height: 800px) {
|
||||||
|
.content {
|
||||||
|
top: 45%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 650px) {
|
||||||
|
.content {
|
||||||
|
width: 352px;
|
||||||
|
height: fit-content;
|
||||||
|
padding: 24px 36px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header {
|
||||||
|
.headline {
|
||||||
|
font-size: 47px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.line {
|
||||||
|
img {
|
||||||
|
width: 125px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 450px) {
|
||||||
|
.content {
|
||||||
|
width: calc(100vw - 96px);
|
||||||
|
padding: 24px 36px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header {
|
||||||
|
.headline {
|
||||||
|
font-size: 36px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.line {
|
||||||
|
img {
|
||||||
|
width: 112px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 380px) {
|
||||||
|
.content {
|
||||||
|
width: calc(100vw - 72px);
|
||||||
|
padding: 12px 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header {
|
||||||
|
.headline {
|
||||||
|
font-size: 32px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.line {
|
||||||
|
img {
|
||||||
|
width: 100px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-fields {
|
||||||
|
.custom-input {
|
||||||
|
font-size: 16px;
|
||||||
|
padding: 12px;
|
||||||
|
}
|
||||||
|
.custom-img {
|
||||||
|
&:nth-child(2) {
|
||||||
|
top: 15px;
|
||||||
|
}
|
||||||
|
&:nth-child(5) {
|
||||||
|
top: 90px;
|
||||||
|
}
|
||||||
|
&:nth-child(8) {
|
||||||
|
top: 162px;
|
||||||
|
}
|
||||||
|
&:nth-child(11) {
|
||||||
|
top: 237px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.passwordEye {
|
||||||
|
top: 162px;
|
||||||
|
}
|
||||||
|
.passwordEyeConfirm {
|
||||||
|
top: 237px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.error-msg {
|
||||||
|
height: 18px;
|
||||||
|
p {
|
||||||
|
font-size: 10px !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.privacy-policy {
|
||||||
|
.label {
|
||||||
|
p {
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -8,8 +8,9 @@ import { TranslateModule } from '@ngx-translate/core';
|
||||||
import { LoadingDialogComponent } from '../../loading-dialog/loading-dialog.component';
|
import { LoadingDialogComponent } from '../../loading-dialog/loading-dialog.component';
|
||||||
import { FirebaseService } from '../../../../services/firebase.service';
|
import { FirebaseService } from '../../../../services/firebase.service';
|
||||||
import { LoginService } from '../../../../services/login.service';
|
import { LoginService } from '../../../../services/login.service';
|
||||||
import { Router } from '@angular/router';
|
import { ActivatedRoute, Router } from '@angular/router';
|
||||||
import { SharedService } from '../../../../services/shared.service';
|
import { SharedService } from '../../../../services/shared.service';
|
||||||
|
import { Subscription } from 'rxjs';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-pw-reset',
|
selector: 'app-pw-reset',
|
||||||
|
|
@ -27,6 +28,9 @@ import { SharedService } from '../../../../services/shared.service';
|
||||||
styleUrl: './pw-reset.component.scss',
|
styleUrl: './pw-reset.component.scss',
|
||||||
})
|
})
|
||||||
export class PwResetComponent {
|
export class PwResetComponent {
|
||||||
|
oobCode: string = '';
|
||||||
|
private queryParamsSubscription: Subscription = new Subscription();
|
||||||
|
|
||||||
pwResetData = {
|
pwResetData = {
|
||||||
password: '',
|
password: '',
|
||||||
passwordConfirm: '',
|
passwordConfirm: '',
|
||||||
|
|
@ -34,15 +38,24 @@ export class PwResetComponent {
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private firebaseService: FirebaseService,
|
private firebaseService: FirebaseService,
|
||||||
public loginSerivce: LoginService,
|
public loginService: LoginService,
|
||||||
public sharedService: SharedService,
|
public sharedService: SharedService,
|
||||||
|
private route: ActivatedRoute,
|
||||||
private router: Router
|
private router: Router
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
|
ngOnInit(): void {
|
||||||
|
this.queryParamsSubscription = this.route.queryParams.subscribe(
|
||||||
|
(params) => {
|
||||||
|
this.oobCode = params['oobCode'];
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
onSubmit(ngForm: NgForm) {
|
onSubmit(ngForm: NgForm) {
|
||||||
this.sharedService.isBtnDisabled = true;
|
this.sharedService.isBtnDisabled = true;
|
||||||
if (ngForm.submitted && ngForm.form.valid) {
|
if (ngForm.submitted && ngForm.form.valid) {
|
||||||
// this.loginSerivce.login(this.pwResetData);
|
this.loginService.newPassword(this.pwResetData.password, this.oobCode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -59,6 +59,7 @@ section {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: -5px;
|
right: -5px;
|
||||||
top: 88px;
|
top: 88px;
|
||||||
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
.custom-input:focus + .custom-img {
|
.custom-input:focus + .custom-img {
|
||||||
display: none;
|
display: none;
|
||||||
|
|
|
||||||
|
|
@ -84,11 +84,13 @@ section {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: -5px;
|
right: -5px;
|
||||||
top: 186px;
|
top: 186px;
|
||||||
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
.passwordEyeConfirm {
|
.passwordEyeConfirm {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: -5px;
|
right: -5px;
|
||||||
top: 272px;
|
top: 272px;
|
||||||
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
.custom-input:focus + .custom-img {
|
.custom-input:focus + .custom-img {
|
||||||
display: none;
|
display: none;
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ import {
|
||||||
GoogleAuthProvider,
|
GoogleAuthProvider,
|
||||||
createUserWithEmailAndPassword,
|
createUserWithEmailAndPassword,
|
||||||
sendPasswordResetEmail,
|
sendPasswordResetEmail,
|
||||||
|
confirmPasswordReset,
|
||||||
} from 'firebase/auth';
|
} from 'firebase/auth';
|
||||||
import { FirebaseService } from './firebase.service';
|
import { FirebaseService } from './firebase.service';
|
||||||
import {
|
import {
|
||||||
|
|
@ -208,8 +209,6 @@ export class LoginService {
|
||||||
// FORGOT PASSWORD
|
// FORGOT PASSWORD
|
||||||
|
|
||||||
passwordReset(email: string) {
|
passwordReset(email: string) {
|
||||||
console.log(email);
|
|
||||||
|
|
||||||
const auth = getAuth();
|
const auth = getAuth();
|
||||||
sendPasswordResetEmail(auth, email)
|
sendPasswordResetEmail(auth, email)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
|
|
@ -222,4 +221,17 @@ export class LoginService {
|
||||||
this.sharedService.isBtnDisabled = false;
|
this.sharedService.isBtnDisabled = false;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
newPassword(newPW: string, oobCode: string) {
|
||||||
|
const auth = getAuth();
|
||||||
|
confirmPasswordReset(auth, oobCode, newPW)
|
||||||
|
.then(() => {
|
||||||
|
this.router.navigate(['/login']);
|
||||||
|
this.sharedService.isBtnDisabled = false;
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.error('Fehler beim Zurücksetzen des Passworts:', error);
|
||||||
|
this.sharedService.isBtnDisabled = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@
|
||||||
"forgot": "Passwort zurücksetzen",
|
"forgot": "Passwort zurücksetzen",
|
||||||
"email": "Ihre E-Mail",
|
"email": "Ihre E-Mail",
|
||||||
"sendMail": "E-Mail senden",
|
"sendMail": "E-Mail senden",
|
||||||
|
"pwChange": "Passwort ändern",
|
||||||
"notice": "Wir senden Ihnen eine E-Mail, über die Sie Ihr Passwort ändern können"
|
"notice": "Wir senden Ihnen eine E-Mail, über die Sie Ihr Passwort ändern können"
|
||||||
},
|
},
|
||||||
"register": {
|
"register": {
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@
|
||||||
"forgot": "Reset Password",
|
"forgot": "Reset Password",
|
||||||
"email": "Your Email",
|
"email": "Your Email",
|
||||||
"sendMail": "Send Mail",
|
"sendMail": "Send Mail",
|
||||||
|
"pwChange": "Change Password",
|
||||||
"notice": "We will send you an email to change your password."
|
"notice": "We will send you an email to change your password."
|
||||||
},
|
},
|
||||||
"register": {
|
"register": {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue