base de l'authentification (#4)

Co-authored-by: styve Lioumba <styve.lioumba@jdc.fr>
This commit is contained in:
Styve Lioumba
2024-09-26 19:08:25 +02:00
committed by styve Lioumba
parent 0d575e0737
commit 1dc1109482
25 changed files with 491 additions and 6 deletions

View File

@@ -1 +1,4 @@
# TrouveTonProfile # TrouveTonProfile
## Description
Trouve Ton Profile est une plateforme innovante qui permet à chacun de trouver facilement des professionnels qualifiés dans tous les domaines de la vie quotidienne. Que tu cherches un électricien, un plombier, un développeur, ou tout autre expert, la plateforme te permet de parcourir rapidement des profils, de découvrir leurs compétences, et de sélectionner la personne idéale pour répondre à tes besoins. Conçue pour faciliter l'accès à des talents locaux et spécialisés, Trouve Ton Profile est l'outil incontournable pour simplifier les tâches du quotidien en connectant les personnes à des solutions fiables et adaptées.

View File

@@ -4,8 +4,8 @@ main {
min-height: 100vh; /* Minimum 100% de la hauteur de la fenêtre */ min-height: 100vh; /* Minimum 100% de la hauteur de la fenêtre */
} }
#content { .content {
flex-grow: 1; /* Cette zone grandit pour remplir l'espace restant */ flex: 1; /* Cette zone grandit pour remplir l'espace restant */
padding: 20px; padding: 20px;
} }

View File

@@ -16,6 +16,16 @@ export const routes: Routes = [
title: 'Liste des profiles', title: 'Liste des profiles',
loadChildren: () => import('@app/routes/profile/profile.module').then(m => m.ProfileModule) loadChildren: () => import('@app/routes/profile/profile.module').then(m => m.ProfileModule)
}, },
{
path:'auth',
title: 'Authentification',
loadChildren: () => import('@app/routes/authentification/authentification.module').then(m => m.AuthentificationModule)
},
{
path: 'my-profile',
title: 'Mon profile',
loadChildren: () => import('@app/routes/my-profile/my-profile.module').then(m => m.MyProfileModule)
},
{ {
path: 'not-found', path: 'not-found',
title: 'Page non trouvée', title: 'Page non trouvée',

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,23 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { AuthComponent } from './auth.component';
describe('AuthComponent', () => {
let component: AuthComponent;
let fixture: ComponentFixture<AuthComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [AuthComponent]
})
.compileComponents();
fixture = TestBed.createComponent(AuthComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@@ -0,0 +1,16 @@
import { Component } from '@angular/core';
import {RouterLink, RouterOutlet} from "@angular/router";
@Component({
selector: 'app-auth',
standalone: true,
imports: [
RouterOutlet,
RouterLink
],
templateUrl: './auth.component.html',
styleUrl: './auth.component.scss'
})
export class AuthComponent {
}

View File

@@ -0,0 +1,24 @@
import {NgModule} from '@angular/core';
import {RouterModule, Routes} from '@angular/router';
import {RegisterComponent} from "@app/shared/features/register/register.component";
import {AuthComponent} from "@app/routes/authentification/auth/auth.component";
import {LoginComponent} from "@app/shared/features/login/login.component";
const routes: Routes = [
{
path: '', component: AuthComponent, children: [
{path: '', component: LoginComponent},
{path: 'register', component: RegisterComponent},
]
},
{path: 'not-found', loadChildren: () => import('@app/routes/not-found/not-found.module').then(m => m.NotFoundModule)},
{path: '**', redirectTo: 'not-found'}
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule]
})
export class AuthentificationRoutingModule {
}

View File

@@ -0,0 +1,14 @@
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { AuthentificationRoutingModule } from './authentification-routing.module';
@NgModule({
declarations: [],
imports: [
CommonModule,
AuthentificationRoutingModule
]
})
export class AuthentificationModule { }

View File

@@ -0,0 +1,14 @@
import {NgModule} from '@angular/core';
import {RouterModule, Routes} from '@angular/router';
import {MyProfileComponent} from "@app/routes/my-profile/my-profile.component";
const routes: Routes = [
{path: '', component: MyProfileComponent}
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule]
})
export class MyProfileRoutingModule {
}

View File

@@ -0,0 +1 @@
<p>my-profile works!</p>

View File

