Commit a53574df by Muhammad Usman

Auth Screens:

	- Login
	- Register
	- Forgot Password
	- Reset Password
	- Welcome
parent 1b1ebd13
......@@ -20,6 +20,7 @@
"prefix": "app",
"styles": [
"styles.scss",
"../node_modules/font-awesome/css/font-awesome.min.css",
"assets/css/custom.scss"
],
"scripts": [
......
......@@ -175,6 +175,11 @@ export const routes: Routes = [
component: ViewCareerUserComponent
}
]
},
{
path: 'my-career-web',
// @ts-ignore
loadChildren: "./components/my-career-web/my-career-web.module#MyCareerWebModule"
}
];
......
import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core';
import { McSharedModule } from '../mc-shared/mc-shared.module';
import { AuthRouting } from './auth.routing';
import { ForgotPasswordComponent } from './forgot-password/forgot-password.component';
import { LoginComponent } from './login/login.component';
import { RegisterComponent } from './register/register.component';
import { ResetPasswordComponent } from './reset-password/reset-password.component';
@NgModule({
imports: [
CommonModule,
McSharedModule,
AuthRouting
],
declarations: [
LoginComponent,
RegisterComponent,
ForgotPasswordComponent,
ResetPasswordComponent
]
})
export class AuthModule {
}
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { ForgotPasswordComponent } from './forgot-password/forgot-password.component';
import { LoginComponent } from './login/login.component';
import { RegisterComponent } from './register/register.component';
import { ResetPasswordComponent } from './reset-password/reset-password.component';
const routes: Routes = [
{path: 'login', component: LoginComponent},
{path: 'register', component: RegisterComponent},
{path: 'forgot-password', component: ForgotPasswordComponent},
{path: 'reset-password/:token', component: ResetPasswordComponent},
{path: '', redirectTo: 'login', pathMatch: 'full'}
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule]
})
export class AuthRouting { }
<div class="bck-link mc-nav-link" routerLink="/my-career-web/auth/login"><i class="fa fa-chevron-left"></i><span>Back</span></div>
<div class="row login-wrapper">
<div class="col-md-offset-4 col-md-4">
<div class="mc-login-logo d-flex justify-content-center">
<img src="/assets/my-career-web/images/MATCHD_LOGO.jpg" alt="">
</div>
<div class="title-goes-here">Title goes here</div>
<div class="subtitle-giving-cont">Subtitle giving context to product and selling users on why they should sign up goes here.</div>
<form class="login-form position-relative" #form="ngForm">
<div class="form-group" *ngIf="!emailSent">
<label>Email Address</label>
<app-form-control>
<input type="email" name="username" required class="form-control" [(ngModel)]="forgotForm.username">
</app-form-control>
</div>
<div class="d-flex justify-content-center" *ngIf="!emailSent">
<app-overlay [isActive]="isLoading"></app-overlay>
<button class="action-btn" (click)="forgot()" [disabled]="isLoading">Reset Password</button>
</div>
<div class="signup-link" *ngIf="!emailSent">
Back to <span class="mc-nav-link" routerLink="/my-career-web/auth/login">Sign in</span>
</div>
<div class="signup-link" *ngIf="emailSent">
You will receive an email if you have an account associated with this email address.
</div>
<div class="d-flex justify-content-center" *ngIf="emailSent">
<button class="action-btn" routerLink="/my-career-web/auth/login">Back to Login</button>
</div>
</form>
</div>
</div>
<span class="mc-footer-label">© {{year}} Matchd | Privacy Policy</span>
.bck-link {
position: absolute;
color: #12A8DE;
line-height: 21px;
z-index: 1000;
top: 15px;
left: 25px;
border: 0;
display: flex;
align-items: center;
span {
font-family: "Museo Sans Rounded", sans-serif;
font-size: 14px;
letter-spacing: 0;
padding-left: 10px;
}
.fa {
font-size: 18px;
}
}
.login-wrapper {
position: relative;
.mc-login-logo {
margin-top: 96px;
img {
height: 60px;
}
}
.title-goes-here {
color: #58595B;
font-family: 'Futura', sans-serif;
font-size: 24px;
font-weight: bold;
letter-spacing: 0;
line-height: 36px;
text-align: center;
margin: 32px 0 8px;
}
.subtitle-giving-cont {
color: #58595B;
font-family: "Museo Sans Rounded";
font-size: 18px;
letter-spacing: 0;
line-height: 27px;
text-align: center;
margin-bottom: 32px;
padding: 0 26px;
}
.action-btn {
height: 50px;
width: 260px;
border-radius: 73px;
background-color: #12A8DE;
padding: 15px;
text-align: center;
color: #fff;
margin: 24px auto 8px;
cursor: pointer;
transition: .3s;
font-weight: bold;
border: 0;
box-shadow: none;
&:hover {
background: #127BAD;
}
}
.login-form {
border-radius: 4px;
background-color: #FFFFFF;
box-shadow: 0 0 20px 0 rgba(128,130,133,0.13);
padding: 24px 26px;
.forgot-password {
font-family: "Museo Sans Rounded", sans-serif;
font-size: 14px;
letter-spacing: 0;
line-height: 21px;
text-align: center;
}
.signup-link {
color: #58595B;
font-family: "Museo Sans Rounded", sans-serif;
font-size: 14px;
letter-spacing: 0;
line-height: 21px;
text-align: center;
}
}
}
.mc-footer-label {
position: absolute;
bottom: 32px;
left: 43%;
color: #808285;
font-family: "Museo Sans Rounded", sans-serif;
font-size: 11px;
letter-spacing: 0;
line-height: 13px;
}
@media only screen and (max-width: 600px) {
.login-wrapper {
.mc-login-logo {
margin-top: 77px;
img {
height: 40px;
}
}
.subtitle-giving-cont {
margin-bottom: 0;
}
.login-form {
box-shadow: none;
.action-btn {
width: 100%;
}
}
}
.mc-footer-label {
left: 29%;
}
}
import { Component, ViewChild } from '@angular/core';
import { NgForm } from '@angular/forms';
import { takeUntil } from 'rxjs/operators';
import { BaseComponent } from '../../base/base.component';
import { AuthService } from '../../services/auth.service';
import { HelperService } from '../../services/helper.service';
import { ToasterService } from '../../services/toaster.service';
@Component({
selector: 'app-forgot-password',
templateUrl: './forgot-password.component.html',
styleUrls: ['./forgot-password.component.scss']
})
export class ForgotPasswordComponent extends BaseComponent {
year = new Date().getFullYear();
forgotForm = {
username: ''
};
emailSent = false;
@ViewChild('form') form: NgForm;
constructor(
private hs: HelperService,
private ts: ToasterService,
private as: AuthService
) {
super();
}
forgot(): void {
if (this.form.invalid) {
return this.hs.validateAllFormFields(this.form);
}
this.isLoading = true;
this.as.forgot(this.forgotForm)
.pipe(takeUntil(this.componentInView))
.subscribe(response => {
this.hs.oneItHttpResponse(response);
if (response.emailSent) {
this.emailSent = true;
this.ts.success('Please check your email for instructions.');
}
this.isLoading = false;
}, err => {
this.hs.handleHttpError(err);
this.isLoading = false;
});
}
}
<div class="row login-wrapper">
<div class="col-md-offset-4 col-md-4">
<div class="mc-login-logo d-flex justify-content-center">
<img src="/assets/my-career-web/images/MATCHD_LOGO.jpg" alt="">
</div>
<div class="title-goes-here">Title goes here</div>
<div class="subtitle-giving-cont">Subtitle giving context to product and selling users on why they should sign up goes here.</div>
<form class="login-form position-relative" #form="ngForm">
<div class="form-group">
<label>Email Address</label>
<app-form-control>
<input type="email" email name="username" required class="form-control" [(ngModel)]="loginForm.username">
</app-form-control>
</div>
<div class="form-group">
<label>Password</label>
<app-form-control>
<input type="password" name="password" required class="form-control" [(ngModel)]="loginForm.password">
</app-form-control>
</div>
<div class="text-center">
<span class="forgot-password mc-nav-link" routerLink="/my-career-web/auth/forgot-password">Forgot password?</span>
</div>
<div class="d-flex justify-content-center">
<app-overlay [isActive]="isLoading"></app-overlay>
<button class="action-btn" (click)="login()" [disabled]="isLoading">Sign in</button>
</div>
<div class="signup-link">
Don’t have an account? <span class="mc-nav-link" routerLink="/my-career-web/auth/register">Sign up free <i style="margin-left: 3px;" class="fa fa-chevron-right"></i></span>
</div>
<div class="d-flex justify-content-center">
<button class="action-btn google-login" [disabled]="isLoading">Sign in with Google</button>
</div>
<div class="d-flex justify-content-center">
<button class="action-btn linkedin-login" [disabled]="isLoading">Sign in with Linkedin</button>
</div>
</form>
</div>
<span class="mc-footer-label">© {{year}} Matchd | Privacy Policy</span>
</div>
.login-wrapper {
position: relative;
margin-bottom: 45px;
.mc-login-logo {
margin-top: 96px;
img {
height: 60px;
}
}
.title-goes-here {
color: #58595B;
font-family: 'Futura', sans-serif;
font-size: 24px;
font-weight: bold;
letter-spacing: 0;
line-height: 36px;
text-align: center;
margin: 32px 0 8px;
}
.subtitle-giving-cont {
color: #58595B;
font-family: "Museo Sans Rounded";
font-size: 18px;
letter-spacing: 0;
line-height: 27px;
text-align: center;
margin-bottom: 32px;
padding: 0 26px;
}
.action-btn {
height: 50px;
width: 260px;
border-radius: 73px;
background-color: #12A8DE;
padding: 15px;
text-align: center;
color: #fff;
margin: 24px auto 8px;
cursor: pointer;
transition: .3s;
font-weight: bold;
border: 0;
box-shadow: none;
&:hover {
background-color: #127BAD;
}
&.google-login {
background-color: #de5246;
&:hover {
background-color: #C34C41;
}
}
&.linkedin-login {
background-color: #0072b1;
margin: 0;
&:hover {
background-color: #005A8D;
}
}
}
.login-form {
border-radius: 4px;
background-color: #FFFFFF;
box-shadow: 0 0 20px 0 rgba(128,130,133,0.13);
padding: 24px 26px;
.forgot-password {
font-family: "Museo Sans Rounded", sans-serif;
font-size: 14px;
letter-spacing: 0;
line-height: 21px;
text-align: center;
}
.signup-link {
color: #58595B;
font-family: "Museo Sans Rounded", sans-serif;
font-size: 14px;
letter-spacing: 0;
line-height: 21px;
text-align: center;
}
}
}
.mc-footer-label {
position: absolute;
bottom: -10%;
left: 43%;
color: #808285;
font-family: "Museo Sans Rounded", sans-serif;
font-size: 11px;
letter-spacing: 0;
line-height: 13px;
}
@media only screen and (max-width: 600px) {
.login-wrapper {
.mc-login-logo {
margin-top: 77px;
img {
height: 40px;
}
}
.subtitle-giving-cont {
margin-bottom: 0;
}
.login-form {
box-shadow: none;
.action-btn {
width: 100%;
}
}
}
.mc-footer-label {
left: 29%;
bottom: -4%;
}
}
import { Component, ViewChild } from '@angular/core';
import { NgForm } from '@angular/forms';
import { Router } from '@angular/router';
import { takeUntil } from 'rxjs/operators';
import { BaseComponent } from '../../base/base.component';
import { AuthService } from '../../services/auth.service';
import { HelperService } from '../../services/helper.service';
@Component({
selector: 'app-login',
templateUrl: './login.component.html',
styleUrls: ['./login.component.scss']
})
export class LoginComponent extends BaseComponent {
year = new Date().getFullYear();
loginForm = {
username: '',
password: ''
};
@ViewChild('form') form: NgForm;
constructor(
private hs: HelperService,
private as: AuthService,
private r: Router
) {
super();
}
login(): void {
if (this.form.invalid) {
return this.hs.validateAllFormFields(this.form);
}
this.isLoading = true;
this.as.login(this.loginForm)
.pipe(takeUntil(this.componentInView))
.subscribe(response => {
this.isLoading = false;
this.hs.oneItHttpResponse(response);
if (response.status === 'error') {
this.loginForm.password = '';
return;
}
this.r.navigate(['/my-career-web/dashboard']);
}, err => {
this.hs.handleHttpError(err);
this.isLoading = false;
});
}
googleLogin(): void {
this.isLoading = true;
this.as.googleLogin()
.pipe(takeUntil(this.componentInView))
.subscribe(response => {
this.hs.oneItHttpResponse(response);
// if (response.status === 'error') {
// this.loginForm.password = '';
// }
this.isLoading = false;
}, err => {
this.hs.handleHttpError(err);
this.isLoading = false;
});
}
linkedInLogin(): void {
this.isLoading = true;
this.as.linkedinLogin()
.pipe(takeUntil(this.componentInView))
.subscribe(response => {
this.hs.oneItHttpResponse(response);
// if (response.status === 'error') {
// this.loginForm.password = '';
// }
this.isLoading = false;
}, err => {
this.hs.handleHttpError(err);
this.isLoading = false;
});
}
}
<div class="bck-link mc-nav-link" routerLink="/my-career-web/auth/login"><i class="fa fa-chevron-left"></i><span>Back</span></div>
<div class="row signup-wrapper">
<div class="col-md-offset-4 col-md-4">
<div class="mc-signup-logo d-flex justify-content-center">
<img src="/assets/my-career-web/images/MATCHD_LOGO.jpg" alt="">
</div>
<div class="title-goes-here">Title goes here</div>
<div class="subtitle-giving-cont">Subtitle giving context to product and selling users on why they should sign up goes here.</div>
<form class="signup-form position-relative" #form="ngForm">
<div class="form-group">
<label>Email Address</label>
<app-form-control>
<input type="email" email name="username" required class="form-control" [(ngModel)]="registerForm.username">
</app-form-control>
</div>
<div class="form-group" style="margin-bottom: 24px;">
<label>Choose a Password</label>
<app-form-control class="password-wrapper">
<input [type]="showPassword ? 'text' : 'password'" name="password" required class="form-control" [(ngModel)]="registerForm.password">
<i class="fa" [ngClass]="showPassword ? 'fa-eye' : 'fa-eye-slash'" (click)="showPassword = !showPassword"></i>
</app-form-control>
</div>
<div class="was-referred form-group">
<span>Were you referred by another member?</span>
<div class="mt-sm-top">
<p-radioButton label="Yes" [value]="true" name="was_referred" [(ngModel)]="registerForm.was_referred">
</p-radioButton>
<p-radioButton label="No" [value]="false" name="was_referred" [(ngModel)]="registerForm.was_referred" [ngStyle]="{'margin-left': '15px'}">
</p-radioButton>
</div>
</div>
<div class="form-group" *ngIf="registerForm.was_referred">
<label>Please enter that member’s referral code</label>
<app-form-control>
<input type="text" name="referral" [required]="registerForm.was_referred" class="form-control" [(ngModel)]="registerForm.ReferralCode">
</app-form-control>
</div>
<div>
<div class="d-flex">
<p-checkbox name="terms" [binary]="true" [(ngModel)]="registerForm.terms" [ngStyle]="{'marginRight': '8px'}"></p-checkbox>
<span style="cursor: pointer;" (click)="registerForm.terms = !registerForm.terms">I have read and agree to the <span class="mc-nav-link">Terms & Conditions</span></span>
</div>
<div class="d-flex" style="margin-top: 16px;">
<p-checkbox name="policy" [binary]="true" [(ngModel)]="registerForm.policy" [ngStyle]="{'marginRight': '8px'}"></p-checkbox>
<span style="cursor: pointer;" (click)="registerForm.policy = !registerForm.policy">I have read and agree to the <span class="mc-nav-link">Privacy Policy</span></span>
</div>
</div>
<div class="d-flex justify-content-center">
<app-overlay [isActive]="isLoading"></app-overlay>
<button class="action-btn" (click)="register()" [disabled]="isLoading && !registerForm.terms || !registerForm.policy">Sign up</button>
</div>
<div class="signup-link">
Already have an account? <span class="mc-nav-link" routerLink="/my-career-web/auth/login">Sign in <i style="margin-left: 3px;" class="fa fa-chevron-right"></i></span>
</div>
</form>
</div>
<span class="mc-footer-label">© {{year}} Matchd | Privacy Policy</span>
</div>
.bck-link {
position: absolute;
color: #12A8DE;
line-height: 21px;
z-index: 1000;
top: 15px;
left: 25px;
border: 0;
display: flex;
align-items: center;
span {
font-family: "Museo Sans Rounded", sans-serif;
font-size: 14px;
letter-spacing: 0;
padding-left: 10px;
}
.fa {
font-size: 18px;
}
}
.signup-wrapper {
position: relative;
margin-bottom: 85px;
.mc-signup-logo {
margin-top: 96px;
img {
height: 60px;
}
}
.title-goes-here {
color: #58595B;
font-family: 'Futura', sans-serif;
font-size: 24px;
font-weight: bold;
letter-spacing: 0;
line-height: 36px;
text-align: center;
margin: 32px 0 8px;
}
.subtitle-giving-cont {
color: #58595B;
font-family: "Museo Sans Rounded";
font-size: 18px;
letter-spacing: 0;
line-height: 27px;
text-align: center;
margin-bottom: 32px;
padding: 0 26px;
}
.password-wrapper {
.fa {
position: absolute;
right: 20px;
top: 18px;
cursor: pointer;
}
}
.action-btn {
height: 50px;
width: 260px;
border-radius: 73px;
background-color: #12A8DE;
padding: 15px;
text-align: center;
color: #fff;
margin: 32px auto 8px;
cursor: pointer;
transition: .3s;
font-weight: bold;
border: 0;
box-shadow: none;
&:disabled {
pointer-events: none;
background: #83b7ca;
}
&:hover {
background: #127BAD;
}
}
.signup-form {
border-radius: 4px;
background-color: #FFFFFF;
box-shadow: 0 0 20px 0 rgba(128,130,133,0.13);
padding: 24px 26px;
.was-referred {
display: flex;
align-items: center;
justify-content: space-between;
}
.forgot-password {
font-family: "Museo Sans Rounded", sans-serif;
font-size: 14px;
letter-spacing: 0;
line-height: 21px;
text-align: center;
}
.signup-link {
color: #58595B;
font-family: "Museo Sans Rounded", sans-serif;
font-size: 14px;
letter-spacing: 0;
line-height: 21px;
text-align: center;
}
}
}
.mc-footer-label {
position: absolute;
bottom: -10%;
left: 43%;
color: #808285;
font-family: "Museo Sans Rounded", sans-serif;
font-size: 11px;
letter-spacing: 0;
line-height: 13px;
}
@media only screen and (max-width: 600px) {
.signup-wrapper {
.mc-signup-logo {
margin-top: 77px;
img {
height: 40px;
}
}
.subtitle-giving-cont {
margin-bottom: 0;
}
.signup-form {
box-shadow: none;
.action-btn {
width: 100%;
}
.was-referred {
display: block;
}
}
.mt-sm-top {
margin-top: 15px;
}
}
.mc-footer-label {
left: 29%;
bottom: -6%;
}
}
import { Component, OnInit, ViewChild } from '@angular/core';
import { NgForm } from '@angular/forms';
import { takeUntil } from 'rxjs/operators';
import { BaseComponent } from '../../base/base.component';
import { AuthService } from '../../services/auth.service';
import { HelperService } from '../../services/helper.service';
@Component({
selector: 'app-register',
templateUrl: './register.component.html',
styleUrls: ['./register.component.scss']
})
export class RegisterComponent extends BaseComponent implements OnInit {
registerForm = {
username: '',
firstname: '',
lastname: '',
email: '',
password: '',
ReferralCode: '',
was_referred: false,
terms: false,
policy: false
};
showPassword = false;
year = new Date().getFullYear();
@ViewChild('form') form: NgForm;
constructor(
private hs: HelperService,
private as: AuthService
) {
super();
}
ngOnInit(): void {
//
}
register(): void {
if (this.form.invalid) {
return this.hs.validateAllFormFields(this.form);
}
this.registerForm.firstname = 'AA';
this.registerForm.lastname = 'BB';
this.registerForm.email = this.registerForm.username;
if (!this.registerForm.was_referred) {
delete this.registerForm.ReferralCode;
}
this.isLoading = true;
this.as.register(this.registerForm)
.pipe(takeUntil(this.componentInView))
.subscribe(response => {
this.isLoading = false;
this.hs.oneItHttpResponse(response);
if (response.registered) {
console.log('Registered');
}
}, err => {
this.isLoading = false;
this.hs.handleHttpError(err);
});
}
}
<div class="bck-link mc-nav-link" routerLink="/my-career-web/auth/login"><i class="fa fa-chevron-left"></i><span>Back</span></div>
<div class="row login-wrapper">
<div class="col-md-offset-4 col-md-4">
<div class="mc-login-logo d-flex justify-content-center">
<img src="/assets/my-career-web/images/MATCHD LOGO_career_horizontal_rgb.png" alt="">
</div>
<div class="title-goes-here">Title goes here</div>
<div class="subtitle-giving-cont">Subtitle giving context to product and selling users on why they should sign up goes here.</div>
<form class="login-form position-relative" #form="ngForm">
<div class="form-group">
<label>Choose your password</label>
<app-form-control>
<app-form-control class="password-wrapper">
<input [type]="showPassword ? 'text' : 'password'" name="password" required class="form-control" [(ngModel)]="resetForm.password">
<i class="fa" [ngClass]="showPassword ? 'fa-eye' : 'fa-eye-slash'" (click)="showPassword = !showPassword"></i>
</app-form-control>
</app-form-control>
</div>
<div class="form-group position-relative">
<label>Confirm your new password</label>
<app-form-control>
<input [type]="showPassword ? 'text' : 'password'" name="confirmPassword" required class="form-control" [(ngModel)]="resetForm.confirmPassword">
</app-form-control>
<small *ngIf="form.valid && resetForm.password !== resetForm.confirmPassword" class="text-danger">Passwords do not match.</small>
</div>
<div class="d-flex justify-content-center">
<app-overlay [isActive]="isLoading"></app-overlay>
<button class="action-btn" (click)="reset()" [disabled]="isLoading || resetForm.password !== resetForm.confirmPassword">Reset Password</button>
</div>
<div class="signup-link">
Got to <span class="mc-nav-link" routerLink="/my-career-web/auth/login">Sign in</span>
</div>
</form>
</div>
</div>
<span class="mc-footer-label">© {{year}} Matchd | Privacy Policy</span>
.bck-link {
position: absolute;
color: #12A8DE;
line-height: 21px;
z-index: 1000;
top: 15px;
left: 25px;
border: 0;
display: flex;
align-items: center;
span {
font-family: "Museo Sans Rounded", sans-serif;
font-size: 14px;
letter-spacing: 0;
padding-left: 10px;
}
.fa {
font-size: 18px;
}
}
.login-wrapper {
position: relative;
.mc-login-logo {
margin-top: 96px;
img {
height: 60px;
}
}
.title-goes-here {
color: #58595B;
font-family: 'Futura', sans-serif;
font-size: 24px;
font-weight: bold;
letter-spacing: 0;
line-height: 36px;
text-align: center;
margin: 32px 0 8px;
}
.subtitle-giving-cont {
color: #58595B;
font-family: "Museo Sans Rounded";
font-size: 18px;
letter-spacing: 0;
line-height: 27px;
text-align: center;
margin-bottom: 32px;
padding: 0 26px;
}
.password-wrapper {
.fa {
position: absolute;
right: 20px;
top: 18px;
cursor: pointer;
}
}
small.text-danger {
position: absolute;
bottom: -15px;
font-size: 10px;
}
.action-btn {
height: 50px;
width: 260px;
border-radius: 73px;
background-color: #12A8DE;
padding: 15px;
text-align: center;
color: #fff;
margin: 24px auto 8px;
cursor: pointer;
transition: .3s;
font-weight: bold;
border: 0;
box-shadow: none;
&:disabled {
pointer-events: none;
background: #83b7ca;
}
&:hover {
background: #127BAD;
}
}
.login-form {
border-radius: 4px;
background-color: #FFFFFF;
box-shadow: 0 0 20px 0 rgba(128,130,133,0.13);
padding: 24px 26px;
.forgot-password {
font-family: "Museo Sans Rounded", sans-serif;
font-size: 14px;
letter-spacing: 0;
line-height: 21px;
text-align: center;
}
.signup-link {
color: #58595B;
font-family: "Museo Sans Rounded", sans-serif;
font-size: 14px;
letter-spacing: 0;
line-height: 21px;
text-align: center;
}
}
}
.mc-footer-label {
position: absolute;
bottom: 4%;
left: 43%;
color: #808285;
font-family: "Museo Sans Rounded", sans-serif;
font-size: 11px;
letter-spacing: 0;
line-height: 13px;
}
@media only screen and (max-width: 600px) {
.login-wrapper {
.mc-login-logo {
margin-top: 77px;
img {
height: 40px;
}
}
.subtitle-giving-cont {
margin-bottom: 0;
}
.login-form {
box-shadow: none;
.action-btn {
width: 100%;
}
}
}
.mc-footer-label {
left: 29%;
bottom: 4%;
}
}
import { Component, OnInit, ViewChild } from '@angular/core';
import { NgForm } from '@angular/forms';
import { ActivatedRoute, Router } from '@angular/router';
import { takeUntil } from 'rxjs/operators';
import { BaseComponent } from '../../base/base.component';
import { AuthService } from '../../services/auth.service';
import { HelperService } from '../../services/helper.service';
import { ToasterService } from '../../services/toaster.service';
@Component({
selector: 'app-reset-password',
templateUrl: './reset-password.component.html',
styleUrls: ['./reset-password.component.scss']
})
export class ResetPasswordComponent extends BaseComponent implements OnInit {
year = new Date().getFullYear();
resetForm = {
password: '',
confirmPassword: ''
};
resetToken;
showPassword = false;
@ViewChild('form') form: NgForm;
constructor(
private hs: HelperService,
private ar: ActivatedRoute,
private ts: ToasterService,
private as: AuthService,
private r: Router
) {
super();
}
ngOnInit(): void {
this.ar.params
.pipe(takeUntil(this.componentInView))
.subscribe(params => {
if (params.token) {
this.resetToken = params.token;
}
});
}
reset(): void {
if (this.form.invalid) {
return this.hs.validateAllFormFields(this.form);
}
const formData = {resetToken: this.resetToken, newPassword: this.resetForm.password};
this.isLoading = true;
this.as.reset(formData)
.pipe(takeUntil(this.componentInView))
.subscribe(response => {
this.isLoading = false;
this.hs.oneItHttpResponse(response);
if (response.passwordChanged) {
this.ts.success('Password changed.');
this.r.navigate(['/my-career-web/auth/login']);
}
}, err => {
this.hs.handleHttpError(err);
this.isLoading = false;
});
}
}
import { OnDestroy } from '@angular/core';
import { Subject } from 'rxjs';
export class BaseComponent implements OnDestroy {
isEditMode = false;
isLoading = false;
protected componentInView = new Subject();
ngOnDestroy(): void {
this.componentInView.next();
this.componentInView.complete();
}
}
import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core';
import { McSharedModule } from '../mc-shared/mc-shared.module';
import { DashboardRouting } from './dashboard.routing';
import { DashboardComponent } from './dashboard/dashboard.component';
@NgModule({
imports: [
CommonModule,
McSharedModule,
DashboardRouting
],
declarations: [DashboardComponent]
})
export class DashboardModule {
}
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { DashboardComponent } from './dashboard/dashboard.component';
const routes: Routes = [
{path: '', component: DashboardComponent}
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule]
})
export class DashboardRouting { }
<app-overlay [isActive]="isLoading"></app-overlay>
<a (click)="logout()">Logout</a>
import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';
import { takeUntil } from 'rxjs/operators';
import { BaseComponent } from '../../base/base.component';
import { AuthService } from '../../services/auth.service';
@Component({
selector: 'app-dashboard',
templateUrl: './dashboard.component.html',
styleUrls: ['./dashboard.component.scss']
})
export class DashboardComponent extends BaseComponent implements OnInit {
constructor(
private as: AuthService,
private r: Router
) {
super();
}
ngOnInit(): void {
//
}
logout(): void {
this.isLoading = true;
this.as.logout()
.pipe(takeUntil(this.componentInView))
.subscribe(() => {
this.r.navigate(['/my-career-web/auth/login']);
this.isLoading = false;
});
}
}
import { Injectable } from '@angular/core';
import { ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot } from '@angular/router';
import { Observable } from 'rxjs/Observable';
import { of } from 'rxjs/observable/of';
import { environment } from '../../../../environments/environment';
import { ApiService } from '../../../oneit/services/api.service';
import { UtilsService } from '../../../oneit/services/utils.service';
@Injectable()
export class HomeGuard implements CanActivate {
constructor(
private r: Router,
private as: ApiService,
private us: UtilsService
) {
}
canActivate(
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot): Observable<boolean> {
const params = {
environment: environment.envName,
queryType: 'All'
};
return this.as.post('svc/EnvironmentInformation', params)
.map(
data => {
if (this.us.isSuccessfulResponse(data)) {
if (data.UserName !== 'noprivauthtoken') {
return true;
}
this.r.navigate(['/my-career-web/auth/login']);
return false;
}
}
)
.catch(
() => of(false)
);
}
}
import { Injectable } from '@angular/core';
import { ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot } from '@angular/router';
import { Observable } from 'rxjs/Observable';
import { of } from 'rxjs/observable/of';
import { environment } from '../../../../environments/environment';
import { ApiService } from '../../../oneit/services/api.service';
import { UtilsService } from '../../../oneit/services/utils.service';
@Injectable()
export class PublicGuard implements CanActivate {
constructor(
private r: Router,
private as: ApiService,
private us: UtilsService
) {
}
canActivate(
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot): Observable<boolean> {
const params = {
environment: environment.envName,
queryType: 'All'
};
return this.as.post('svc/EnvironmentInformation', params)
.map(
data => {
if (this.us.isSuccessfulResponse(data)) {
if (data.UserName !== 'noprivauthtoken') {
this.r.navigate(['/my-career-web/dashboard']);
return false;
}
return true;
}
}
)
.catch(
() => of(false)
);
}
}
<div class="my-career-app container-fluid" [@routeAnimations]="o.isActivated ? o.activatedRoute : ''">
<p-toast></p-toast>
<router-outlet #o="outlet"></router-outlet>
</div>
import { animate, style, transition, trigger } from '@angular/animations';
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-wrapper',
templateUrl: './wrapper.component.html',
styleUrls: ['./wrapper.component.scss'],
animations: [
trigger('routeAnimations', [
transition('* => *', [
style({opacity: 0}),
animate('300ms', style({opacity: 1}))
])
]
)
]
})
export class WrapperComponent implements OnInit {
constructor() {
//
}
ngOnInit() {
//
}
}
<div [class]="'form-control-wrapper ' + class" [ngClass]="{ 'is-invalid': isHighlighted }">
<ng-content></ng-content>
<small class="form-text text-danger" *ngIf="isHighlighted">{{getError()}}</small>
</div>
.form-control-wrapper {
position: relative;
.text-danger {
position: absolute;
bottom: -15px;
font-size: 10px;
}
&.is-invalid {
.text-danger {
color: #e62a10;
}
}
}
import { Component, ContentChild, Input } from '@angular/core';
import { AbstractControl, NgModel } from '@angular/forms';
@Component({
selector: 'app-form-control',
templateUrl: './form-control.component.html',
styleUrls: ['./form-control.component.scss']
})
export class FormControlComponent {
@Input() errorMap;
@Input() class = '';
@ContentChild(NgModel) model: NgModel;
errorMessages = {
email: 'Enter a valid email.',
required: 'This field is required.',
min: 'value too small',
max: 'value too large',
minLength: 'value too short',
maxLength: 'value too big',
greaterThan: 'Less than start time.'
};
getError(): string {
const errors = this.control.errors;
let error = '';
if (errors) {
Object
.keys(errors)
.some(errorKey => {
if (errors[errorKey]) {
error = this.errorMessages[errorKey] || this.errorMap[errorKey] || 'Invalid value';
return true;
}
});
}
return error;
}
get control(): AbstractControl {
return this.model.control;
}
get isHighlighted(): boolean {
return this.control.invalid && (this.control.dirty || this.control.touched);
}
}
import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { CheckboxModule } from 'primeng/checkbox';
import { RadioButtonModule } from 'primeng/radiobutton';
import { ToastModule } from 'primeng/toast';
import { HelperService } from '../services/helper.service';
import { ToasterService } from '../services/toaster.service';
import { FormControlComponent } from './form-control/form-control.component';
import { OverlayComponent } from './overlay/overlay.component';
const MODULES = [
ReactiveFormsModule,
FormsModule,
RadioButtonModule,
CheckboxModule,
ToastModule
];
const COMPONENTS = [
FormControlComponent,
OverlayComponent
];
const DIRECTIVES = [
];
@NgModule({
imports: [
CommonModule,
...MODULES
],
exports: [
...MODULES,
...COMPONENTS,
...DIRECTIVES
],
providers: [
ToasterService,
HelperService
],
declarations: [
...COMPONENTS,
...DIRECTIVES
]
})
export class McSharedModule {
}
<div class="overlay-wrapper" *ngIf="isActive" [@fadeOutAnimation]>
<div class="loader-container" style="background-color: transparent;">
<div class="loader-inner" style="transform-origin: center center; transform: scale(1, 1);">
<div class="ball-pulse">
<div style="background-color: rgb(25, 118, 210);"></div>
<div style="background-color: rgb(25, 118, 210);"></div>
<div style="background-color: rgb(25, 118, 210);"></div>
</div>
</div>
</div>
</div>
.overlay-wrapper {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
display: flex;
align-items: center;
justify-content: center;
background: rgba(255, 255, 255, 0.7);
z-index: 100;
}
.ball-pulse-sync > div, .ball-pulse > div {
width: 15px;
height: 15px;
margin: 2px;
display: inline-block
}
.ball-pulse-sync > div, .ball-pulse > div, .ball-scale > div {
background-color: #fff;
border-radius: 100%
}
@-webkit-keyframes scale {
0%, 80% {
transform: scale(1);
opacity: 1
}
45% {
transform: scale(.1);
opacity: .7
}
}
@keyframes scale {
0%, 80% {
transform: scale(1);
opacity: 1
}
45% {
transform: scale(.1);
opacity: .7
}
}
.ball-pulse > div:nth-child(0) {
-webkit-animation: .75s cubic-bezier(.2,.68,.18,1.08) -.36s infinite scale;
animation: .75s cubic-bezier(.2,.68,.18,1.08) -.36s infinite scale
}
.ball-pulse > div:nth-child(1) {
-webkit-animation: .75s cubic-bezier(.2,.68,.18,1.08) -.24s infinite scale;
animation: .75s cubic-bezier(.2,.68,.18,1.08) -.24s infinite scale
}
.ball-pulse > div:nth-child(2) {
-webkit-animation: .75s cubic-bezier(.2,.68,.18,1.08) -.12s infinite scale;
animation: .75s cubic-bezier(.2,.68,.18,1.08) -.12s infinite scale
}
.ball-pulse > div:nth-child(3) {
-webkit-animation: .75s cubic-bezier(.2, .68, .18, 1.08) infinite scale;
animation: .75s cubic-bezier(.2, .68, .18, 1.08) infinite scale
}
.ball-pulse > div {
-webkit-animation-fill-mode: both;
animation-fill-mode: both
}
@-webkit-keyframes ball-pulse-sync {
33% {
transform: translateY(10px)
}
66% {
transform: translateY(-10px)
}
100% {
transform: translateY(0)
}
}
@keyframes ball-pulse-sync {
33% {
transform: translateY(10px)
}
66% {
transform: translateY(-10px)
}
100% {
transform: translateY(0)
}
}
.ball-pulse-sync > div:nth-child(0) {
-webkit-animation: .6s ease-in-out -.21s infinite ball-pulse-sync;
animation: .6s ease-in-out -.21s infinite ball-pulse-sync
}
.ball-pulse-sync > div:nth-child(1) {
-webkit-animation: .6s ease-in-out -.14s infinite ball-pulse-sync;
animation: .6s ease-in-out -.14s infinite ball-pulse-sync
}
.ball-pulse-sync > div:nth-child(2) {
-webkit-animation: .6s ease-in-out -.07s infinite ball-pulse-sync;
animation: .6s ease-in-out -.07s infinite ball-pulse-sync
}
.ball-pulse-sync > div:nth-child(3) {
-webkit-animation: .6s ease-in-out infinite ball-pulse-sync;
animation: .6s ease-in-out infinite ball-pulse-sync
}
.ball-pulse-sync > div {
-webkit-animation-fill-mode: both;
animation-fill-mode: both
}
import { animate, style, transition, trigger } from '@angular/animations';
import { Component, Input } from '@angular/core';
@Component({
selector: 'app-overlay',
templateUrl: './overlay.component.html',
styleUrls: ['./overlay.component.scss'],
animations: [
trigger('fadeOutAnimation', [
transition(':leave',
animate(300, style({opacity: 0})))
])
]
})
export class OverlayComponent {
@Input() isActive = false;
}
import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core';
import { MessageService } from 'primeng/api';
import { HomeGuard } from './guards/home.guard';
import { PublicGuard } from './guards/public.guard';
import { WrapperComponent } from './layouts/wrapper/wrapper.component';
import { McSharedModule } from './mc-shared/mc-shared.module';
import { MyCareerWebRouting } from './my-career-web.routing';
import { AuthService } from './services/auth.service';
import { WelcomeComponent } from './welcome/welcome.component';
@NgModule({
imports: [
CommonModule,
McSharedModule,
MyCareerWebRouting
],
providers: [
AuthService,
MessageService,
PublicGuard,
HomeGuard
],
declarations: [
WrapperComponent,
WelcomeComponent
]
})
export class MyCareerWebModule {
}
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { AuthModule } from './auth/auth.module';
import { DashboardModule } from './dashboard/dashboard.module';
import { HomeGuard } from './guards/home.guard';
import { PublicGuard } from './guards/public.guard';
import { WrapperComponent } from './layouts/wrapper/wrapper.component';
import { WelcomeComponent } from './welcome/welcome.component';
const routes: Routes = [
{
path: '',
component: WrapperComponent,
children: [
{
path: 'auth',
// @ts-ignore
// tslint:disable-next-line:newline-per-chained-call
loadChildren: () => import('./auth/auth.module').then(() => AuthModule),
canActivate: [PublicGuard]
},
{
path: 'dashboard',
// @ts-ignore
// tslint:disable-next-line:newline-per-chained-call
loadChildren: () => import('./dashboard/dashboard.module').then(() => DashboardModule),
canActivate: [HomeGuard]
},
{path: '', component: WelcomeComponent, canActivate: [PublicGuard]}
]
}
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule]
})
export class MyCareerWebRouting {
}
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import { environment } from '../../../../environments/environment';
import { ApiService } from '../../../oneit/services/api.service';
@Injectable()
export class AuthService {
env = environment.envName;
constructor(
private as: ApiService
) {
}
login(formData): Observable<any> {
formData.environment = this.env;
return this.as.post('svc/Login', formData);
}
googleLogin(formData = {} as any): Observable<any> {
formData.environment = this.env;
return this.as.post('svc/LoginWithGoogle', formData);
}
linkedinLogin(formData = {} as any): Observable<any> {
formData.environment = this.env;
return this.as.post('svc/LoginWithGoogle', formData);
}
forgot(formData): Observable<any> {
formData.environment = this.env;
return this.as.post('svc/RequestPasswordReset', formData);
}
register(formData): Observable<any> {
formData.environment = this.env;
return this.as.post('svc/RegisterMyCareerUser', formData);
}
reset(formData): Observable<any> {
formData.environment = this.env;
return this.as.post('svc/PasswordChange', formData);
}
logout(formData = {} as any): Observable<any> {
formData.environment = this.env;
return this.as.post('svc/Logout', formData);
}
}
import { HttpErrorResponse } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { FormArray, FormControl, FormGroup } from '@angular/forms';
import { ToasterService } from './toaster.service';
@Injectable()
export class HelperService {
constructor(
private ts: ToasterService
) {
}
validateAllFormFields(form?: any): void {
const formObj = typeof form.form ? form.form : form;
Object
.keys(form.controls)
.forEach(field => {
const control = formObj.get(field);
if (control instanceof FormControl) {
control.markAsDirty({onlySelf: true});
control.markAsTouched({onlySelf: true});
} else if (control instanceof FormGroup) {
this.validateAllFormFields(control);
} else if (control instanceof FormArray) {
control.controls.forEach(ctrl => {
if (ctrl instanceof FormControl) {
ctrl.markAsDirty({onlySelf: true});
ctrl.markAsTouched({onlySelf: true});
} else if (ctrl instanceof FormGroup) {
this.validateAllFormFields(ctrl);
}
});
}
});
}
handleHttpError(httpError: HttpErrorResponse): void {
let message;
message = httpError.error.errors ? httpError.error.errors[Object.keys(httpError.error.errors)[0]] : httpError.error.message;
switch (httpError.status) {
case 401:
break;
case 403:
break;
case 404:
break;
case 422:
break;
case 500:
message = 'Internal server error';
break;
case 0:
message = 'No internet connection.';
break;
default:
break;
}
this.ts.error(message, 'Request Error');
}
oneItHttpResponse(response): void {
if (response.status === 'error') {
this.ts.error(response.errorDetails[0], 'Error');
}
}
}
import { Injectable } from '@angular/core';
import { MessageService } from 'primeng/api';
@Injectable()
export class ToasterService {
constructor(
private ms: MessageService
) { }
error(txt, title = 'Error'): void {
this.ms.add({severity: 'error', summary: title, detail: txt, life: 3000});
}
success(txt, title = 'Success'): void {
this.ms.add({severity: 'success', summary: title, detail: txt, life: 3000});
}
info(txt, title = 'Notification'): void {
this.ms.add({severity: 'info', summary: title, detail: txt, life: 3000});
}
}
<div class="row login-wrapper">
<div class="col-md-offset-4 col-md-4">
<div class="mc-login-logo d-flex justify-content-center">
<img src="/assets/my-career-web/images/MATCHD_LOGO.jpg" alt="">
</div>
<div class="title-goes-here">Welcome to Matchd Career</div>
<div class="subtitle-giving-cont">You can either Sign Up for a new account or Sign In to your existing account.</div>
<div class="d-flex justify-content-between">
<button class="action-btn" routerLink="/my-career-web/auth/login">Sign In</button>
<button class="action-btn" routerLink="/my-career-web/auth/register">Sign Up</button>
</div>
</div>
</div>
.login-wrapper {
position: relative;
margin-bottom: 45px;
.mc-login-logo {
margin-top: 96px;
img {
height: 60px;
}
}
.title-goes-here {
color: #58595B;
font-family: 'Futura', sans-serif;
font-size: 24px;
font-weight: bold;
letter-spacing: 0;
line-height: 36px;
text-align: center;
margin: 32px 0 8px;
}
.subtitle-giving-cont {
color: #58595B;
font-family: "Museo Sans Rounded";
font-size: 18px;
letter-spacing: 0;
line-height: 27px;
text-align: center;
margin-bottom: 32px;
padding: 0 26px;
}
.action-btn {
height: 50px;
width: 260px;
border-radius: 73px;
background-color: #12A8DE;
padding: 15px;
text-align: center;
color: #fff;
margin: 24px auto 8px;
cursor: pointer;
transition: .3s;
font-weight: bold;
border: 0;
box-shadow: none;
&:hover {
background-color: #127BAD;
}
&.google-login {
background-color: #de5246;
&:hover {
background-color: #C34C41;
}
}
&.linkedin-login {
background-color: #0072b1;
margin: 0;
&:hover {
background-color: #005A8D;
}
}
}
}
.mc-footer-label {
position: absolute;
bottom: -10%;
left: 43%;
color: #808285;
font-family: "Museo Sans Rounded", sans-serif;
font-size: 11px;
letter-spacing: 0;
line-height: 13px;
}
@media only screen and (max-width: 600px) {
.login-wrapper {
.mc-login-logo {
margin-top: 77px;
img {
height: 40px;
}
}
.subtitle-giving-cont {
margin-bottom: 0;
}
}
.mc-footer-label {
left: 29%;
bottom: -4%;
}
}
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-welcome',
templateUrl: './welcome.component.html',
styleUrls: ['./welcome.component.scss']
})
export class WelcomeComponent implements OnInit {
constructor() { }
ngOnInit() {
}
}
export const environment = {
production: false,
baseUrl: 'http://localhost:8080/performa/',
baseUrl: 'http://vm4.qa03.oneit.com.au/mycareer/',
envName: 'QA',
gtmKey: 'GTM-M6M4SW6'
};
......@@ -7,6 +7,7 @@
@import url('~primeicons/primeicons.css');
@import url('~select2/dist/css/select2.min.css');
@import url('~assets/css/common.css');
@import 'styles/my-career-styles/styles';
/* You can add global styles to this file, and also import other style files */
......@@ -141,4 +142,4 @@ p-progressSpinner {
.modal-open {
overflow: scroll;
}
\ No newline at end of file
}
.d-flex {
display: flex !important;
}
.justify-content {
&-center {
justify-content: center;
}
&-between {
justify-content: space-between;
}
}
.align-items {
&-center {
align-items: center;
}
}
.position {
&-relative {
position: relative;
}
}
.form-group {
margin-bottom: 21px;
label {
color: #58595B;
font-family: "Museo Sans Rounded", sans-serif;
font-size: 14px;
letter-spacing: 0;
line-height: 21px;
margin-bottom: 6px;
}
.form-control {
box-sizing: border-box;
height: 46px;
background-color: #FFFFFF;
border-radius: 4px;
border: 2px solid #E0E0E0;
box-shadow: none !important;
transition: .3s;
&:focus, &:active {
border: 2px solid #12A8DE !important;
}
&.ng-dirty.ng-valid, &.ng-touched.ng-valid {
border: 1px solid #1DBA3C;
}
&.ng-dirty.ng-invalid, &.ng-touched.ng-invalid {
border: 1px solid #e62a10;
}
}
}
.mc-nav-link {
color: #12A8DE;
border-bottom: 1px solid transparent;
transition: .3s;
cursor: pointer;
&:hover {
border-bottom-color: #12A8DE;
}
}
.my-career-app {
@import "flex-helpers";
@import "form";
@import "misc";
@import "primeng/radio";
@import "primeng/checkbox";
@import "primeng/toast";
}
p-checkbox {
.ui-chkbox {
&-box {
border: 1px solid #E0E0E0;
.ui-chkbox-icon {
font-size: 1em;
margin-left: 1px;
margin-top: 1px;
}
&.ui-state-active {
background: #12A8DE !important;
border-color: #12A8DE !important;
}
}
}
}
p-radioButton {
.ui-radiobutton {
margin: 0;
&-label {
font-family: 'Museo Sans Rounded 500', sans-serif;
margin: 0 0 0 5px;
}
&-box {
border: 1px solid #E0E0E0;
.pi-circle-on {
transform: scale(0.75);
background: #12A8DE;
}
}
}
}
.ui-toast {
width: 17em;
&-message {
&-text-content {
margin-left: 0;
}
&-error {
background: #bd2712;
color: #fff;
}
&-success {
background: #1DBA3C;
color: #fff;
}
}
&-close-icon {
color: #fff;
right: 8px;
top: 8px;
font-size: 20px;
}
&-summary {
padding: 0 0 0.2em 0;
}
&-icon {
display: none;
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment