+
+
+
+
+
+
+
+
+
+
+
+
{{participantsCount}}
+
Participants
+
+
+
+
+
+
+
{{formateursCount}}
+
Formateurs
+
+
+
+
+
+
+
{{formationsCount}}
+
Formations
+
+
+
+
+
+
+
{{utilisateursCount}}
+
Utilisateurs
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ # |
+ Nom |
+ Prénom |
+ Email |
+ Téléphone |
+ Spécialité |
+ Employeur |
+ Nb formations |
+
+
+
+
+ {{ i + 1 }} |
+ {{ formateur.nom }} |
+ {{ formateur.prenom }} |
+ {{ formateur.email }} |
+ {{ formateur.tel }} |
+ {{ formateur.specialite }} |
+ {{ formateur.employeur }} |
+ {{ formateur.nb }} |
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/app/home/home.component.ts b/src/app/home/home.component.ts
index 9aba51e04..f9ed327d2 100644
--- a/src/app/home/home.component.ts
+++ b/src/app/home/home.component.ts
@@ -9,6 +9,13 @@ import * as Chartist from 'chartist';
styleUrls: ['./home.component.css']
})
export class HomeComponent implements OnInit {
+
+ // Nouveaux compteurs
+ public participantsCount: number = 0;
+ public formateursCount: number = 0;
+ public formationsCount: number = 0;
+ public utilisateursCount: number = 0;
+
public emailChartType: ChartType;
public emailChartData: any;
public emailChartLegendItems: LegendItem[];
@@ -25,7 +32,37 @@ export class HomeComponent implements OnInit {
public activityChartResponsive: any[];
public activityChartLegendItems: LegendItem[];
constructor() { }
-
+ formateurs = [
+ {
+ nom: 'Miladi',
+ prenom: 'Imen',
+ email: 'imen.miladi@example.com',
+ tel: '+216 99 123 456',
+ specialite: 'Développement mobile',
+ employeur: 'ISI Ariana',
+ nb:'6'
+ },
+ {
+ nom: 'Doe',
+ prenom: 'Jane',
+ email: 'jane.doe@example.com',
+ tel: '+216 20 654 321',
+ specialite: 'Intelligence Artificielle',
+ employeur: 'Université Centrale',
+ nb:'5'
+ },
+ {
+ nom: 'Ali',
+ prenom: 'Ahmed',
+ email: 'ahmed.ali@example.com',
+ tel: '+216 25 789 456',
+ specialite: 'Mobile Development',
+ employeur: 'GoMyCode',
+ nb:'3'
+ },
+ // Ajouter d'autres formateurs ici
+ ];
+
ngOnInit() {
this.emailChartType = ChartType.Pie;
this.emailChartData = {
@@ -77,36 +114,45 @@ export class HomeComponent implements OnInit {
];
this.activityChartType = ChartType.Bar;
- this.activityChartData = {
- labels: ['Jan', 'Feb', 'Mar', 'Apr', 'Mai', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
- series: [
- [542, 443, 320, 780, 553, 453, 326, 434, 568, 610, 756, 895],
- [412, 243, 280, 580, 453, 353, 300, 364, 368, 410, 636, 695]
- ]
- };
- this.activityChartOptions = {
- seriesBarDistance: 10,
- axisX: {
- showGrid: false
- },
- height: '245px'
- };
- this.activityChartResponsive = [
- ['screen and (max-width: 640px)', {
- seriesBarDistance: 5,
- axisX: {
- labelInterpolationFnc: function (value) {
- return value[0];
- }
- }
- }]
- ];
- this.activityChartLegendItems = [
- { title: 'Tesla Model S', imageClass: 'fa fa-circle text-info' },
- { title: 'BMW 5 Series', imageClass: 'fa fa-circle text-danger' }
- ];
-
+this.activityChartData = {
+ labels: ['Jan', 'Feb', 'Mar', 'Apr', 'Mai', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
+ series: [
+ [542, 443, 320, 780, 5530, 4530, 3260, 4340, 5680, 6100, 7560, 8950],
+ [412, 243, 280, 580, 4530, 3530, 3000, 3640, 3680, 4100, 6360, 6950],
+ [1000, 249, 3000, 580, 5000, 6000, 7000, 8000, 3000, 6000, 4500, 5700]
+ ]
+};
+this.activityChartOptions = {
+ seriesBarDistance: 10,
+ axisX: {
+ showGrid: false
+ },
+ axisY: {
+ type: Chartist.FixedScaleAxis,
+ low: 0, // 🔥 commence bien à zéro
+ high: 10000,
+ ticks: [0, 1000, 2000, 3000, 4000, 5000, 6000, 7000, 8000, 9000, 10000], // 🔥 on ajoute 0 ici
+ labelInterpolationFnc: function(value) {
+ return value; // si tu veux ajouter 'DT', fais return value + ' DT';
+ }
+ },
+ height: '245px'
+};
+this.activityChartResponsive = [
+ ['screen and (max-width: 640px)', {
+ seriesBarDistance: 5,
+ axisX: {
+ labelInterpolationFnc: function (value) {
+ return value[0];
+ }
}
+ }]
+];
-}
+this.activityChartLegendItems = [
+ { title: 'Web', imageClass: 'fa fa-circle text-info' },
+ { title: 'mobile', imageClass: 'fa fa-circle text-danger' },
+ { title: 'AI', imageClass: 'fa fa-circle text-warning' }
+];
+ }}
\ No newline at end of file
diff --git a/src/app/interceptors/auth.interceptor.spec.ts b/src/app/interceptors/auth.interceptor.spec.ts
new file mode 100644
index 000000000..7ab58dbd1
--- /dev/null
+++ b/src/app/interceptors/auth.interceptor.spec.ts
@@ -0,0 +1,16 @@
+import { TestBed } from '@angular/core/testing';
+
+import { AuthInterceptor } from './auth.interceptor';
+
+describe('AuthInterceptor', () => {
+ beforeEach(() => TestBed.configureTestingModule({
+ providers: [
+ AuthInterceptor
+ ]
+ }));
+
+ it('should be created', () => {
+ const interceptor: AuthInterceptor = TestBed.inject(AuthInterceptor);
+ expect(interceptor).toBeTruthy();
+ });
+});
diff --git a/src/app/interceptors/auth.interceptor.ts b/src/app/interceptors/auth.interceptor.ts
new file mode 100644
index 000000000..fe935125c
--- /dev/null
+++ b/src/app/interceptors/auth.interceptor.ts
@@ -0,0 +1,26 @@
+import { Injectable } from '@angular/core';
+import {
+ HttpRequest,
+ HttpHandler,
+ HttpEvent,
+ HttpInterceptor
+} from '@angular/common/http';
+import { Observable } from 'rxjs';
+
+@Injectable()
+export class AuthInterceptor implements HttpInterceptor {
+
+ constructor() {}
+
+ intercept(request: HttpRequest
, next: HttpHandler): Observable> {
+ const token = localStorage.getItem('token');
+ if (token) {
+ request = request.clone({
+ setHeaders: {
+ Authorization: `Bearer ${token}`
+ }
+ });
+ }
+ return next.handle(request);
+ }
+}
diff --git a/src/app/interfaces/login-request.interface.ts b/src/app/interfaces/login-request.interface.ts
new file mode 100644
index 000000000..2b26d9f8c
--- /dev/null
+++ b/src/app/interfaces/login-request.interface.ts
@@ -0,0 +1,4 @@
+export interface LoginRequest {
+ login: string;
+ motDePasse: string;
+ }
\ No newline at end of file
diff --git a/src/app/layouts/admin-layout/admin-layout.routing.ts b/src/app/layouts/admin-layout/admin-layout.routing.ts
index e09417d82..a09a97fed 100644
--- a/src/app/layouts/admin-layout/admin-layout.routing.ts
+++ b/src/app/layouts/admin-layout/admin-layout.routing.ts
@@ -2,20 +2,34 @@ import { Routes } from '@angular/router';
import { HomeComponent } from '../../home/home.component';
import { UserComponent } from '../../user/user.component';
+
import { TablesComponent } from '../../tables/tables.component';
import { TypographyComponent } from '../../typography/typography.component';
import { IconsComponent } from '../../icons/icons.component';
import { MapsComponent } from '../../maps/maps.component';
import { NotificationsComponent } from '../../notifications/notifications.component';
import { UpgradeComponent } from '../../upgrade/upgrade.component';
+import { UsersListComponent } from 'app/users-list/users-list.component';
+import { FormateurListComponent } from 'app/formateur-list/formateur-list.component';
+import { FormationListeComponent } from 'app/formation-liste/formation-liste.component';
+import { ParticipantListComponent } from 'app/participant-list/participant-list.component';
+import { AuthGuard } from 'app/guards/auth.guard';
+import { EmployeurListComponent } from 'app/employeur-list/employeur-list.component';
export const AdminLayoutRoutes: Routes = [
- { path: 'dashboard', component: HomeComponent },
- { path: 'user', component: UserComponent },
- { path: 'table', component: TablesComponent },
- { path: 'typography', component: TypographyComponent },
- { path: 'icons', component: IconsComponent },
- { path: 'maps', component: MapsComponent },
- { path: 'notifications', component: NotificationsComponent },
- { path: 'upgrade', component: UpgradeComponent },
+ { path: 'dashboard', component: HomeComponent ,canActivate: [AuthGuard]},
+ { path: 'user', component: UserComponent ,canActivate: [AuthGuard]},
+
+ { path: 'user-list', component: UsersListComponent ,canActivate: [AuthGuard]},
+ { path: 'participant-list', component: ParticipantListComponent ,canActivate: [AuthGuard]},
+ { path: 'table', component: TablesComponent ,canActivate: [AuthGuard]},
+ { path: 'typography', component: TypographyComponent ,canActivate: [AuthGuard]},
+ { path: 'icons', component: IconsComponent ,canActivate: [AuthGuard]},
+ { path: 'maps', component: MapsComponent ,canActivate: [AuthGuard]},
+ { path: 'notifications', component: NotificationsComponent ,canActivate: [AuthGuard]},
+ { path: 'upgrade', component: UpgradeComponent ,canActivate: [AuthGuard]},
+ {path: 'formateur-list', component:FormateurListComponent ,canActivate: [AuthGuard]},
+ {path: 'formation-liste', component:FormationListeComponent ,canActivate: [AuthGuard]},
+ { path: 'participant-list', component: ParticipantListComponent ,canActivate: [AuthGuard]},
+ { path: 'employeur-list', component: EmployeurListComponent ,canActivate: [AuthGuard]},
];
diff --git a/src/app/login/login.component.css b/src/app/login/login.component.css
new file mode 100644
index 000000000..96cb2a90b
--- /dev/null
+++ b/src/app/login/login.component.css
@@ -0,0 +1,106 @@
+/* login.component.css */
+.login-container {
+ height: 100vh;
+ width: 100%;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ background-image: url('assets/img/background_login.jpg');
+ background-size: cover;
+ background-position: center;
+ }
+
+ .login-card {
+ width: 400px;
+ padding: 40px;
+ border-radius: 10px;
+ background-color: rgba(255, 255, 255, 0.95);
+ box-shadow: 0 8px 20px rgba(0, 0, 0, 0.2);
+ }
+
+ .logo-container {
+ text-align: center;
+ margin-bottom: 30px;
+ }
+
+ .logo {
+ width: 100px;
+ height: auto;
+ margin-bottom: 15px;
+ }
+
+ h1 {
+ color: #d82c2c;
+ margin: 0;
+ font-size: 24px;
+ font-weight: 600;
+ }
+
+ .login-form .form-group {
+ margin-bottom: 20px;
+ }
+
+ .login-form label {
+ display: block;
+ margin-bottom: 8px;
+ font-weight: 500;
+ color: #333;
+ }
+
+ .login-form input[type="text"],
+ .login-form input[type="password"] {
+ width: 100%;
+ padding: 12px;
+ border: 1px solid #ddd;
+ border-radius: 5px;
+ font-size: 16px;
+ transition: border-color 0.3s;
+ }
+
+ .login-form input:focus {
+ border-color: #d82c2c;
+ outline: none;
+ box-shadow: 0 0 0 2px rgba(216, 44, 44, 0.2);
+ }
+
+ .remember-me {
+ display: flex;
+ align-items: center;
+ margin-bottom: 20px;
+ }
+
+ .remember-me input {
+ margin-right: 8px;
+ }
+
+ .login-button {
+ width: 100%;
+ padding: 14px;
+ border: none;
+ border-radius: 5px;
+ background-color: #d82c2c;
+ color: white;
+ font-size: 16px;
+ font-weight: 600;
+ cursor: pointer;
+ transition: background-color 0.3s;
+ }
+
+ .login-button:hover {
+ background-color: #b52222;
+ }
+
+ .forgot-password {
+ margin-top: 15px;
+ text-align: center;
+ }
+
+ .forgot-password a {
+ color: #d82c2c;
+ text-decoration: none;
+ font-size: 14px;
+ }
+
+ .forgot-password a:hover {
+ text-decoration: underline;
+ }
\ No newline at end of file
diff --git a/src/app/login/login.component.html b/src/app/login/login.component.html
new file mode 100644
index 000000000..ea6f0796e
--- /dev/null
+++ b/src/app/login/login.component.html
@@ -0,0 +1,44 @@
+
+
+
+
+

+
Centre de Formation
+
+
+
+
+
\ No newline at end of file
diff --git a/src/app/login/login.component.spec.ts b/src/app/login/login.component.spec.ts
new file mode 100644
index 000000000..10eca249d
--- /dev/null
+++ b/src/app/login/login.component.spec.ts
@@ -0,0 +1,23 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { LoginComponent } from './login.component';
+
+describe('LoginComponent', () => {
+ let component: LoginComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ declarations: [ LoginComponent ]
+ })
+ .compileComponents();
+
+ fixture = TestBed.createComponent(LoginComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/src/app/login/login.component.ts b/src/app/login/login.component.ts
new file mode 100644
index 000000000..9d79d272d
--- /dev/null
+++ b/src/app/login/login.component.ts
@@ -0,0 +1,53 @@
+// login.component.ts
+import { Component } from '@angular/core';
+import { Router } from '@angular/router';
+import { AuthService } from 'app/services/auth.service';
+import Swal from 'sweetalert2';
+@Component({
+ selector: 'app-login',
+ templateUrl: './login.component.html',
+ styleUrls: ['./login.component.css']
+})
+export class LoginComponent {
+ username: string = '';
+ password: string = '';
+ rememberMe: boolean = false;
+
+ credentials = {
+ login: '',
+ motDePasse: ''
+ };
+
+ constructor(private authService: AuthService, private router: Router) {}
+
+ onLogin() {
+ this.authService.login(this.credentials).subscribe({
+ next: (response) => {
+ localStorage.setItem('token', response.token);
+ this.router.navigate(['/dashboard']);
+ },
+ error: (err) => {
+ if (err.status === 500 || err.status === 0) {
+ // Erreur serveur ou backend non joignable
+ Swal.fire({
+ icon: 'error',
+ title: 'Erreur serveur',
+ text: 'Veuillez réessayer plus tard.',
+ confirmButtonColor: '#d82c2c',
+ confirmButtonText:"réessayer"
+ });
+ } else {
+ // Erreur d’identifiants (ex : exception Runtime côté backend)
+ Swal.fire({
+ icon: 'warning',
+ title: 'Identifiants invalides',
+ text: "Nom d'utilisateur ou mot de passe incorrect.",
+ confirmButtonColor: '#d82c2c',
+ confirmButtonText:"réessayer",
+
+
+ });
+ }
+ },
+ });
+ }}
\ No newline at end of file
diff --git a/src/app/participant-list/participant-list.component.css b/src/app/participant-list/participant-list.component.css
new file mode 100644
index 000000000..35527918f
--- /dev/null
+++ b/src/app/participant-list/participant-list.component.css
@@ -0,0 +1,56 @@
+/* Amélioration de l'apparence des boutons */
+.btn {
+ border-radius: 4px;
+ font-weight: 500;
+ padding: 0.375rem 0.75rem;
+ transition: all 0.2s ease-in-out;
+ margin-right: 8px;
+}
+
+.btn-sm {
+ font-size: 1.3rem;
+ padding: 0.25rem 0.5rem;
+}
+
+.btn-info {
+ box-shadow: 0 2px 4px rgba(23, 162, 184, 0.3);
+}
+
+.btn-danger {
+ box-shadow: 0 2px 4px rgba(220, 53, 69, 0.3);
+}
+
+.btn-primary {
+ box-shadow: 0 2px 4px rgba(13, 110, 253, 0.3);
+}
+
+.btn:hover {
+ transform: translateY(-1px);
+ box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
+}
+
+.btn i {
+ margin-right: 5px;
+}
+
+/* Amélioration de l'espacement dans le tableau */
+.table td, .table th {
+ padding: 12px 15px;
+ vertical-align: middle;
+}
+
+/* Amélioration pour le bouton Ajouter */
+.header .btn-primary {
+ padding: 0.5rem 1rem;
+ display: flex;
+ align-items: center;
+}
+
+.header .btn-primary i {
+ margin-right: 8px;
+}
+
+.modal-body {
+ max-height: 70vh;
+ overflow-y: auto;
+}
\ No newline at end of file
diff --git a/src/app/participant-list/participant-list.component.html b/src/app/participant-list/participant-list.component.html
new file mode 100644
index 000000000..2234dfff8
--- /dev/null
+++ b/src/app/participant-list/participant-list.component.html
@@ -0,0 +1,133 @@
+
+
+
+
+
+
+
+
+
+
+ {{ cell }} |
+ Actions |
+
+
+
+
+ {{ participant.id }} |
+ {{ participant.nom }} |
+ {{ participant.prenom }} |
+ {{ participant.structure?.libelle }} |
+ {{ participant.profile?.libelle }} |
+ {{ participant.email }} |
+ {{ participant.tel }} |
+
+
+
+
+
+ |
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Êtes-vous sûr de vouloir supprimer cet participant?
+
+ Nom: {{ selectedUser[1] }}
+ ID: {{ selectedUser[0] }}
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/app/participant-list/participant-list.component.spec.ts b/src/app/participant-list/participant-list.component.spec.ts
new file mode 100644
index 000000000..e8050d745
--- /dev/null
+++ b/src/app/participant-list/participant-list.component.spec.ts
@@ -0,0 +1,23 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { ParticipantListComponent } from './participant-list.component';
+
+describe('ParticipantListComponent', () => {
+ let component: ParticipantListComponent;
+ let fixture: ComponentFixture
;
+
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ declarations: [ ParticipantListComponent ]
+ })
+ .compileComponents();
+
+ fixture = TestBed.createComponent(ParticipantListComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/src/app/participant-list/participant-list.component.ts b/src/app/participant-list/participant-list.component.ts
new file mode 100644
index 000000000..0bd5ad838
--- /dev/null
+++ b/src/app/participant-list/participant-list.component.ts
@@ -0,0 +1,238 @@
+import { Component, OnInit } from '@angular/core';
+import { FormBuilder, FormGroup, Validators } from '@angular/forms';
+import { ParticipantListService } from 'app/services/participant-list.service';
+
+declare interface TableData {
+ headerRow: string[];
+ dataRows: string[][];
+}
+
+@Component({
+ selector: 'app-participant-list',
+ templateUrl: './participant-list.component.html',
+ styleUrls: ['./participant-list.component.css']
+})
+export class ParticipantListComponent implements OnInit {
+ public tableData1: TableData;
+ public userForm: FormGroup;
+ public isEditMode: boolean = false;
+ public selectedUserIndex: number = -1;
+ public selectedUser: string[] = null;
+ public participants : any;
+ public showUserModal: boolean = false;
+ public showDeleteModal: boolean = false;
+ structures: any[] = [
+ { id: 1, name: 'Direction centrale' },
+ { id: 2, name: 'Direction régionale' },
+ ];
+ profiles: any[] = [
+ { id: 3, name: 'gestionnaire' },
+ { id: 2, name: 'informaticien (bac + 3)' },
+ { id: 1, name: 'informaticien (bac + 5)' },
+ { id: 4, name: 'juriste' },
+ { id: 5, name: 'technicien supérieur' },
+ ];
+
+
+ constructor(private formBuilder: FormBuilder,private participantService: ParticipantListService) {}
+
+
+ ngOnInit() {
+ let data: string[][] = [];
+ this.participantService.getAllParticipant().subscribe({
+ next: (res) => {
+ console.log('Users fetched:', res);
+ this.participants = res ;
+ data = res.map((user: any) => [
+ String(user.id),
+ String(user.nom),
+ String(user.prenom),
+ String(user.structure?.libelle ),
+ String(user.profile?.libelle ),
+ String(user.email),
+ String(user.tel)
+ ]);
+ this.tableData1 = {
+ headerRow: ['ID', 'Nom', 'Prénom', 'Structure', 'Profil', 'Email', 'Téléphone'],
+ dataRows: data
+ };
+
+ console.log("data = ",data);
+ },
+ error: (err) => {
+ console.error('Error fetching users:', err);
+ },
+ complete: () => {
+ console.log('User fetching completed.');
+ }
+ });
+
+ this.tableData1 = {
+ headerRow: ['ID', 'Nom', 'Prénom', 'Structure', 'Profil', 'Email', 'Téléphone'],
+ dataRows: data
+ };
+
+
+
+ this.initForm();
+ }
+
+ ngAfterViewInit(){
+ this.loadParticipants();
+ }
+
+ initForm() {
+ this.userForm = this.formBuilder.group({
+ id: ['', Validators.required],
+ nom: ['', Validators.required],
+ prenom: ['', Validators.required],
+ structure: ['', Validators.required],
+ profile: ['', Validators.required],
+ email: ['', [Validators.required, Validators.email]],
+ telephone: ['', [Validators.required, Validators.pattern('^[0-9]{8}$')]]
+ });
+ }
+
+ openAddModal() {
+ this.isEditMode = false;
+ this.selectedUserIndex = -1;
+
+ const nextId = (
+ Math.max(...this.tableData1.dataRows.map(row => parseInt(row[0]))) + 1
+ ).toString();
+
+ this.userForm.reset();
+ this.userForm.patchValue({ id: nextId });
+
+ this.showUserModal = true;
+ }
+
+ openEditModal(index: number) {
+ this.isEditMode = true;
+ this.selectedUserIndex = index;
+ const userData = this.participants[index]
+
+ this.userForm.patchValue({
+ id: userData.id,
+ nom: userData.nom,
+ prenom: userData.prenom,
+ structure: userData.structure,
+ profile: userData.profile,
+ email: userData.email,
+ telephone: userData.telephone
+ });
+
+ this.showUserModal = true;
+ }
+
+ saveUser() {
+ if (this.userForm.invalid) {
+ return;
+ }
+
+ const formValues = this.userForm.value;
+
+ // Récupérer les IDs de profile et structure sélectionnés
+ const profileId = formValues.profile; // ID du profil sélectionné
+ const structureId = formValues.structure; // ID de la structure sélectionnée
+
+ if (this.isEditMode) {
+ const newParticipant = {
+ nom: formValues.nom,
+ prenom: formValues.prenom,
+ email: formValues.email,
+ tel: formValues.telephone,
+ profileId : formValues.profile,
+ structureId : formValues.structure
+ };
+ // Update existing user
+ this.participantService.updateParticipant(formValues.id, newParticipant).subscribe({
+ next: (updatedUser) => {
+ console.log('User updated:', updatedUser);
+ this.loadParticipants(); // Refresh the user list
+ this.showUserModal = false;
+ },
+ error: (err) => {
+ console.error('Error updating user:', err);
+ }
+ });
+ } else
+ // Envoie de la requête POST avec les IDs de profile et structure en paramètres
+ {
+
+ // Créer l'objet participant sans les IDs de profile et structure
+ const newParticipant = {
+ nom: formValues.nom,
+ prenom: formValues.prenom,
+ email: formValues.email,
+ tel: formValues.telephone
+ };
+ console.log(newParticipant)
+ // Récupérer les IDs de profile et structure sélectionnés
+ const profileId = formValues.profile; // ID du profil sélectionné
+ const structureId = formValues.structure; // ID de la structure sélectionnée
+
+
+ this.participantService.createParticipant(newParticipant, profileId, structureId)
+ .subscribe(
+ (response) => {
+ console.log('Participant créé avec succès', response);
+ this.closeUserModal();
+ this.userForm.reset();
+ this.initForm;
+ // Actualiser la liste des participants
+ this.loadParticipants();
+ },
+ (error) => {
+ console.error('Erreur lors de la création du participant', error);
+ }
+ );
+ }}
+ loadParticipants(): void {
+ this.participantService.getAllParticipant().subscribe(
+ (data) => {
+ this.participants = data; // Mettre à jour le tableau des participants
+ },
+ (error) => {
+ console.error('Erreur lors du chargement des participants:', error);
+ }
+ );
+ }
+
+
+ deleteParticipant(index: number) {
+ this.selectedUserIndex = index;
+ this.selectedUser = this.tableData1.dataRows[index];
+ this.showDeleteModal = true;
+ console.log("selectedParticipant!", this.selectedUser);
+ }
+
+ confirmDelete() {
+ const participantId = this.selectedUser[0]; // ID du participant sélectionné
+ console.log('Deleting participant with ID:', participantId);
+
+ // Effectuer la suppression
+ this.participantService.deleteParticipant(participantId).subscribe({
+ next: () => {
+ // Mettre à jour la liste des participants après suppression
+ this.loadParticipants(); // Recharger les participants
+ console.log('teeeeeeeeeessssssssssssssssssst:');
+ // Si le participant supprimé était dans la liste, réactualiser la sélection
+ this.showDeleteModal = false; // Fermer la modale de confirmation
+ this.selectedUserIndex = -1;
+ this.selectedUser = null;
+ },
+ error: (err) => {
+ console.error('Error deleting user:', err);
+ }
+ });
+ }
+
+ closeUserModal() {
+ this.showUserModal = false;
+ }
+
+ closeDeleteModal() {
+ this.showDeleteModal = false;
+ }
+}
diff --git a/src/app/search-pagination/search-pagination.component.css b/src/app/search-pagination/search-pagination.component.css
new file mode 100644
index 000000000..e69de29bb
diff --git a/src/app/search-pagination/search-pagination.component.html b/src/app/search-pagination/search-pagination.component.html
new file mode 100644
index 000000000..9da4dab7a
--- /dev/null
+++ b/src/app/search-pagination/search-pagination.component.html
@@ -0,0 +1,20 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/app/search-pagination/search-pagination.component.spec.ts b/src/app/search-pagination/search-pagination.component.spec.ts
new file mode 100644
index 000000000..7d1ded857
--- /dev/null
+++ b/src/app/search-pagination/search-pagination.component.spec.ts
@@ -0,0 +1,23 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { SearchPaginationComponent } from './search-pagination.component';
+
+describe('SearchPaginationComponent', () => {
+ let component: SearchPaginationComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ declarations: [ SearchPaginationComponent ]
+ })
+ .compileComponents();
+
+ fixture = TestBed.createComponent(SearchPaginationComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/src/app/search-pagination/search-pagination.component.ts b/src/app/search-pagination/search-pagination.component.ts
new file mode 100644
index 000000000..de64b1b5e
--- /dev/null
+++ b/src/app/search-pagination/search-pagination.component.ts
@@ -0,0 +1,32 @@
+import { Component, EventEmitter, Input, Output } from '@angular/core';
+
+@Component({
+ selector: 'app-search-pagination',
+ templateUrl: './search-pagination.component.html',
+ styleUrls: ['./search-pagination.component.css']
+})
+export class SearchPaginationComponent {
+ @Input() totalItems: number = 0;
+ @Input() pageSize: number = 5;
+ @Input() currentPage: number = 1;
+ @Output() pageChange = new EventEmitter();
+ @Output() searchChange = new EventEmitter();
+
+ searchTerm: string = '';
+
+ onSearchChange() {
+ this.searchChange.emit(this.searchTerm);
+ }
+
+ onPageChange(page: number) {
+ this.pageChange.emit(page);
+ }
+
+ get totalPages(): number {
+ return Math.ceil(this.totalItems / this.pageSize);
+ }
+
+ pages(): number[] {
+ return Array(this.totalPages).fill(0).map((x,i) => i+1);
+ }
+}
diff --git a/src/app/services/auth.service.ts b/src/app/services/auth.service.ts
new file mode 100644
index 000000000..d10f2d7e3
--- /dev/null
+++ b/src/app/services/auth.service.ts
@@ -0,0 +1,32 @@
+import { Injectable } from '@angular/core';
+import { HttpClient } from '@angular/common/http';
+import { Observable } from 'rxjs';
+
+@Injectable({
+ providedIn: 'root'
+})
+export class AuthService {
+ private apiUrl = 'http://localhost:8094/authenticate'; // URL du backend
+
+ constructor(private http: HttpClient) {}
+
+ login(credentials: { login: string, motDePasse: string }): Observable<{token: string}> {
+ return this.http.post<{token: string}>(this.apiUrl, credentials);
+ }
+
+ saveToken(token: string) {
+ localStorage.setItem('jwt', token);
+ }
+
+ getToken(): string | null {
+ return localStorage.getItem('jwt');
+ }
+
+ isLoggedIn(): boolean {
+ return !!this.getToken();
+ }
+
+ logout() {
+ localStorage.removeItem('jwt');
+ }
+}
diff --git a/src/app/services/employeur.service.spec.ts b/src/app/services/employeur.service.spec.ts
new file mode 100644
index 000000000..cc8431328
--- /dev/null
+++ b/src/app/services/employeur.service.spec.ts
@@ -0,0 +1,16 @@
+import { TestBed } from '@angular/core/testing';
+
+import { EmployeurService } from './employeur.service';
+
+describe('EmployeurService', () => {
+ let service: EmployeurService;
+
+ beforeEach(() => {
+ TestBed.configureTestingModule({});
+ service = TestBed.inject(EmployeurService);
+ });
+
+ it('should be created', () => {
+ expect(service).toBeTruthy();
+ });
+});
diff --git a/src/app/services/employeur.service.ts b/src/app/services/employeur.service.ts
new file mode 100644
index 000000000..e6293054e
--- /dev/null
+++ b/src/app/services/employeur.service.ts
@@ -0,0 +1,54 @@
+import { Injectable } from '@angular/core';
+import { HttpClient } from '@angular/common/http';
+import { catchError, Observable } from 'rxjs';
+import Swal from 'sweetalert2';
+
+@Injectable({
+ providedIn: 'root'
+})
+export class EmployeurService {
+ private apiUrl = 'http://localhost:8094/employeurs'; // URL du backend pour les employeurs
+
+ constructor(private http: HttpClient) { }
+
+ // Méthode pour obtenir tous les employeurs
+ getEmployeurs(): Observable {
+ console.log(this.http.get(this.apiUrl))
+ return this.http.get(this.apiUrl);
+
+ }
+
+ // Méthode pour créer un employeur
+ createEmployeur(employeur: any): Observable {
+ console.log(this.http.get(this.apiUrl))
+ return this.http.post(this.apiUrl, employeur);
+ }
+
+ // Méthode pour mettre à jour un employeur
+ updateEmployeur(employeurId: any, employeur: any): Observable {
+ console.log(this.http.get(this.apiUrl))
+ return this.http.put(`${this.apiUrl}/${employeurId}`, employeur);
+ }
+
+ // Méthode pour supprimer un employeur
+ deleteEmployeur(id: any): Observable {
+ return this.http.delete(`${this.apiUrl}/${id}`).pipe(
+ catchError((error) => {
+ // Si une erreur se produit lors de la requête HTTP, on la gère ici.
+ Swal.fire({
+ confirmButtonColor: '#d82c2c',
+ icon: 'error',
+ title: 'Erreur',
+ text: error.error.message || 'Une erreur est survenue lors de la suppression.',
+ });
+ throw error; // Lancer l'erreur à nouveau pour la gestion dans le composant si nécessaire
+ })
+ );
+ }
+
+
+ // Méthode pour obtenir un employeur par son ID
+ getEmployeurById(id: any): Observable {
+ return this.http.get(`${this.apiUrl}/${id}`);
+ }
+}
diff --git a/src/app/services/formateur-list.service.spec.ts b/src/app/services/formateur-list.service.spec.ts
new file mode 100644
index 000000000..a4d15b3d2
--- /dev/null
+++ b/src/app/services/formateur-list.service.spec.ts
@@ -0,0 +1,16 @@
+import { TestBed } from '@angular/core/testing';
+
+import { FormateurListService } from './formateur-list.service';
+
+describe('FormateurListService', () => {
+ let service: FormateurListService;
+
+ beforeEach(() => {
+ TestBed.configureTestingModule({});
+ service = TestBed.inject(FormateurListService);
+ });
+
+ it('should be created', () => {
+ expect(service).toBeTruthy();
+ });
+});
diff --git a/src/app/services/formateur-list.service.ts b/src/app/services/formateur-list.service.ts
new file mode 100644
index 000000000..8f111a5ee
--- /dev/null
+++ b/src/app/services/formateur-list.service.ts
@@ -0,0 +1,27 @@
+import { HttpClient } from '@angular/common/http';
+import { Injectable } from '@angular/core';
+import { Observable } from 'rxjs';
+
+@Injectable({
+ providedIn: 'root'
+})
+export class FormateurListService {
+ private apiUrl = 'http://localhost:8094/formateurs'; // URL du backend pour les formateurs
+
+ constructor(private http: HttpClient) { }
+
+ getAllFormateurs(): Observable {
+ return this.http.get(this.apiUrl);
+ }
+
+ createFormateur(formateur: any,employeurId: Number): Observable {
+ return this.http.post(`${this.apiUrl}?employeurId=${employeurId}`, formateur); }
+
+ updateFormateur(formateurId: number, formateur: any): Observable {
+ return this.http.put(`${this.apiUrl}/${formateurId}`, formateur);
+ }
+
+ deleteFormateur(formateurId: any): Observable {
+ return this.http.delete(`${this.apiUrl}/${formateurId}`);
+ }
+}
diff --git a/src/app/services/formation-list.service.spec.ts b/src/app/services/formation-list.service.spec.ts
new file mode 100644
index 000000000..454591644
--- /dev/null
+++ b/src/app/services/formation-list.service.spec.ts
@@ -0,0 +1,16 @@
+import { TestBed } from '@angular/core/testing';
+
+import { FormationListService } from './formation-list.service';
+
+describe('FormationListService', () => {
+ let service: FormationListService;
+
+ beforeEach(() => {
+ TestBed.configureTestingModule({});
+ service = TestBed.inject(FormationListService);
+ });
+
+ it('should be created', () => {
+ expect(service).toBeTruthy();
+ });
+});
diff --git a/src/app/services/formation-list.service.ts b/src/app/services/formation-list.service.ts
new file mode 100644
index 000000000..600c6e850
--- /dev/null
+++ b/src/app/services/formation-list.service.ts
@@ -0,0 +1,55 @@
+import { HttpClient, HttpParams } from '@angular/common/http';
+import { Injectable } from '@angular/core';
+import { Observable } from 'rxjs';
+
+@Injectable({
+ providedIn: 'root'
+})
+export class FormationListService {
+ private apiUrl = 'http://localhost:8094/formations';
+
+ constructor(private http: HttpClient) { }
+
+ getAllFormations(): Observable {
+ return this.http.get(this.apiUrl);
+ }
+ deleteFormation(formationId: any): Observable {
+ return this.http.delete(`${this.apiUrl}/${formationId}`);
+ }
+
+ getFormationParticipants(formationId:any): Observable {
+ return this.http.get(`${this.apiUrl}/${formationId}/participants`);
+ }
+
+ createFormation1(formation: any, formateurId: number, domaineId: number): Observable {
+ const params = new HttpParams()
+ .set('formateurId', formateurId.toString())
+ .set('domaineId', domaineId.toString());
+
+ return this.http.post(`${this.apiUrl}`, formation, { params });
+ }
+
+ updateFormation(formationId:number,formation: any, formateurId: number, domaineId: number): Observable {
+ const params = new HttpParams()
+ .set('formateurId', formateurId.toString())
+ .set('domaineId', domaineId.toString());
+
+ return this.http.put(`${this.apiUrl}/${formationId}`, formation, { params });
+ }
+
+ // EXECEPTION : getAllDomains
+ getAllDomaines(): Observable {
+ return this.http.get('http://localhost:8094/domaines');
+ }
+ addParticipantToFormation(formationId: number, participantId: number): Observable {
+ return this.http.post(
+ `${this.apiUrl}/${formationId}/participants/${participantId}`,
+ {}
+ );
+ }
+ removeParticipantFromFormation(formationId: number, participantId: number): Observable {
+ return this.http.delete(
+ `${this.apiUrl}/${formationId}/participants/${participantId}`
+ );
+ }
+}
diff --git a/src/app/services/participant-list.service.spec.ts b/src/app/services/participant-list.service.spec.ts
new file mode 100644
index 000000000..f5ba56654
--- /dev/null
+++ b/src/app/services/participant-list.service.spec.ts
@@ -0,0 +1,16 @@
+import { TestBed } from '@angular/core/testing';
+
+import { ParticipantListService } from './participant-list.service';
+
+describe('ParticipantListService', () => {
+ let service: ParticipantListService;
+
+ beforeEach(() => {
+ TestBed.configureTestingModule({});
+ service = TestBed.inject(ParticipantListService);
+ });
+
+ it('should be created', () => {
+ expect(service).toBeTruthy();
+ });
+});
diff --git a/src/app/services/participant-list.service.ts b/src/app/services/participant-list.service.ts
new file mode 100644
index 000000000..b172f2260
--- /dev/null
+++ b/src/app/services/participant-list.service.ts
@@ -0,0 +1,53 @@
+import { HttpClient } from '@angular/common/http';
+import { Injectable } from '@angular/core';
+import { Observable } from 'rxjs/internal/Observable';
+
+@Injectable({
+ providedIn: 'root'
+})
+export class ParticipantListService {
+
+ private apiUrl = 'http://localhost:8094/participants';
+
+ constructor(private http: HttpClient) { }
+
+ getAllParticipant() {
+ return this.http.get(this.apiUrl);
+ }
+
+ deleteParticipant(participantId: any){
+ return this.http.delete(`${this.apiUrl}/${participantId}`);
+ }
+
+ createParticipant(participant: any, profileId: number, structureId: number){
+ console.log(participant)
+ const body = {
+ ...participant
+ };
+ return this.http.post(this.apiUrl, body, {
+ params: {
+ profileId: profileId.toString(),
+ structureId: structureId.toString()
+ }
+ });
+ }
+
+ updateParticipant(participantId: number, participant: any): Observable {
+ const participantToSend = {
+ nom: participant.nom,
+ prenom: participant.prenom,
+ email: participant.email,
+ tel: participant.tel,
+ profile: { id: participant.profileId },
+ structure: { id: participant.structureId }
+ };
+
+ console.log('Participant envoyé :', participantToSend);
+
+ return this.http.put(`${this.apiUrl}/${participantId}`, participantToSend);
+ }
+
+
+
+
+}
diff --git a/src/app/services/user-list.service.spec.ts b/src/app/services/user-list.service.spec.ts
new file mode 100644
index 000000000..a65e883e1
--- /dev/null
+++ b/src/app/services/user-list.service.spec.ts
@@ -0,0 +1,16 @@
+import { TestBed } from '@angular/core/testing';
+
+import { UserListService } from './user-list.service';
+
+describe('UserListService', () => {
+ let service: UserListService;
+
+ beforeEach(() => {
+ TestBed.configureTestingModule({});
+ service = TestBed.inject(UserListService);
+ });
+
+ it('should be created', () => {
+ expect(service).toBeTruthy();
+ });
+});
diff --git a/src/app/services/user-list.service.ts b/src/app/services/user-list.service.ts
new file mode 100644
index 000000000..4caf6f151
--- /dev/null
+++ b/src/app/services/user-list.service.ts
@@ -0,0 +1,29 @@
+import { HttpClient } from '@angular/common/http';
+import { Injectable } from '@angular/core';
+import { Observable } from 'rxjs';
+
+@Injectable({
+ providedIn: 'root'
+})
+export class UserListService {
+ private apiUrl = 'http://localhost:8094/utilisateurs'; // URL du backend
+
+ constructor(private http: HttpClient) { }
+
+ getAllUsers() {
+ return this.http.get(this.apiUrl);
+ }
+
+
+ createUser(user: any, roleId: any): Observable {
+ return this.http.post(`${this.apiUrl}?roleId=${roleId}`, user);
+ }
+
+ updateUser(userId:any ,user: any, roleId: any): Observable {
+ return this.http.put(`${this.apiUrl}/${userId}?roleId=${roleId}`, user);
+ }
+
+ deleteUser(userId: any): Observable {
+ return this.http.delete(`${this.apiUrl}/${userId}`);
+ }
+}
diff --git a/src/app/shared/footer/footer.component.html b/src/app/shared/footer/footer.component.html
index 12fe1788b..c17954ad9 100644
--- a/src/app/shared/footer/footer.component.html
+++ b/src/app/shared/footer/footer.component.html
@@ -25,7 +25,7 @@
- © {{test | date: 'yyyy'}} Creative Tim, made with love for a better web
+ © {{test | date: 'yyyy'}} IMM made with love & kif for a better web
diff --git a/src/app/shared/navbar/navbar.component.html b/src/app/shared/navbar/navbar.component.html
index 6a5aca258..f9630c9ef 100644
--- a/src/app/shared/navbar/navbar.component.html
+++ b/src/app/shared/navbar/navbar.component.html
@@ -67,7 +67,7 @@
-
+
Log out
diff --git a/src/app/shared/navbar/navbar.component.ts b/src/app/shared/navbar/navbar.component.ts
index 068ed7ee8..4fa508b22 100644
--- a/src/app/shared/navbar/navbar.component.ts
+++ b/src/app/shared/navbar/navbar.component.ts
@@ -1,6 +1,7 @@
import { Component, OnInit, ElementRef } from '@angular/core';
import { ROUTES } from '../../sidebar/sidebar.component';
import {Location, LocationStrategy, PathLocationStrategy} from '@angular/common';
+import { Router } from '@angular/router';
@Component({
// moduleId: module.id,
@@ -14,7 +15,7 @@ export class NavbarComponent implements OnInit{
private toggleButton: any;
private sidebarVisible: boolean;
- constructor(location: Location, private element: ElementRef) {
+ constructor(location: Location, private element: ElementRef , private router: Router) {
this.location = location;
this.sidebarVisible = false;
}
@@ -63,4 +64,9 @@ export class NavbarComponent implements OnInit{
}
return 'Dashboard';
}
+
+ logout() {
+ localStorage.removeItem('token'); // Supprime le token
+ this.router.navigate(['/login']); // Redirige vers la page de connexion
+ }
}
diff --git a/src/app/sidebar/sidebar.component.html b/src/app/sidebar/sidebar.component.html
index 817b194c6..dfe3fd145 100644
--- a/src/app/sidebar/sidebar.component.html
+++ b/src/app/sidebar/sidebar.component.html
@@ -1,11 +1,11 @@