@@ -0,0 +1,23 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { MyProfileComponent } from './my-profile.component';
describe('MyProfileComponent', () => {
let component: MyProfileComponent;
let fixture: ComponentFixture<MyProfileComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [MyProfileComponent]
})
.compileComponents();
fixture = TestBed.createComponent(MyProfileComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@@ -0,0 +1,12 @@
import { Component } from '@angular/core';
@Component({
selector: 'app-my-profile',
standalone: true,
imports: [],
templateUrl: './my-profile.component.html',
styleUrl: './my-profile.component.scss'
})
export class MyProfileComponent {
}

View File

@@ -0,0 +1,14 @@
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { MyProfileRoutingModule } from './my-profile-routing.module';
@NgModule({
declarations: [],
imports: [
CommonModule,
MyProfileRoutingModule
]
})
export class MyProfileModule { }

View File

@@ -1,4 +1,4 @@
<header class="w-screen bg-white dark:bg-gray-900"> <header class="w-screen bg-white dark:bg-gray-900 min-h-12">
<div class="w-full"> <div class="w-full">
<nav <nav
class="fixed w-full z-20 top-0 start-1/2 max-w-6xl -translate-x-1/2 bg-white dark:bg-gray-900"> class="fixed w-full z-20 top-0 start-1/2 max-w-6xl -translate-x-1/2 bg-white dark:bg-gray-900">
@@ -42,8 +42,7 @@
</button> </button>
} }
<span class="text-black dark:text-white"> | </span> <span class="text-black dark:text-white"> | </span>
<button <a [routerLink]="['/auth']"
type="button"
class="text-black dark:text-white font-medium rounded-lg text-sm px-4 py-2 text-center flex items-center justify-center gap-1"> class="text-black dark:text-white font-medium rounded-lg text-sm px-4 py-2 text-center flex items-center justify-center gap-1">
<span class="inline-block h-4 w-4"> <span class="inline-block h-4 w-4">
<svg <svg
@@ -55,7 +54,7 @@
</svg> </svg>
</span> </span>
<span class="hidden sm:block text-black dark:text-white">Se connecter</span> <span class="hidden sm:block text-black dark:text-white">Se connecter</span>
</button> </a>
<button <button
data-collapse-toggle="navbar-sticky" data-collapse-toggle="navbar-sticky"
type="button" type="button"

View File

@@ -0,0 +1,56 @@
<form [formGroup]="loginForm" (ngSubmit)="onSubmit()" class="w-full space-y-4">
<div class="">
<div class="relative">
<span class="absolute block w-3 h-3 -translate-y-1/2 top-1/2 left-1">
<svg xmlns="http://www.w3.org/2000/svg" class="w-full h-full fill-current" viewBox="0 0 512 512">
<path
d="M256 64C150 64 64 150 64 256s86 192 192 192c17.7 0 32 14.3 32 32s-14.3 32-32 32C114.6 512 0 397.4 0 256S114.6 0 256 0S512 114.6 512 256v32c0 53-43 96-96 96c-29.3 0-55.6-13.2-73.2-33.9C320 371.1 289.5 384 256 384c-70.7 0-128-57.3-128-128s57.3-128 128-128c27.9 0 53.7 8.9 74.7 24.1c5.7-5 13.1-8.1 21.3-8.1c17.7 0 32 14.3 32 32v80 32c0 17.7 14.3 32 32 32s32-14.3 32-32V256c0-106-86-192-192-192zm64 192a64 64 0 1 0 -128 0 64 64 0 1 0 128 0z"/>
</svg>
</span>
<input formControlName="email" placeholder="email" type="email" id="email" name="email" class="w-full h-10 px-5 py-2 text-xs bg-transparent border rounded-md"/>
</div>
</div>
<div class="">
<div class="text-right">
<div class="relative">
<span class="absolute block w-3 h-3 -translate-y-1/2 top-1/2 left-1">
<svg xmlns="http://www.w3.org/2000/svg" class="w-full h-full fill-current" viewBox="0 0 448 512">
<path
d="M144 144v48H304V144c0-44.2-35.8-80-80-80s-80 35.8-80 80zM80 192V144C80 64.5 144.5 0 224 0s144 64.5 144 144v48h16c35.3 0 64 28.7 64 64V448c0 35.3-28.7 64-64 64H64c-35.3 0-64-28.7-64-64V256c0-35.3 28.7-64 64-64H80z"/>
</svg>
</span>
<input formControlName="password" placeholder="mot de passe" type="password" id="password" name="" class="w-full h-10 px-5 py-2 text-xs bg-transparent border rounded-md"/>
<button class="absolute w-4 h-4 -translate-y-1/2 right-1 top-1/2 togglePasswordVisibility">
<span class="inline-block w-4 h-4">
<svg xmlns="http://www.w3.org/2000/svg" class="w-full h-full fill-current" viewBox="0 -960 960 960">
<path d="M480-320q75 0 127.5-52.5T660-500q0-75-52.5-127.5T480-680q-75 0-127.5 52.5T300-500q0 75 52.5 127.5T480-320Zm0-72q-45 0-76.5-31.5T372-500q0-45 31.5-76.5T480-608q45 0 76.5 31.5T588-500q0 45-31.5 76.5T480-392Zm0 192q-146 0-266-81.5T40-500q54-137 174-218.5T480-800q146 0 266 81.5T920-500q-54 137-174 218.5T480-200Zm0-300Zm0 220q113 0 207.5-59.5T832-500q-50-101-144.5-160.5T480-720q-113 0-207.5 59.5T128-500q50 101 144.5 160.5T480-280Z"/>
</svg>
</span>
</button>
</div>
<a [routerLink]="['']" class="text-xs">Mot de passe oublié?</a>
</div>
</div>
<div class="relative">
<button class="text-xs py-2 px-4 border bg-[#002B2F] w-1/2 text-center text-gray-50 rounded-md">
Se connecter
</button>
</div>
<div class="relative">
<div class="flex items-center">
<input checked id="checked-checkbox" type="checkbox" value="" class="w-4 h-4 text-red-600 bg-gray-100 border-gray-300 rounded"/>
<label for="checked-checkbox" class="text-sm font-medium ms-2">
Se souvenir de moi
</label>
</div>
</div>
<div class="">
<p class="text-xs font-light text-center"> Vous n'avez pas de compte?
<a [routerLink]="['register']" class="font-bold">Créez-en ici</a>
</p>
</div>
</form>

