Commit e2113669 authored by vtduong0912's avatar vtduong0912

implemented login 1/2

parent f87a738f
...@@ -91,7 +91,7 @@ ...@@ -91,7 +91,7 @@
"input": "public" "input": "public"
} }
], ],
"styles": ["src/styles.scss"], "styles": ["src/styles.scss", "node_modules/ng-zorro-antd/ng-zorro-antd.min.css"],
"scripts": [] "scripts": []
} }
} }
......
...@@ -8,5 +8,7 @@ export class AuthGuard implements CanActivate { ...@@ -8,5 +8,7 @@ export class AuthGuard implements CanActivate {
constructor() {} constructor() {}
canActivate(): boolean { canActivate(): boolean {
return true; return true;
// return false if logged in
// return false;
} }
} }
export namespace Login {
export type Response = {
user: {
username: string,
role: string,
}
};
export type Request = {
username: string,
password: string
};
}
\ No newline at end of file
import { HttpClient } from "@angular/common/http";
import { Injectable } from "@angular/core";
import { Login } from "../model/login.model";
import { ResponseResult } from "../../../shared/data-access/interface/response.type";
import { Observable, map } from "rxjs";
@Injectable({
providedIn: 'root'
})
export class AuthService {
constructor(
private _http: HttpClient
) { }
loginPost(request: Login.Request) {
return this._http
.post<ResponseResult<Login.Response>>('login', request)
.pipe(
map((response) => {
console.log(response);
return response;
}));
}
}
\ No newline at end of file
<div class="tw-max-w-7xl tw-mx-auto">
<nz-card
class="tw-max-w-[30rem] tw-mx-auto tw-mt-8 tw-rounded-lg"
nzTitle="Login"
>
<form nz-form [formGroup]="signInFormGroup">
<nz-form-item>
<nz-form-control>
<nz-input-group>
<input
type="text"
nz-input
id="username_input"
placeholder="Username"
class="tw-h-10 tw-text-sm tw-rounded-md"
formControlName="username"
/>
</nz-input-group>
</nz-form-control>
</nz-form-item>
<nz-form-item>
<nz-form-control>
<nz-input-group>
<input
type="password"
nz-input
id="password_input"
placeholder="Password"
class="tw-h-10 tw-text-sm tw-rounded-md"
formControlName="password"
/>
</nz-input-group>
</nz-form-control>
</nz-form-item>
<div *ngIf="errorMsg">
<nz-alert nzType="error" [nzMessage]="errorMsg"></nz-alert>
</div>
<nz-form-item>
<nz-form-control>
<label nz-checkbox
>Remember me</label
>
</nz-form-control>
</nz-form-item>
<div></div>
<div class="tw-w-full tw-text-center tw-my-3">
<button
(click)="onLogin()"
nz-button
nzType="primary"
class="tw-text-lg tw-h-10"
>
Login
</button>
</div>
</form>
</nz-card>
</div>
<ng-template #prefixTemplateUser
><span nz-icon nzType="user"></span
></ng-template>
<ng-template #prefixTemplatePassword
><span nz-icon nzType="ellipsis" nzTheme="outline"></span
></ng-template>
import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core'; import { ChangeDetectionStrategy, ChangeDetectorRef, Component, OnInit } from '@angular/core';
import { CommonModule } from '@angular/common'; import { CommonModule, JsonPipe } from '@angular/common';
import { NzCardModule } from 'ng-zorro-antd/card';
import { NzInputModule } from 'ng-zorro-antd/input'
import { NzButtonModule } from 'ng-zorro-antd/button';
import { NzIconModule } from 'ng-zorro-antd/icon';
import { NzCheckboxModule } from 'ng-zorro-antd/checkbox';
import { NzFormModule } from 'ng-zorro-antd/form';
import { NzAlertModule } from 'ng-zorro-antd/alert';
import { FormBuilder, FormGroup, ReactiveFormsModule, Validators } from '@angular/forms';
import { AuthService } from '../data-access/service/auth.service';
import { validateUsername } from '../../shared/utils/form-validator/username.validator';
import { catchError, of, tap } from 'rxjs';
import { ResponseResult } from '../../shared/data-access/interface/response.type';
import { Login } from '../data-access/model/login.model';
import { Router } from '@angular/router';
@Component({ @Component({
selector: 'meu-login', selector: 'meu-login',
standalone: true, standalone: true,
templateUrl: './login.component.html', templateUrl: './login.component.html',
styleUrls: ['./login.component.scss'], styleUrls: ['./login.component.scss'],
imports: [CommonModule], imports: [
CommonModule,
NzCardModule,
NzInputModule,
NzButtonModule,
NzIconModule,
NzCheckboxModule,
NzAlertModule,
NzFormModule,
ReactiveFormsModule,
JsonPipe
],
changeDetection: ChangeDetectionStrategy.OnPush, changeDetection: ChangeDetectionStrategy.OnPush,
}) })
export class LoginComponent implements OnInit { export class LoginComponent implements OnInit {
constructor() {} errorMsg?: string;
signInFormGroup!: FormGroup;
ngOnInit() {} constructor(
private _formBuilder: FormBuilder,
private _authService: AuthService,
private _changeDetectorRef: ChangeDetectorRef,
private _router: Router
) {}
ngOnInit(): void {
this.signInFormGroup = this._formBuilder.group({
username: [null, [Validators.required, validateUsername]],
password: [null, Validators.required],
});
}
onLogin() {
const data = this.signInFormGroup.value;
this.signInFormGroup.markAllAsTouched();
this._authService.loginPost(data)
.pipe(
tap((response: ResponseResult<Login.Response>) => {
this.onSuccess(response);
}),
catchError((error: ResponseResult<any>) => {
this.onError(error);
return of(null);
})
)
.subscribe();
}
onSuccess(response: ResponseResult<Login.Response>) {
console.log(response);
this._router.navigate(['/home']);
}
onError(error: ResponseResult<any>) {
if (error.status === 401) {
this.errorMsg = "Invalid username or password!";
} else {
this.errorMsg = "An error has occurred! Please try later.";
}
this._changeDetectorRef.markForCheck();
}
} }
...@@ -33,7 +33,13 @@ export const shellRoutes: Routes = [ ...@@ -33,7 +33,13 @@ export const shellRoutes: Routes = [
}, },
{ {
path: 'login', path: 'login',
component: LoginComponent, component: LayoutComponent,
children: [
{
path: '',
canActivate: [AuthGuard], canActivate: [AuthGuard],
loadChildren: () => import('../../+login/login.routes'),
}
]
}, },
]; ];
<footer> <nz-footer>
<h1> <h1>This is footer</h1>
It is a footer </nz-footer>
</h1> \ No newline at end of file
</footer>
\ No newline at end of file
import { CommonModule } from '@angular/common'; import { CommonModule } from '@angular/common';
import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core'; import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core';
import { NzLayoutModule } from 'ng-zorro-antd/layout';
@Component({ @Component({
selector: 'meu-footer', selector: 'meu-footer',
standalone: true, standalone: true,
imports: [CommonModule], imports: [CommonModule, NzLayoutModule],
templateUrl: './footer.component.html', templateUrl: './footer.component.html',
changeDetection: ChangeDetectionStrategy.OnPush, changeDetection: ChangeDetectionStrategy.OnPush,
}) })
......
<header> <nz-header class="tw-bg-white">
<h1> <a routerLink="/home" routerLinkActive="active">
It is a header <img src="https://yt3.googleusercontent.com/y4J_Fs5ksRlxx6_LzT1VKxVqH_T8Vyn_RN_YYgLJhuMzBS5qxTgm7NlEcMkQd3hgCpfWtYcEUg=s900-c-k-c0x00ffffff-no-rj" class="tw-border tw-rounded-full tw-w-10 tw-h-10 tw-mt-3 tw-float-left">
</h1> </a>
</header> <ul nz-menu nzMode="horizontal">
\ No newline at end of file <li nz-menu-item>Home</li>
<li nz-menu-item routerLink="/login" routerLinkActive="active">Login</li>
<li nz-menu-item>Register</li>
</ul>
</nz-header>
import { CommonModule } from '@angular/common'; import { CommonModule } from '@angular/common';
import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core'; import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core';
import { NzLayoutModule } from 'ng-zorro-antd/layout';
import { NzCardModule } from 'ng-zorro-antd/card';
import { NzMenuModule } from 'ng-zorro-antd/menu';
import { RouterLink, RouterLinkActive } from '@angular/router';
@Component({ @Component({
selector: 'meu-header', selector: 'meu-header',
standalone: true, standalone: true,
imports: [CommonModule], imports: [CommonModule, NzLayoutModule, NzCardModule, NzMenuModule, RouterLink, RouterLinkActive],
templateUrl: './header.component.html', templateUrl: './header.component.html',
changeDetection: ChangeDetectionStrategy.OnPush, changeDetection: ChangeDetectionStrategy.OnPush,
}) })
......
...@@ -12,6 +12,8 @@ import { NzToolTipModule } from 'ng-zorro-antd/tooltip'; ...@@ -12,6 +12,8 @@ import { NzToolTipModule } from 'ng-zorro-antd/tooltip';
import { BreakpointObserver, Breakpoints } from '@angular/cdk/layout'; import { BreakpointObserver, Breakpoints } from '@angular/cdk/layout';
import { HeaderComponent } from './components/header/feature/header.component'; import { HeaderComponent } from './components/header/feature/header.component';
import { FooterComponent } from './components/footer/feature/footer.component'; import { FooterComponent } from './components/footer/feature/footer.component';
import { NzCardModule } from 'ng-zorro-antd/card';
import { NzLayoutModule } from 'ng-zorro-antd/layout';
@Component({ @Component({
selector: 'meu-layout', selector: 'meu-layout',
...@@ -25,14 +27,17 @@ import { FooterComponent } from './components/footer/feature/footer.component'; ...@@ -25,14 +27,17 @@ import { FooterComponent } from './components/footer/feature/footer.component';
NzIconModule, NzIconModule,
CommonModule, CommonModule,
NzToolTipModule, NzToolTipModule,
NzLayoutModule
], ],
template: ` template: `
<div class="tw-container"> <div class="tw-container">
<nz-layout>
<meu-header></meu-header> <meu-header></meu-header>
<div class="tw-relative tw-min-h-[92dvh]"> <div class="tw-relative tw-min-h-[92dvh]">
<router-outlet></router-outlet> <router-outlet></router-outlet>
</div> </div>
<meu-footer></meu-footer> <meu-footer></meu-footer>
</nz-layout>
</div> </div>
`, `,
animations: [], animations: [],
......
export const environment = { export const environment = {
API_DOMAIN: 'http://localhost:5051/api/v1.0/', //custom API_DOMAIN: 'http://localhost:3000/', //custom
}; };
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
@tailwind utilities; @tailwind utilities;
@import "custom/tailwind"; @import "custom/tailwind";
@import "custom/ant"; @import "custom/ant";
@import "ng-zorro-antd/ng-zorro-antd.min.css";
@layer base { @layer base {
:root { :root {
......
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