diff --git a/src/app/app.component.html b/src/app/app.component.html
index 642c284..7490ec0 100644
--- a/src/app/app.component.html
+++ b/src/app/app.component.html
@@ -1,9 +1,9 @@
-
diff --git a/src/app/app.component.ts b/src/app/app.component.ts
index 7131c97..ab69dbd 100644
--- a/src/app/app.component.ts
+++ b/src/app/app.component.ts
@@ -1,5 +1,6 @@
import { Component, Renderer2 } from '@angular/core';
import { ColorThemeService } from './services/colorTheme.service';
+import { AuthService } from './services/auth.service';
@Component({
selector: 'app-root',
@@ -7,16 +8,19 @@ import { ColorThemeService } from './services/colorTheme.service';
styleUrls: ['./app.component.scss'],
})
export class AppComponent {
- title = 'flotte-frontend';
+ title = 'fLotte-fRontend';
darkThemeIsActive: boolean = false;
+ loggedIn = false;
constructor(
private renderer: Renderer2,
- private themeService: ColorThemeService
+ private themeService: ColorThemeService,
+ private authService: AuthService
) {
this.renderer.addClass(document.body, 'mat-app-background'); //so the background color changes dependent on current theme
this.themeService.load();
this.darkThemeIsActive = this.themeService.currentActive() === 'dark-theme';
+ this.authService.loggedIn.subscribe((value) => (this.loggedIn = value));
}
changeTheme(event) {
diff --git a/src/app/app.module.ts b/src/app/app.module.ts
index 546efd0..a2df947 100644
--- a/src/app/app.module.ts
+++ b/src/app/app.module.ts
@@ -1,5 +1,7 @@
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
+import {FormsModule, ReactiveFormsModule} from '@angular/forms';
+import { HttpClientModule } from '@angular/common/http';
// Angular Material Components
import {MatToolbarModule} from '@angular/material/toolbar';
@@ -11,6 +13,9 @@ import {MatSlideToggleModule} from '@angular/material/slide-toggle';
import {MatIconModule} from '@angular/material/icon';
import {MatSidenavModule} from '@angular/material/sidenav';
import {MatListModule} from '@angular/material/list';
+import {MatFormFieldModule} from '@angular/material/form-field';
+import {MatProgressSpinnerModule} from '@angular/material/progress-spinner';
+import {MatProgressBarModule} from '@angular/material/progress-bar';
import { AppRoutingModule } from './app-routing.module';
@@ -29,8 +34,11 @@ import { BikesComponent } from './pages/bikes/bikes.component';
],
imports: [
BrowserModule,
+ HttpClientModule,
AppRoutingModule,
BrowserAnimationsModule,
+ FormsModule,
+ ReactiveFormsModule,
MatToolbarModule,
MatButtonModule,
MatTableModule,
@@ -39,7 +47,10 @@ import { BikesComponent } from './pages/bikes/bikes.component';
MatSlideToggleModule,
MatIconModule,
MatSidenavModule,
- MatListModule
+ MatListModule,
+ MatFormFieldModule,
+ MatProgressSpinnerModule,
+ MatProgressBarModule
],
providers: [],
bootstrap: [AppComponent]
diff --git a/src/app/models/user.ts b/src/app/models/user.ts
new file mode 100644
index 0000000..16091b4
--- /dev/null
+++ b/src/app/models/user.ts
@@ -0,0 +1,5 @@
+export class User {
+ email: string;
+ requestToken: string;
+ refreshToken: string;
+}
\ No newline at end of file
diff --git a/src/app/pages/login/login.component.html b/src/app/pages/login/login.component.html
index 147cfc4..290b9a0 100644
--- a/src/app/pages/login/login.component.html
+++ b/src/app/pages/login/login.component.html
@@ -1 +1,38 @@
-login works!
+
+
fLotte Login
+
+ E-Mail-Adresse eingeben
+
+
+ Bitte geben Sie eine E-Mail-Adresse ein.
+
+
+ Bitte geben Sie eine valide E-Mail-Adresse ein.
+
+
+
+
+ Passwort eingeben
+
+
+ Bitte geben Sie Ihr Passwort ein.
+
+
+ {{ hide ? "visibility_off" : "visibility" }}
+
+
+
+
+ Login
+
+
diff --git a/src/app/pages/login/login.component.scss b/src/app/pages/login/login.component.scss
index e69de29..542b480 100644
--- a/src/app/pages/login/login.component.scss
+++ b/src/app/pages/login/login.component.scss
@@ -0,0 +1,16 @@
+#login-form {
+ height: 100%;
+ display: flex;
+ flex-direction: column;
+ max-width: 32em;
+ min-width: 5em;
+ margin: auto;
+ margin-top: 3em;
+ padding: 1em;
+ .mat-form-field {
+ margin: 0.5em 0;
+ }
+ #loading-bar {
+ margin-bottom: 1em;
+ }
+}
\ No newline at end of file
diff --git a/src/app/pages/login/login.component.ts b/src/app/pages/login/login.component.ts
index c74528f..653e5bb 100644
--- a/src/app/pages/login/login.component.ts
+++ b/src/app/pages/login/login.component.ts
@@ -1,4 +1,6 @@
import { Component, OnInit } from '@angular/core';
+import {FormControl, Validators} from '@angular/forms';
+import {AuthService} from '../../services/auth.service';
@Component({
selector: 'app-login',
@@ -6,10 +8,20 @@ import { Component, OnInit } from '@angular/core';
styleUrls: ['./login.component.scss']
})
export class LoginComponent implements OnInit {
-
- constructor() { }
+ email = new FormControl('', [Validators.required, Validators.email]);
+ password = new FormControl('', [Validators.required]);
+ hide = true;
+ loading = false;
+ constructor(private authService: AuthService) { }
ngOnInit(): void {
}
+ login() {
+ if (this.email.invalid || this.password.invalid) {
+ return;
+ }
+ this.authService.login(this.email.value, this.password.value).subscribe();
+ }
+
}
diff --git a/src/app/services/auth.service.ts b/src/app/services/auth.service.ts
new file mode 100644
index 0000000..85bf050
--- /dev/null
+++ b/src/app/services/auth.service.ts
@@ -0,0 +1,49 @@
+import { Injectable } from '@angular/core';
+import { HttpClient } from '@angular/common/http';
+import { map } from 'rxjs/operators';
+import { environment } from '../../environments/environment';
+import { BehaviorSubject } from 'rxjs';
+
+@Injectable({
+ providedIn: 'root',
+})
+export class AuthService {
+ public loggedIn: BehaviorSubject;
+
+ constructor(private http: HttpClient) {
+ this.loggedIn = new BehaviorSubject(false);
+ this.checkIfUserIsLoggedIn();
+ }
+
+ private checkIfUserIsLoggedIn(): void {
+ this.loggedIn.next(!!this.requestToken);
+ }
+
+ public get requestToken(): string {
+ return localStorage.getItem('requestToken');
+ }
+
+ public get refreshToken(): string {
+ return localStorage.getItem('refreshToken');
+ }
+
+ login(email: string, password: string) {
+ return this.http
+ .post(`${environment.authUrl}/login`, { email, password })
+ .pipe(
+ map((response) => {
+ // store request and refresh token in local storage to keep user logged in between page refreshes
+ localStorage.setItem('requestToken', response.request_token);
+ localStorage.setItem('refreshToken', response.refresh_token);
+ this.checkIfUserIsLoggedIn();
+ })
+ );
+ }
+
+ logout() {
+ // remove token from local storage to log user out
+ localStorage.removeItem('requestToken');
+ localStorage.removeItem('refreshToken');
+ this.checkIfUserIsLoggedIn();
+ }
+}
diff --git a/src/environments/environment.ts b/src/environments/environment.ts
index 7b4f817..459188a 100644
--- a/src/environments/environment.ts
+++ b/src/environments/environment.ts
@@ -3,7 +3,9 @@
// The list of file replacements can be found in `angular.json`.
export const environment = {
- production: false
+ production: false,
+ apiUrl: "http://localhost:4000",
+ authUrl: "http://localhost:8080"
};
/*
diff --git a/src/styles.scss b/src/styles.scss
index f31f353..42b42d7 100644
--- a/src/styles.scss
+++ b/src/styles.scss
@@ -3,3 +3,17 @@
html, body { height: 100%; }
body { margin: 0; font-family: Roboto, "Helvetica Neue", sans-serif; }
+
+h1 {
+ display: block;
+ padding-bottom: 5px;
+ position: relative;
+}
+h1:before {
+ content: "";
+ position: absolute;
+ width: 5rem;
+ height: 1px;
+ bottom: 0;
+ border-bottom: 3px solid #7fc600;
+}
\ No newline at end of file