Skip to content
This repository was archived by the owner on Jul 20, 2026. It is now read-only.

Commit 58989ca

Browse files
committed
Mamanayo c'est kompliké
1 parent 67919cd commit 58989ca

12 files changed

Lines changed: 787 additions & 12 deletions

frontend/src/app/app.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
<app-navbar [userId]="currentUserId"/>
1+
<app-navbar/>
22
<router-outlet />

frontend/src/app/app.routes.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,14 @@ import { HomeComponent } from './home.component';
44
import { ShopComponent } from './shop.component';
55
import { CartComponent } from './cart.component';
66
import { AdminComponent } from './admin.component';
7+
import { LoginComponent } from './login.component';
8+
import { RegisterComponent } from './register.component';
79

810
export const routes: Routes = [
911
{ path: '', component: HomeComponent},
1012
{ path: 'account', component: AccountComponent},
13+
{ path: 'login', component: LoginComponent},
14+
{ path: 'register', component: RegisterComponent},
1115
{ path: 'shop', component: ShopComponent },
1216
{ path: 'cart', component: CartComponent },
1317
{ path: 'admin', component: AdminComponent }

frontend/src/app/app.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ export class App implements OnInit {
1818
constructor(private readonly http: HttpClient) {}
1919

2020
ngOnInit(): void {
21-
this.http.get<{ status: string; postgres: string; mongo: string }>('/api/health')
21+
this.http.get<{ status: string; postgres: string; mongo: string }>('/health')
2222
.subscribe({
2323
next: (response) => this.health.set(JSON.stringify(response)),
2424
error: () => this.error.set('health check failed')
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
<div class="auth-page">
2+
<div class="auth-container">
3+
<div class="auth-header">
4+
<span class="auth-eyebrow">Bienvenue</span>
5+
<h1 class="auth-title">Connexion</h1>
6+
<p class="auth-sub">Rejoignez l’effervescence <span class="highlight">Effes</span></p>
7+
</div>
8+
9+
<form [formGroup]="loginForm" (ngSubmit)="onSubmit()" class="auth-form">
10+
<div class="form-group">
11+
<label for="email">Email</label>
12+
<input
13+
id="email"
14+
type="email"
15+
formControlName="email"
16+
placeholder="votre@email.com"
17+
[class.is-invalid]="email?.invalid && email?.touched"
18+
/>
19+
<div class="invalid-feedback" *ngIf="email?.invalid && email?.touched">
20+
<span *ngIf="email?.errors?.['required']">L’email est requis</span>
21+
<span *ngIf="email?.errors?.['email']">Format d’email invalide</span>
22+
</div>
23+
</div>
24+
25+
<div class="form-group">
26+
<label for="password">Mot de passe</label>
27+
<input
28+
id="password"
29+
type="password"
30+
formControlName="password"
31+
placeholder="••••••••"
32+
[class.is-invalid]="password?.invalid && password?.touched"
33+
/>
34+
<div class="invalid-feedback" *ngIf="password?.invalid && password?.touched">
35+
<span *ngIf="password?.errors?.['required']">Le mot de passe est requis</span>
36+
<span *ngIf="password?.errors?.['minlength']">6 caractères minimum</span>
37+
</div>
38+
</div>
39+
40+
<!-- Erreur globale -->
41+
<div class="alert alert-danger" *ngIf="errorMessage">
42+
{{ errorMessage }}
43+
</div>
44+
45+
<button type="submit" class="btn-primary" [disabled]="loading">
46+
{{ loading ? 'Connexion...' : 'Se connecter' }}
47+
</button>
48+
49+
<p class="auth-switch">
50+
Pas encore de compte ? <a routerLink="/register">Inscrivez-vous</a>
51+
</p>
52+
</form>
53+
</div>
54+
</div>
Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
@import url('https://fonts.googleapis.com/css2?family=Bebas+Neue&family=DM+Sans:ital,wght@0,400;0,500;1,400&display=swap');
2+
3+
$fire: #E8390E;
4+
$coal: #1A1208;
5+
$ash: #2E2416;
6+
$cream: #F5ECD7;
7+
$muted: #9C8E7A;
8+
9+
.auth-page {
10+
min-height: 100vh;
11+
background: #0F0C08;
12+
display: flex;
13+
align-items: center;
14+
justify-content: center;
15+
padding: 2rem;
16+
font-family: 'DM Sans', sans-serif;
17+
}
18+
19+
.auth-container {
20+
max-width: 420px;
21+
width: 100%;
22+
background: $coal;
23+
border: 1px solid $ash;
24+
border-radius: 6px;
25+
padding: 2.5rem 2rem;
26+
}
27+
28+
.auth-header {
29+
text-align: center;
30+
margin-bottom: 2rem;
31+
}
32+
33+
.auth-eyebrow {
34+
display: block;
35+
font-size: 0.75rem;
36+
letter-spacing: 0.3em;
37+
text-transform: uppercase;
38+
color: $muted;
39+
margin-bottom: 0.25rem;
40+
}
41+
42+
.auth-title {
43+
font-family: 'Bebas Neue', sans-serif;
44+
font-size: 2.8rem;
45+
color: $cream;
46+
letter-spacing: 0.04em;
47+
margin: 0 0 0.25rem;
48+
}
49+
50+
.auth-sub {
51+
font-size: 1rem;
52+
color: $muted;
53+
font-style: italic;
54+
margin: 0;
55+
}
56+
57+
.highlight {
58+
color: $fire;
59+
}
60+
61+
.auth-form {
62+
display: flex;
63+
flex-direction: column;
64+
gap: 1.25rem;
65+
}
66+
67+
.form-group {
68+
display: flex;
69+
flex-direction: column;
70+
gap: 0.35rem;
71+
72+
label {
73+
font-size: 0.85rem;
74+
font-weight: 500;
75+
color: $cream;
76+
letter-spacing: 0.03em;
77+
}
78+
79+
input {
80+
background: lighten($coal, 5%);
81+
border: 1px solid $ash;
82+
border-radius: 4px;
83+
padding: 0.7rem 1rem;
84+
font-size: 1rem;
85+
font-family: 'DM Sans', sans-serif;
86+
color: $cream;
87+
transition: border 0.2s, box-shadow 0.2s;
88+
89+
&::placeholder {
90+
color: $muted;
91+
opacity: 0.6;
92+
}
93+
94+
&:focus {
95+
outline: none;
96+
border-color: $fire;
97+
box-shadow: 0 0 0 2px rgba($fire, 0.25);
98+
}
99+
100+
&.is-invalid {
101+
border-color: $fire;
102+
}
103+
}
104+
105+
.invalid-feedback {
106+
font-size: 0.8rem;
107+
color: $fire;
108+
margin-top: 0.2rem;
109+
}
110+
}
111+
112+
.alert {
113+
padding: 0.6rem 1rem;
114+
border-radius: 4px;
115+
font-size: 0.9rem;
116+
background: rgba($fire, 0.12);
117+
border-left: 3px solid $fire;
118+
color: $cream;
119+
}
120+
121+
.btn-primary {
122+
background: $fire;
123+
color: $cream;
124+
border: none;
125+
border-radius: 4px;
126+
padding: 0.8rem;
127+
font-size: 0.95rem;
128+
font-weight: 500;
129+
letter-spacing: 0.05em;
130+
text-transform: uppercase;
131+
cursor: pointer;
132+
transition: background 0.2s, transform 0.15s;
133+
134+
&:hover:not(:disabled) {
135+
background: darken($fire, 8%);
136+
transform: translateY(-2px);
137+
}
138+
139+
&:disabled {
140+
opacity: 0.6;
141+
cursor: not-allowed;
142+
}
143+
}
144+
145+
.auth-switch {
146+
text-align: center;
147+
font-size: 0.9rem;
148+
color: $muted;
149+
margin: 0.5rem 0 0;
150+
151+
a {
152+
color: $fire;
153+
text-decoration: none;
154+
font-weight: 500;
155+
&:hover {
156+
text-decoration: underline;
157+
}
158+
}
159+
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import { Component } from '@angular/core';
2+
import { ReactiveFormsModule , FormGroup, Validators, FormBuilder } from '@angular/forms';
3+
import { Router, RouterLink } from '@angular/router';
4+
import { AccountService } from './services/account.service';
5+
import { CommonModule } from '@angular/common';
6+
7+
@Component({
8+
selector: 'app-login',
9+
standalone: true,
10+
templateUrl: './login.component.html',
11+
styleUrls: ['./login.component.scss'],
12+
imports : [
13+
CommonModule,
14+
ReactiveFormsModule,
15+
RouterLink,
16+
]
17+
})
18+
export class LoginComponent {
19+
loginForm: FormGroup;
20+
loading = false;
21+
errorMessage = '';
22+
23+
constructor(
24+
private fb: FormBuilder,
25+
private accountService: AccountService,
26+
private router: Router
27+
) {
28+
this.loginForm = this.fb.group({
29+
email: ['', [Validators.required, Validators.email]],
30+
password: ['', [Validators.required, Validators.minLength(6)]]
31+
});
32+
}
33+
34+
onSubmit() {
35+
if (this.loginForm.invalid) {
36+
this.loginForm.markAllAsTouched();
37+
return;
38+
}
39+
40+
this.loading = true;
41+
this.errorMessage = '';
42+
const { email, password } = this.loginForm.value;
43+
44+
this.accountService.login(email, password).subscribe({
45+
next: () => {
46+
this.loading = false;
47+
this.router.navigate(['/']); // redirige vers la page d'accueil
48+
},
49+
error: (err) => {
50+
this.loading = false;
51+
this.errorMessage = err.error?.message || 'Erreur de connexion, vérifiez vos identifiants.';
52+
}
53+
});
54+
}
55+
56+
// Getters pour les erreurs
57+
get email() { return this.loginForm.get('email'); }
58+
get password() { return this.loginForm.get('password'); }
59+
}

frontend/src/app/partials/navbar/navbar.component.html

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,19 @@
99
</button>
1010

1111
<ul class="navbar-links" [class.open]="menuOpen">
12-
<li><a routerLink="/" routerLinkActive="active" [routerLinkActiveOptions]="{ exact: true }">Home</a></li>
13-
<li><a routerLink="/shop" routerLinkActive="active">Order</a></li>
14-
@if (userId) {
15-
<li><a routerLink="/cart" routerLinkActive="active">Cart</a></li>
16-
<li><a routerLink="/account" routerLinkActive="active">My account</a></li>
12+
<li><a routerLink="/" routerLinkActive="active" [routerLinkActiveOptions]="{ exact: true }">Accueil</a></li>
13+
14+
@if (accountService.isLoggedIn()) {
15+
<li><a routerLink="/shop" routerLinkActive="active">Commander</a></li>
16+
<li><a routerLink="/cart" routerLinkActive="active">Panier</a></li>
17+
<li><a routerLink="/account" routerLinkActive="active">Mon Compte</a></li>
1718
<li><a routerLink="/invoices" routerLinkActive="active">Invoices</a></li>
18-
<li class="signout"><a routerLink="/sign-out">Sign out</a></li>
19+
<li class="signout">
20+
<a href="javascript:void(0)" (click)="onLogout()">Déconnexion</a>
21+
</li>
1922
} @else {
20-
<li><a routerLink="/sign-in" routerLinkActive="active">Sign in</a></li>
21-
<li class="cta"><a routerLink="/sign-up">Sign up</a></li>
23+
<li><a routerLink="/login" routerLinkActive="active">Connexion</a></li>
24+
<li class="cta"><a routerLink="/register">Inscription</a></li>
2225
}
2326
</ul>
2427
</div>
Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
import { Component, Input } from '@angular/core';
1+
import { Component } from '@angular/core';
22
import { RouterLink, RouterLinkActive } from '@angular/router';
33
import { CommonModule } from '@angular/common';
4+
import { AccountService } from '../../services/account.service';
45

56
@Component({
67
selector: 'app-navbar',
@@ -10,6 +11,16 @@ import { CommonModule } from '@angular/common';
1011
styleUrl: './navbar.component.scss',
1112
})
1213
export class NavbarComponent {
13-
@Input() userId: string | null = null;
1414
menuOpen = false;
15+
16+
constructor(public accountService: AccountService) {}
17+
18+
onLogout(): void {
19+
this.accountService.logout();
20+
this.menuOpen = false;
21+
}
22+
23+
get isLoggedIn(): boolean {
24+
return this.accountService.isLoggedIn();
25+
}
1526
}

0 commit comments

Comments
 (0)