From 95d5308934f34f733fd52998345c2173bb1c3471 Mon Sep 17 00:00:00 2001 From: Florian THIERRY Date: Thu, 6 Jun 2024 11:05:02 +0200 Subject: [PATCH] Re-design of login page. --- frontend/src/app/app.routes.ts | 4 ++ .../publications/publication.rest-service.ts | 4 ++ .../src/app/pages/login/login.component.html | 9 ++- .../src/app/pages/login/login.component.scss | 62 ++++++++++++++--- .../src/app/pages/login/login.component.ts | 4 +- .../publication/publication.component.html | 29 ++++++++ .../publication/publication.component.scss | 66 +++++++++++++++++++ .../publication/publication.component.ts | 55 ++++++++++++++++ 8 files changed, 221 insertions(+), 12 deletions(-) create mode 100644 frontend/src/app/pages/publication/publication.component.html create mode 100644 frontend/src/app/pages/publication/publication.component.scss create mode 100644 frontend/src/app/pages/publication/publication.component.ts diff --git a/frontend/src/app/app.routes.ts b/frontend/src/app/app.routes.ts index 18fa3f8..40a172c 100644 --- a/frontend/src/app/app.routes.ts +++ b/frontend/src/app/app.routes.ts @@ -9,6 +9,10 @@ export const routes: Routes = [ path: 'disconnect', loadComponent: () => import('./pages/disconnection/disconnection.component').then(module => module.DisconnectionComponent) }, + { + path: 'publications/:publicationId', + loadComponent: () => import('./pages/publication/publication.component').then(module => module.PublicationComponent) + }, { path: '**', loadComponent: () => import('./pages/home/home.component').then(module => module.HomeComponent) diff --git a/frontend/src/app/core/rest-services/publications/publication.rest-service.ts b/frontend/src/app/core/rest-services/publications/publication.rest-service.ts index d16a9cf..a1ef724 100644 --- a/frontend/src/app/core/rest-services/publications/publication.rest-service.ts +++ b/frontend/src/app/core/rest-services/publications/publication.rest-service.ts @@ -12,4 +12,8 @@ export class PublicationRestService { getLatest(): Promise { return lastValueFrom(this.httpClient.get('/api/publications/latest')); } + + getById(publicationId: string): Promise { + return lastValueFrom(this.httpClient.get(`/api/publications/${publicationId}`)); + } } diff --git a/frontend/src/app/pages/login/login.component.html b/frontend/src/app/pages/login/login.component.html index 45e31f5..6d0a4a7 100644 --- a/frontend/src/app/pages/login/login.component.html +++ b/frontend/src/app/pages/login/login.component.html @@ -1,18 +1,23 @@

Login

+ person - +
+ lock - +
\ No newline at end of file diff --git a/frontend/src/app/pages/login/login.component.scss b/frontend/src/app/pages/login/login.component.scss index 2592ed7..4c630e0 100644 --- a/frontend/src/app/pages/login/login.component.scss +++ b/frontend/src/app/pages/login/login.component.scss @@ -3,34 +3,78 @@ flex-direction: column; justify-content: center; align-items: center; + padding: 1em; form { - min-width: 40em; - max-width: 90%; + width: 80%; + max-width: 20em; display: flex; flex-direction: column; justify-content: center; - gap: .5em; + gap: 1em; + box-shadow: 0 2px 5px 0 rgba(0,0,0,.16),0 2px 10px 0 rgba(0,0,0,.12); + border-radius: .5em; + padding: 1em 1.5em; + + h1 { + margin: 0; + } div { display: flex; - gap: .5em; + flex-direction: column; + position: relative; + gap: .1em; + + mat-icon { + position: absolute; + top: 1.2em; + left: .5em; + color: #777; + } &.actions { - justify-content: end; + flex-direction: row; + justify-content: space-between; + align-items: center; + + a { + color: #3f51b5; + text-decoration: none; + } button { - width: 10em; - height: 2em; + padding: .8em 1.2em; + border-radius: 10em; + border: none; + background-color: #3f51b5; + color: white; + transition: background-color .2s ease-in-out; + + &:hover { + background-color: #5b6ed8; + cursor: pointer; + } } } label { - flex: 1 30%; + flex: 1; + font-style: italic; + padding-left: 1em; + color: #777; + + .required { + color: red; + } } input { - flex: 1 70%; + flex: 1; + background-color: #eeeeee; + border: none; + border-radius: 10em; + padding: 1em 1em 1em 3em; } } } diff --git a/frontend/src/app/pages/login/login.component.ts b/frontend/src/app/pages/login/login.component.ts index 7f6fcfb..3fe8a5f 100644 --- a/frontend/src/app/pages/login/login.component.ts +++ b/frontend/src/app/pages/login/login.component.ts @@ -3,13 +3,15 @@ import { FormBuilder, FormControl, FormGroup, ReactiveFormsModule, Validators } import { MatSnackBarModule } from '@angular/material/snack-bar'; import { Subscription, debounceTime, map } from 'rxjs'; import { LoginService } from './login.service'; +import { MatIconModule } from '@angular/material/icon'; +import { RouterModule } from '@angular/router'; @Component({ selector: 'app-login', standalone: true, templateUrl: './login.component.html', styleUrl: './login.component.scss', - imports: [ ReactiveFormsModule ], + imports: [ReactiveFormsModule, MatIconModule, RouterModule], providers: [LoginService, MatSnackBarModule] }) export class LoginComponent implements OnInit, OnDestroy { diff --git a/frontend/src/app/pages/publication/publication.component.html b/frontend/src/app/pages/publication/publication.component.html new file mode 100644 index 0000000..36d1f1c --- /dev/null +++ b/frontend/src/app/pages/publication/publication.component.html @@ -0,0 +1,29 @@ + + + + + + +
+ +
+

{{ publication.title }}

+

{{ publication.description }}

+
+
+
+ + Publication posted by {{ publication.author.name }} + + ({{ publication.creationDate | date: 'short' : 'fr-FR' }}) + +
+
+
+ + +
+

Publication failed to load...

+
+
+
\ No newline at end of file diff --git a/frontend/src/app/pages/publication/publication.component.scss b/frontend/src/app/pages/publication/publication.component.scss new file mode 100644 index 0000000..a624e14 --- /dev/null +++ b/frontend/src/app/pages/publication/publication.component.scss @@ -0,0 +1,66 @@ +$cardBorderRadius: .5em; + +:host { + display: flex; + justify-content: center; + + .card { + display: flex; + flex-direction: column; + margin: 1em; + max-width: 80em; + border-radius: .5em; + box-shadow: 0 2px 5px 0 rgba(0,0,0,.16),0 2px 10px 0 rgba(0,0,0,.12); + + img { + height: 25em; + object-fit: cover; + border-radius: $cardBorderRadius $cardBorderRadius 0 0; + } + + header { + padding: 2em; + + h1 { + font-size: 2em; + margin-bottom: .5em; + } + + h2 { + font-size: 1.2em; + line-height: 1.6em; + margin: 0; + font-weight: 400; + } + } + + main { + border-top: 1px solid #dddddd; + margin: 0 2em 2em 2em; + padding-top: 2em; + } + + footer { + display: flex; + flex-direction: row; + align-items: center; + background-color: #f0f0f0; + border-radius: 0 0 $cardBorderRadius $cardBorderRadius; + padding: 1em 2em; + gap: 1em; + + img { + $imageSize: 4em; + border-radius: 10em; + width: $imageSize; + height: $imageSize; + object-fit: cover; + } + + .publication-date { + font-style: italic; + color: #bdbdbd; + } + } + } +} \ No newline at end of file diff --git a/frontend/src/app/pages/publication/publication.component.ts b/frontend/src/app/pages/publication/publication.component.ts new file mode 100644 index 0000000..3b54fc4 --- /dev/null +++ b/frontend/src/app/pages/publication/publication.component.ts @@ -0,0 +1,55 @@ +import { Component, OnDestroy, OnInit, inject } from '@angular/core'; +import { PublicationRestService } from '../../core/rest-services/publications/publication.rest-service'; +import { ActivatedRoute } from '@angular/router'; +import { Subscription } from 'rxjs'; +import { Publication } from '../../core/rest-services/publications/model/publication'; +import { MatSnackBar } from '@angular/material/snack-bar'; +import { CommonModule } from '@angular/common'; +import { MatProgressSpinner } from '@angular/material/progress-spinner'; +import { MatTooltip } from '@angular/material/tooltip'; + +@Component({ + selector: 'app-publication', + standalone: true, + imports: [CommonModule, MatProgressSpinner, MatTooltip], + templateUrl: './publication.component.html', + styleUrl: './publication.component.scss' +}) +export class PublicationComponent implements OnInit, OnDestroy { + private activatedRoute = inject(ActivatedRoute); + private publicationRestService = inject(PublicationRestService); + private paramMapSubscription?: Subscription; + private snackBar = inject(MatSnackBar); + isLoading: boolean = false; + publication?: Publication; + + ngOnInit(): void { + this.paramMapSubscription = this.activatedRoute + .paramMap + .subscribe(params => { + const publicationId = params.get('publicationId'); + + if (publicationId) { + this.isLoading = true; + + this.publicationRestService.getById(publicationId) + .then(publication => { + this.publication = publication; + }) + .catch(error => { + this.snackBar.open('An error occurred while loading publication...', 'Close', { duration: 5000 }); + console.error('An error occurred while loading publication...', error); + }) + .finally(() => { + this.isLoading = false; + }); + } + }); + + // this.publicationRestService.getById() + } + + ngOnDestroy(): void { + this.paramMapSubscription?.unsubscribe(); + } +}