View File

@@ -0,0 +1,23 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { LoginComponent } from './login.component';
describe('LoginComponent', () => {
let component: LoginComponent;
let fixture: ComponentFixture<LoginComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [LoginComponent]
})
.compileComponents();
fixture = TestBed.createComponent(LoginComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@@ -0,0 +1,35 @@
import {Component, inject, output} from '@angular/core';
import {Router, RouterLink} from "@angular/router";
import {FormBuilder, FormControl, ReactiveFormsModule, Validators} from "@angular/forms";
@Component({
selector: 'app-login',
standalone: true,
imports: [
RouterLink,
ReactiveFormsModule
],
templateUrl: './login.component.html',
styleUrl: './login.component.scss'
})
export class LoginComponent {
private formBuilder = inject(FormBuilder);
private router = inject(Router);
loginForm = this.formBuilder.group({
email: new FormControl('', Validators.required),
password: new FormControl('', Validators.required)
});
formSubmitted = output<any>()
onSubmit() {
if (this.loginForm.invalid) {
return;
}
const data = this.loginForm.getRawValue();
this.formSubmitted.emit(data);
this.router.navigate(['/my-profile'])
}
}

View File

@@ -0,0 +1,67 @@
<form [formGroup]="registerForm" (ngSubmit)="onSubmit()" class="w-full space-y-4">
<div class="">
<div class="relative">
<span class="absolute block w-3 h-3 -translate-y-1/2 top-1/2 left-1">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"
class="w-3 h-3">
<path stroke-linecap="round" stroke-linejoin="round"
d="M15.75 6a3.75 3.75 0 1 1-7.5 0 3.75 3.75 0 0 1 7.5 0ZM4.501 20.118a7.5 7.5 0 0 1 14.998 0A17.933 17.933 0 0 1 12 21.75c-2.676 0-5.216-.584-7.499-1.632Z"/>
</svg>
</span>
<input formControlName="name" placeholder="nom" type="text" name="name" id="name"
class="w-full h-10 px-5 py-2 text-xs bg-transparent border rounded-md"/>
</div>
</div>
<div class="">
<div class="relative">
<span class="absolute block w-3 h-3 -translate-y-1/2 top-1/2 left-1">
<svg xmlns="http://www.w3.org/2000/svg" class="w-full h-full fill-current" viewBox="0 0 512 512">
<path
d="M256 64C150 64 64 150 64 256s86 192 192 192c17.7 0 32 14.3 32 32s-14.3 32-32 32C114.6 512 0 397.4 0 256S114.6 0 256 0S512 114.6 512 256v32c0 53-43 96-96 96c-29.3 0-55.6-13.2-73.2-33.9C320 371.1 289.5 384 256 384c-70.7 0-128-57.3-128-128s57.3-128 128-128c27.9 0 53.7 8.9 74.7 24.1c5.7-5 13.1-8.1 21.3-8.1c17.7 0 32 14.3 32 32v80 32c0 17.7 14.3 32 32 32s32-14.3 32-32V256c0-106-86-192-192-192zm64 192a64 64 0 1 0 -128 0 64 64 0 1 0 128 0z"/>
</svg>
</span>
<input formControlName="email" placeholder="email" type="email" id="email" name="email"
class="w-full h-10 px-5 py-2 text-xs bg-transparent border rounded-md"/>
</div>
</div>
<div class="">
<div class="text-right">
<div class="relative">
<span class="absolute block w-3 h-3 -translate-y-1/2 top-1/2 left-1">
<svg xmlns="http://www.w3.org/2000/svg" class="w-full h-full fill-current" viewBox="0 0 448 512">
<path
d="M144 144v48H304V144c0-44.2-35.8-80-80-80s-80 35.8-80 80zM80 192V144C80 64.5 144.5 0 224 0s144 64.5 144 144v48h16c35.3 0 64 28.7 64 64V448c0 35.3-28.7 64-64 64H64c-35.3 0-64-28.7-64-64V256c0-35.3 28.7-64 64-64H80z"/>
</svg>
</span>
<input formControlName="password" placeholder="mot de passe" type="password" id="password" name="password"
class="w-full h-10 px-5 py-2 text-xs bg-transparent border rounded-md"/>
<button class="absolute w-4 h-4 -translate-y-1/2 right-1 top-1/2 togglePasswordVisibility">
<span class="inline-block w-4 h-4">
<svg xmlns="http://www.w3.org/2000/svg" class="w-full h-full fill-current" viewBox="0 -960 960 960">
<path
d="M480-320q75 0 127.5-52.5T660-500q0-75-52.5-127.5T480-680q-75 0-127.5 52.5T300-500q0 75 52.5 127.5T480-320Zm0-72q-45 0-76.5-31.5T372-500q0-45 31.5-76.5T480-608q45 0 76.5 31.5T588-500q0 45-31.5 76.5T480-392Zm0 192q-146 0-266-81.5T40-500q54-137 174-218.5T480-800q146 0 266 81.5T920-500q-54 137-174 218.5T480-200Zm0-300Zm0 220q113 0 207.5-59.5T832-500q-50-101-144.5-160.5T480-720q-113 0-207.5 59.5T128-500q50 101 144.5 160.5T480-280Z"/>
</svg>
</span>
</button>
</div>
</div>
</div>
<div class="relative">
<button type="submit" class="text-xs py-2 px-4 border bg-[#002B2F] w-1/2 text-center text-gray-50 rounded-md">
S'inscrire
</button>
</div>
<div class="">
<p class="text-xs font-light text-center"> Vous avez un compte?
<a [routerLink]="['/auth']" class="font-bold">Connectez vous ici</a>
</p>
</div>
</form>

View File

@@ -0,0 +1,23 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { RegisterComponent } from './register.component';
describe('RegisterComponent', () => {
let component: RegisterComponent;
let fixture: ComponentFixture<RegisterComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [RegisterComponent]
})
.compileComponents();
fixture = TestBed.createComponent(RegisterComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@@ -0,0 +1,35 @@
import {Component, inject, output} from '@angular/core';
import {Router, RouterLink} from "@angular/router";
import {FormBuilder, FormControl, ReactiveFormsModule, Validators} from "@angular/forms";
@Component({
selector: 'app-register',
standalone: true,
imports: [
RouterLink,
ReactiveFormsModule
],
templateUrl: './register.component.html',
styleUrl: './register.component.scss'
})
export class RegisterComponent {
private formBuilder = inject(FormBuilder);
private router = inject(Router);
protected registerForm = this.formBuilder.group({
name: new FormControl('', Validators.required),
email: new FormControl('', Validators.required),
password: new FormControl('', Validators.required)
});
formSubmitted = output<any>()
onSubmit() {
if (this.registerForm.invalid) {
return;
}
const data = this.registerForm.getRawValue();
this.formSubmitted.emit(data);
this.router.navigate(['/auth'])
}
}

View File

@@ -8,6 +8,13 @@ module.exports = {
extend: { extend: {
backgroundColor: ['dark'], backgroundColor: ['dark'],
textColor: ['dark'], textColor: ['dark'],
boxShadow: {
oauthBtn:
'inset -2px -2px 8px 0px rgba(0, 0, 0, 0.25), 2px 2px 8px 0px rgba(0, 0, 0, 0.25)',
},
backgroundImage: {
auth: 'url("https://images.unsplash.com/photo-1477346611705-65d1883cee1e?q=80&w=2940&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D")',
},
}, },
}, },
plugins: [], plugins: [],