auth front
This commit is contained in:
@@ -141,3 +141,42 @@ export const checkAuth = (req, res) => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const getprofile = async (req, res) => {
|
||||||
|
const token = req.cookies.jwt;
|
||||||
|
let conn;
|
||||||
|
try {
|
||||||
|
conn = await pool.getConnection();
|
||||||
|
|
||||||
|
req.user = jwt.verify(token, process.env.JWT_SECRET);
|
||||||
|
|
||||||
|
// Requête pour récupérer les informations de l'utilisateur sauf le mot de passe
|
||||||
|
const query = `
|
||||||
|
SELECT id, email, firstname, lastname, updated_at, created_at
|
||||||
|
FROM users
|
||||||
|
WHERE id = ?`;
|
||||||
|
const results = await conn.query(query, [req.user.id]);
|
||||||
|
|
||||||
|
// Vérifie si l'utilisateur existe
|
||||||
|
if (results.length === 0) {
|
||||||
|
return res.status(404).json({
|
||||||
|
message: 'Utilisateur non trouvé.',
|
||||||
|
status: false
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return res.status(200).json({
|
||||||
|
results
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Erreur lors de la récupération de l\'utilisateur :', error);
|
||||||
|
return res.status(500).json({
|
||||||
|
message: 'Erreur lors de la récupération de l\'utilisateur.',
|
||||||
|
status: false
|
||||||
|
});
|
||||||
|
} finally {
|
||||||
|
if (conn) {
|
||||||
|
await conn.release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import {
|
|||||||
register,
|
register,
|
||||||
login,
|
login,
|
||||||
checkAuth,
|
checkAuth,
|
||||||
logout,
|
logout, getprofile,
|
||||||
} from "../controllers/authController.js";
|
} from "../controllers/authController.js";
|
||||||
import {verifyToken} from "../middleware/tokenJWTMiddleware.js";
|
import {verifyToken} from "../middleware/tokenJWTMiddleware.js";
|
||||||
import multer from "multer";
|
import multer from "multer";
|
||||||
@@ -29,7 +29,7 @@ const generateFileName = (originalName) => {
|
|||||||
};
|
};
|
||||||
const storage = multer.diskStorage({
|
const storage = multer.diskStorage({
|
||||||
destination: function (req, file, cb) {
|
destination: function (req, file, cb) {
|
||||||
cb(null, 'uploads/'); // Stockage des fichiers dans le dossier uploads/
|
cb(null, 'uploads/');
|
||||||
},
|
},
|
||||||
filename: function (req, file, cb) {
|
filename: function (req, file, cb) {
|
||||||
cb(null, generateFileName(file.originalname));
|
cb(null, generateFileName(file.originalname));
|
||||||
@@ -48,6 +48,7 @@ router.post('/upload', verifyToken, upload.single('file'), (req, res) => {
|
|||||||
router.post('/auth/register', register);
|
router.post('/auth/register', register);
|
||||||
router.post('/auth/login', login);
|
router.post('/auth/login', login);
|
||||||
router.post('/auth/logout', logout);
|
router.post('/auth/logout', logout);
|
||||||
|
router.get('/auth/user', verifyToken, getprofile);
|
||||||
router.get('/auth/check-auth', verifyToken, checkAuth);
|
router.get('/auth/check-auth', verifyToken, checkAuth);
|
||||||
|
|
||||||
export default router;
|
export default router;
|
||||||
|
|||||||
@@ -63,7 +63,6 @@ const startServer = async () => {
|
|||||||
console.log(`🚀 Lancement de l'API en cours... 🔧`);
|
console.log(`🚀 Lancement de l'API en cours... 🔧`);
|
||||||
await testDatabaseConnection();
|
await testDatabaseConnection();
|
||||||
app.listen(process.env.PORT, () => {
|
app.listen(process.env.PORT, () => {
|
||||||
console.log(`📢 NODE_ENV = ${process.env.NODE_ENV} 🌍`);
|
|
||||||
console.log(`📢 Chargement du fichier : ${envFile} 📄`);
|
console.log(`📢 Chargement du fichier : ${envFile} 📄`);
|
||||||
console.log(`🚀 API démarrée sur le port ${process.env.PORT} 🎯`);
|
console.log(`🚀 API démarrée sur le port ${process.env.PORT} 🎯`);
|
||||||
console.log(`🌍 Allowed Origin : ${process.env.ALLOWED_ORIGIN} 🔗`);
|
console.log(`🌍 Allowed Origin : ${process.env.ALLOWED_ORIGIN} 🔗`);
|
||||||
|
|||||||
16
package-lock.json
generated
16
package-lock.json
generated
@@ -8,6 +8,7 @@
|
|||||||
"name": "eni-angular",
|
"name": "eni-angular",
|
||||||
"version": "0.0.0",
|
"version": "0.0.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@angular/animations": "^19.2.1",
|
||||||
"@angular/common": "^19.2.0",
|
"@angular/common": "^19.2.0",
|
||||||
"@angular/compiler": "^19.2.0",
|
"@angular/compiler": "^19.2.0",
|
||||||
"@angular/core": "^19.2.0",
|
"@angular/core": "^19.2.0",
|
||||||
@@ -350,6 +351,21 @@
|
|||||||
"tslib": "^2.1.0"
|
"tslib": "^2.1.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@angular/animations": {
|
||||||
|
"version": "19.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@angular/animations/-/animations-19.2.1.tgz",
|
||||||
|
"integrity": "sha512-I67XYXBic9bM+yfce6Dqa950TsrEWB6uwSB2l6eIg3Byp48yJxQYbyjvjDbMXPieU2Bzo8FYVSD+lc8cF4+L6A==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"tslib": "^2.3.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": "^18.19.1 || ^20.11.1 || >=22.0.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@angular/core": "19.2.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@angular/build": {
|
"node_modules/@angular/build": {
|
||||||
"version": "19.2.1",
|
"version": "19.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/@angular/build/-/build-19.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/@angular/build/-/build-19.2.1.tgz",
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
},
|
},
|
||||||
"private": true,
|
"private": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@angular/animations": "^19.2.1",
|
||||||
"@angular/common": "^19.2.0",
|
"@angular/common": "^19.2.0",
|
||||||
"@angular/compiler": "^19.2.0",
|
"@angular/compiler": "^19.2.0",
|
||||||
"@angular/core": "^19.2.0",
|
"@angular/core": "^19.2.0",
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
</h5>
|
</h5>
|
||||||
</div>
|
</div>
|
||||||
<nav class="flex min-w-[240px] flex-col gap-1 p-2 font-sans text-base font-normal text-blue-gray-700">
|
<nav class="flex min-w-[240px] flex-col gap-1 p-2 font-sans text-base font-normal text-blue-gray-700">
|
||||||
<div class="relative block w-full">
|
<div *ngIf="user.id !== 0" class="relative block w-full">
|
||||||
<div role="button"
|
<div role="button"
|
||||||
class="flex items-center w-full p-0 leading-tight transition-all rounded-lg outline-none bg-blue-gray-50/50 text-start text-blue-gray-700 hover:bg-blue-gray-50 hover:bg-opacity-80 hover:text-blue-gray-900 focus:bg-blue-gray-50 focus:bg-opacity-80 focus:text-blue-gray-900 active:bg-blue-gray-50 active:bg-opacity-80 active:text-blue-gray-900">
|
class="flex items-center w-full p-0 leading-tight transition-all rounded-lg outline-none bg-blue-gray-50/50 text-start text-blue-gray-700 hover:bg-blue-gray-50 hover:bg-opacity-80 hover:text-blue-gray-900 focus:bg-blue-gray-50 focus:bg-opacity-80 focus:text-blue-gray-900 active:bg-blue-gray-50 active:bg-opacity-80 active:text-blue-gray-900">
|
||||||
<button type="button"
|
<button type="button"
|
||||||
@@ -61,7 +61,19 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div role="button"
|
<div *ngIf="user.id === 0" routerLink="/login" role="button"
|
||||||
|
class="flex cursor-pointer items-center w-full p-3 leading-tight transition-all rounded-lg outline-none text-start hover:bg-blue-gray-50 hover:bg-opacity-80 hover:text-blue-gray-900 focus:bg-blue-gray-50 focus:bg-opacity-80 focus:text-blue-gray-900 active:bg-blue-gray-50 active:bg-opacity-80 active:text-blue-gray-900">
|
||||||
|
<div class="grid mr-4 place-items-center">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"
|
||||||
|
class="w-5 h-5">
|
||||||
|
<path fill-rule="evenodd"
|
||||||
|
d="M18.685 19.097A9.723 9.723 0 0021.75 12c0-5.385-4.365-9.75-9.75-9.75S2.25 6.615 2.25 12a9.723 9.723 0 003.065 7.097A9.716 9.716 0 0012 21.75a9.716 9.716 0 006.685-2.653zm-12.54-1.285A7.486 7.486 0 0112 15a7.486 7.486 0 015.855 2.812A8.224 8.224 0 0112 20.25a8.224 8.224 0 01-5.855-2.438zM15.75 9a3.75 3.75 0 11-7.5 0 3.75 3.75 0 017.5 0z"
|
||||||
|
clip-rule="evenodd"></path>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
Connexion/Inscription
|
||||||
|
</div>
|
||||||
|
<div *ngIf="user.id !== 0" role="button"
|
||||||
class="flex items-center w-full p-3 leading-tight transition-all rounded-lg outline-none text-start hover:bg-blue-gray-50 hover:bg-opacity-80 hover:text-blue-gray-900 focus:bg-blue-gray-50 focus:bg-opacity-80 focus:text-blue-gray-900 active:bg-blue-gray-50 active:bg-opacity-80 active:text-blue-gray-900">
|
class="flex items-center w-full p-3 leading-tight transition-all rounded-lg outline-none text-start hover:bg-blue-gray-50 hover:bg-opacity-80 hover:text-blue-gray-900 focus:bg-blue-gray-50 focus:bg-opacity-80 focus:text-blue-gray-900 active:bg-blue-gray-50 active:bg-opacity-80 active:text-blue-gray-900">
|
||||||
<div class="grid mr-4 place-items-center">
|
<div class="grid mr-4 place-items-center">
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"
|
||||||
@@ -73,19 +85,7 @@
|
|||||||
</div>
|
</div>
|
||||||
Profile
|
Profile
|
||||||
</div>
|
</div>
|
||||||
<div role="button"
|
<div *ngIf="user.id !== 0" role="button"
|
||||||
class="flex items-center w-full p-3 leading-tight transition-all rounded-lg outline-none text-start hover:bg-blue-gray-50 hover:bg-opacity-80 hover:text-blue-gray-900 focus:bg-blue-gray-50 focus:bg-opacity-80 focus:text-blue-gray-900 active:bg-blue-gray-50 active:bg-opacity-80 active:text-blue-gray-900">
|
|
||||||
<div class="grid mr-4 place-items-center">
|
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"
|
|
||||||
class="w-5 h-5">
|
|
||||||
<path fill-rule="evenodd"
|
|
||||||
d="M11.078 2.25c-.917 0-1.699.663-1.85 1.567L9.05 4.889c-.02.12-.115.26-.297.348a7.493 7.493 0 00-.986.57c-.166.115-.334.126-.45.083L6.3 5.508a1.875 1.875 0 00-2.282.819l-.922 1.597a1.875 1.875 0 00.432 2.385l.84.692c.095.078.17.229.154.43a7.598 7.598 0 000 1.139c.015.2-.059.352-.153.43l-.841.692a1.875 1.875 0 00-.432 2.385l.922 1.597a1.875 1.875 0 002.282.818l1.019-.382c.115-.043.283-.031.45.082.312.214.641.405.985.57.182.088.277.228.297.35l.178 1.071c.151.904.933 1.567 1.85 1.567h1.844c.916 0 1.699-.663 1.85-1.567l.178-1.072c.02-.12.114-.26.297-.349.344-.165.673-.356.985-.57.167-.114.335-.125.45-.082l1.02.382a1.875 1.875 0 002.28-.819l.923-1.597a1.875 1.875 0 00-.432-2.385l-.84-.692c-.095-.078-.17-.229-.154-.43a7.614 7.614 0 000-1.139c-.016-.2.059-.352.153-.43l.84-.692c.708-.582.891-1.59.433-2.385l-.922-1.597a1.875 1.875 0 00-2.282-.818l-1.02.382c-.114.043-.282.031-.449-.083a7.49 7.49 0 00-.985-.57c-.183-.087-.277-.227-.297-.348l-.179-1.072a1.875 1.875 0 00-1.85-1.567h-1.843zM12 15.75a3.75 3.75 0 100-7.5 3.75 3.75 0 000 7.5z"
|
|
||||||
clip-rule="evenodd"></path>
|
|
||||||
</svg>
|
|
||||||
</div>
|
|
||||||
Paramètre
|
|
||||||
</div>
|
|
||||||
<div role="button"
|
|
||||||
class="flex items-center w-full p-3 leading-tight transition-all rounded-lg outline-none text-start hover:bg-blue-gray-50 hover:bg-opacity-80 hover:text-blue-gray-900 focus:bg-blue-gray-50 focus:bg-opacity-80 focus:text-blue-gray-900 active:bg-blue-gray-50 active:bg-opacity-80 active:text-blue-gray-900">
|
class="flex items-center w-full p-3 leading-tight transition-all rounded-lg outline-none text-start hover:bg-blue-gray-50 hover:bg-opacity-80 hover:text-blue-gray-900 focus:bg-blue-gray-50 focus:bg-opacity-80 focus:text-blue-gray-900 active:bg-blue-gray-50 active:bg-opacity-80 active:text-blue-gray-900">
|
||||||
<div class="grid mr-4 place-items-center">
|
<div class="grid mr-4 place-items-center">
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"
|
||||||
|
|||||||
@@ -1,11 +1,40 @@
|
|||||||
import { Component } from '@angular/core';
|
import {Component, OnInit} from '@angular/core';
|
||||||
|
import {AuthService} from '../../_services/auth.service';
|
||||||
|
import {Users} from '../../_models/users';
|
||||||
|
import {catchError, of} from 'rxjs';
|
||||||
|
import {NgIf} from '@angular/common';
|
||||||
|
import {RouterLink} from '@angular/router';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-sidbar',
|
selector: 'app-sidbar',
|
||||||
imports: [],
|
imports: [
|
||||||
|
NgIf,
|
||||||
|
RouterLink
|
||||||
|
],
|
||||||
templateUrl: './sidbar.component.html',
|
templateUrl: './sidbar.component.html',
|
||||||
styleUrl: './sidbar.component.css'
|
styleUrl: './sidbar.component.css'
|
||||||
})
|
})
|
||||||
export class SidbarComponent {
|
export class SidbarComponent implements OnInit {
|
||||||
|
|
||||||
|
user: Users = { id: 0, email: '', firstname: '', lastname: '', password_hash: '', updated_at: new Date(), created_at: new Date() };
|
||||||
|
|
||||||
|
constructor(private authService: AuthService) {
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit(): void {
|
||||||
|
this.loadUsers();
|
||||||
|
}
|
||||||
|
|
||||||
|
loadUsers(): void {
|
||||||
|
this.authService.getProfil().pipe(
|
||||||
|
catchError(error => {
|
||||||
|
return of(null);
|
||||||
|
})
|
||||||
|
).subscribe(users => {
|
||||||
|
if (users) {
|
||||||
|
this.user = users;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
21
src/app/_guards/auth.guard.ts
Normal file
21
src/app/_guards/auth.guard.ts
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
import {CanActivate, Router} from '@angular/router';
|
||||||
|
import {Injectable} from '@angular/core';
|
||||||
|
import {AuthService} from '../_services/auth.service';
|
||||||
|
import {Observable, tap} from 'rxjs';
|
||||||
|
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root'
|
||||||
|
})
|
||||||
|
export class authGuard implements CanActivate {
|
||||||
|
constructor(private authService: AuthService, private router: Router) {}
|
||||||
|
|
||||||
|
canActivate(): Observable<boolean> {
|
||||||
|
return this.authService.isAuthenticated().pipe(
|
||||||
|
tap(status => {
|
||||||
|
if (!status) {
|
||||||
|
this.router.navigate(['/login']);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
22
src/app/_guards/no-auth.guard.ts
Normal file
22
src/app/_guards/no-auth.guard.ts
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { CanActivate, Router } from '@angular/router';
|
||||||
|
import { AuthService } from '../_services/auth.service';
|
||||||
|
import {map, Observable, tap} from 'rxjs';
|
||||||
|
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root'
|
||||||
|
})
|
||||||
|
export class noAuthGuard implements CanActivate {
|
||||||
|
constructor(private authService: AuthService, private router: Router) {}
|
||||||
|
|
||||||
|
canActivate(): Observable<boolean> {
|
||||||
|
return this.authService.isAuthenticated().pipe(
|
||||||
|
tap(status => {
|
||||||
|
if (status) {
|
||||||
|
this.router.navigate(['/profile']);
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
map(status => !status)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
9
src/app/_models/users.ts
Normal file
9
src/app/_models/users.ts
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
export interface Users {
|
||||||
|
id: number;
|
||||||
|
email: string;
|
||||||
|
firstname: string;
|
||||||
|
lastname: string;
|
||||||
|
password_hash: string;
|
||||||
|
updated_at: Date;
|
||||||
|
created_at: Date;
|
||||||
|
}
|
||||||
72
src/app/_services/auth.service.ts
Normal file
72
src/app/_services/auth.service.ts
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import {HttpClient, HttpHeaders} from '@angular/common/http';
|
||||||
|
import {Users} from '../_models/users';
|
||||||
|
import {catchError, map, Observable, of} from 'rxjs';
|
||||||
|
import {environment} from '../../environments/environment';
|
||||||
|
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root'
|
||||||
|
})
|
||||||
|
export class AuthService {
|
||||||
|
|
||||||
|
constructor(private http: HttpClient) { }
|
||||||
|
|
||||||
|
register(user: Users): Observable<any> {
|
||||||
|
const headers = new HttpHeaders({
|
||||||
|
'Authorization': environment.apikey,
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
});
|
||||||
|
return this.http.post<any>(environment.apiurl + '/auth/register', user, { headers });
|
||||||
|
}
|
||||||
|
|
||||||
|
login(user: { email: string; password: string }) {
|
||||||
|
const headers = new HttpHeaders({
|
||||||
|
'Authorization': environment.apikey,
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
});
|
||||||
|
return this.http.post(environment.apiurl + '/auth/login', user, {
|
||||||
|
headers,
|
||||||
|
withCredentials: true
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
logout(): Observable<any> {
|
||||||
|
const headers = new HttpHeaders({
|
||||||
|
'Authorization': environment.apikey,
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
});
|
||||||
|
return this.http.post(
|
||||||
|
environment.apiurl + '/auth/logout', {}, {
|
||||||
|
headers,
|
||||||
|
withCredentials: true
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
isAuthenticated(): Observable<boolean> {
|
||||||
|
const headers = new HttpHeaders({
|
||||||
|
'Authorization': environment.apikey,
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
});
|
||||||
|
return this.http.get(environment.apiurl + '/auth/check-auth', {
|
||||||
|
headers,
|
||||||
|
withCredentials: true
|
||||||
|
}).pipe(
|
||||||
|
map((response: any) => {
|
||||||
|
return response.status;
|
||||||
|
}),
|
||||||
|
catchError(() => {
|
||||||
|
return of(false);
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
getProfil(): Observable<Users> {
|
||||||
|
const headers = new HttpHeaders({
|
||||||
|
'Authorization': environment.apikey,
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
});
|
||||||
|
return this.http.get<Users>(environment.apiurl + '/auth/user', { headers, withCredentials: true });
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -4,6 +4,7 @@ import {SidbarComponent} from './_component/sidbar/sidbar.component';
|
|||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-root',
|
selector: 'app-root',
|
||||||
|
standalone: true,
|
||||||
imports: [RouterOutlet, SidbarComponent],
|
imports: [RouterOutlet, SidbarComponent],
|
||||||
templateUrl: './app.component.html',
|
templateUrl: './app.component.html',
|
||||||
styleUrl: './app.component.css'
|
styleUrl: './app.component.css'
|
||||||
|
|||||||
@@ -1,8 +1,27 @@
|
|||||||
import { ApplicationConfig, provideZoneChangeDetection } from '@angular/core';
|
import { ApplicationConfig, provideZoneChangeDetection } from '@angular/core';
|
||||||
import { provideRouter } from '@angular/router';
|
import {
|
||||||
|
provideRouter,
|
||||||
|
withEnabledBlockingInitialNavigation,
|
||||||
|
withInMemoryScrolling,
|
||||||
|
withViewTransitions
|
||||||
|
} from '@angular/router';
|
||||||
|
|
||||||
import { routes } from './app.routes';
|
import { routes } from './app.routes';
|
||||||
|
import {provideAnimations} from '@angular/platform-browser/animations';
|
||||||
|
import {provideHttpClient} from '@angular/common/http';
|
||||||
|
|
||||||
export const appConfig: ApplicationConfig = {
|
export const appConfig: ApplicationConfig = {
|
||||||
providers: [provideZoneChangeDetection({ eventCoalescing: true }), provideRouter(routes)]
|
providers: [
|
||||||
|
provideAnimations(),
|
||||||
|
provideRouter(routes,
|
||||||
|
withViewTransitions(),
|
||||||
|
withEnabledBlockingInitialNavigation(),
|
||||||
|
withInMemoryScrolling({
|
||||||
|
scrollPositionRestoration: 'enabled',
|
||||||
|
anchorScrolling: 'enabled'
|
||||||
|
})
|
||||||
|
),
|
||||||
|
provideZoneChangeDetection({ eventCoalescing: true }),
|
||||||
|
provideHttpClient(),
|
||||||
|
],
|
||||||
};
|
};
|
||||||
|
|||||||
0
src/app/public/pages/login/login.component.css
Normal file
0
src/app/public/pages/login/login.component.css
Normal file
32
src/app/public/pages/login/login.component.html
Normal file
32
src/app/public/pages/login/login.component.html
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
<section class="bg-gray-100 flex items-center justify-center min-h-screen p-4">
|
||||||
|
<div class="bg-white rounded-lg shadow-lg p-8 max-w-md w-full">
|
||||||
|
<div class="text-center mb-8">
|
||||||
|
<h1 class="text-2xl font-bold text-gray-800">Connexion</h1>
|
||||||
|
<p class="text-gray-600 mt-2">Entrez vos identifiants pour vous connecter</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<form>
|
||||||
|
<div class="mb-6">
|
||||||
|
<label for="email" class="block text-gray-700 text-sm font-medium mb-2">Email</label>
|
||||||
|
<input type="email" id="email" name="email" class="w-full px-4 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent" placeholder="votre@email.com" required>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mb-6">
|
||||||
|
<div class="flex justify-between items-center mb-2">
|
||||||
|
<label for="password" class="block text-gray-700 text-sm font-medium">Mot de passe</label>
|
||||||
|
</div>
|
||||||
|
<input type="password" id="password" name="password" class="w-full px-4 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent" placeholder="••••••••" required>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button type="submit" class="w-full bg-blue-600 text-white py-2 px-4 rounded-md hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 transition-colors">
|
||||||
|
Se connecter
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<div class="mt-6 text-center">
|
||||||
|
<p class="text-sm text-gray-600">
|
||||||
|
Pas encore de compte? <a routerLink="/register" class="text-blue-600 hover:text-blue-800 font-medium">S'inscrire</a>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
14
src/app/public/pages/login/login.component.ts
Normal file
14
src/app/public/pages/login/login.component.ts
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
import { Component } from '@angular/core';
|
||||||
|
import {RouterLink} from '@angular/router';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-login',
|
||||||
|
imports: [
|
||||||
|
RouterLink
|
||||||
|
],
|
||||||
|
templateUrl: './login.component.html',
|
||||||
|
styleUrl: './login.component.css'
|
||||||
|
})
|
||||||
|
export class LoginComponent {
|
||||||
|
|
||||||
|
}
|
||||||
43
src/app/public/pages/register/register.component.html
Normal file
43
src/app/public/pages/register/register.component.html
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
<section class="bg-gray-100 flex items-center justify-center min-h-screen p-4">
|
||||||
|
<div class="bg-white rounded-lg shadow-lg p-8 max-w-md w-full">
|
||||||
|
<div class="text-center mb-8">
|
||||||
|
<h1 class="text-2xl font-bold text-gray-800">Inscription</h1>
|
||||||
|
<p class="text-gray-600 mt-2">Entrez vos informations pour vous inscrire</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<form>
|
||||||
|
<div class="mb-6">
|
||||||
|
<label for="email" class="block text-gray-700 text-sm font-medium mb-2">Email</label>
|
||||||
|
<input type="email" id="email" name="email" class="w-full px-4 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent" placeholder="votre@email.com" required>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mb-6">
|
||||||
|
<label for="firstname" class="block text-gray-700 text-sm font-medium mb-2">Prénom</label>
|
||||||
|
<input type="text" id="firstname" name="firstname" class="w-full px-4 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent" placeholder="votre@email.com" required>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mb-6">
|
||||||
|
<label for="lastname" class="block text-gray-700 text-sm font-medium mb-2">Nom</label>
|
||||||
|
<input type="text" id="lastname" name="lastname" class="w-full px-4 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent" placeholder="votre@email.com" required>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mb-6">
|
||||||
|
<div class="flex justify-between items-center mb-2">
|
||||||
|
<label for="password" class="block text-gray-700 text-sm font-medium">Mot de passe</label>
|
||||||
|
</div>
|
||||||
|
<input type="password" id="password" name="password" class="w-full px-4 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent" placeholder="••••••••" required>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mb-6">
|
||||||
|
<div class="flex justify-between items-center mb-2">
|
||||||
|
<label for="confirmPassword" class="block text-gray-700 text-sm font-medium">Confirmer le mot de passe</label>
|
||||||
|
</div>
|
||||||
|
<input type="password" id="confirmPassword" name="confirmPassword" class="w-full px-4 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent" placeholder="••••••••" required>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button type="submit" class="w-full bg-blue-600 text-white py-2 px-4 rounded-md hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 transition-colors">
|
||||||
|
S'inscrire
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
14
src/app/public/pages/register/register.component.ts
Normal file
14
src/app/public/pages/register/register.component.ts
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
import { Component } from '@angular/core';
|
||||||
|
import {RouterLink} from '@angular/router';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-register',
|
||||||
|
imports: [
|
||||||
|
RouterLink
|
||||||
|
],
|
||||||
|
templateUrl: './register.component.html',
|
||||||
|
styleUrl: './register.component.css'
|
||||||
|
})
|
||||||
|
export class RegisterComponent {
|
||||||
|
|
||||||
|
}
|
||||||
@@ -3,10 +3,14 @@ import { RouterModule, Routes } from '@angular/router';
|
|||||||
import {NotFoundComponent} from './pages/not-found/not-found.component';
|
import {NotFoundComponent} from './pages/not-found/not-found.component';
|
||||||
import {PublicLayoutComponent} from './public-layout/public-layout.component';
|
import {PublicLayoutComponent} from './public-layout/public-layout.component';
|
||||||
import {HomeComponent} from './pages/home/home.component';
|
import {HomeComponent} from './pages/home/home.component';
|
||||||
|
import {LoginComponent} from './pages/login/login.component';
|
||||||
|
import {RegisterComponent} from './pages/register/register.component';
|
||||||
|
|
||||||
const routes: Routes = [
|
const routes: Routes = [
|
||||||
{ path: '', component: PublicLayoutComponent, children: [
|
{ path: '', component: PublicLayoutComponent, children: [
|
||||||
{ path: '', component: HomeComponent },
|
{ path: '', component: HomeComponent },
|
||||||
|
{ path: 'login', component: LoginComponent },
|
||||||
|
{ path: 'register', component: RegisterComponent },
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{ path: '**', component: NotFoundComponent },
|
{ path: '**', component: NotFoundComponent },
|
||||||
|
|||||||
4
src/environments/environment.ts
Normal file
4
src/environments/environment.ts
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
export const environment = {
|
||||||
|
apiurl: 'http://localhost:3333',
|
||||||
|
apikey: '9IgFg8cnUS4XJE7Q91A0XjrWnjbnBhdk98jcI6fV1n6NAEYz31SHicge8Vkq0bCGvfKsjylb19ouri6FFUeNC1PgPvwrNCC3G5jcz4PLInlFanzf47hCsBJw4IXuhNHC',
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user