Compare commits

..

3 Commits

Author SHA1 Message Date
Antoine PEREDERII e72636c4d7 Update 'Sources/config/config.php'
continuous-integration/drone/push Build is passing Details
1 year ago
Antoine PEREDERII 97623ba062 Merge branch 'master' of codefirst.iut.uca.fr:HeartDev/Web
continuous-integration/drone/push Build is passing Details
1 year ago
Antoine PEREDERII 32afdd093c 📝 Add MCD on the readme file
1 year ago

@ -1,6 +1,6 @@
kind: pipeline kind: pipeline
type: docker type: docker
name: HeartTrack name: HeartWave
trigger: trigger:
event: event:
@ -14,10 +14,9 @@ steps:
- cd Sources - cd Sources
- rm -r vendor - rm -r vendor
- rm composer.lock - rm composer.lock
#- apk update && apk add --no-cache libcouchbase-dev && pecl install couchbase && docker-php-ext-enable couchbase
# Installe les dépendances PHP si nécessaire # Installe les dépendances PHP si nécessaire
- php composer.phar install --no-interaction - php composer.phar install --no-interaction
# - ./vendor/bin/phpunit tests - ./vendor/bin/phpunit tests
# Sonar static code analisis deployment # Sonar static code analisis deployment
# TODO : use an image that already have unzip # TODO : use an image that already have unzip
@ -36,16 +35,16 @@ steps:
- export SONAR_SCANNER_OPTS="-server" - export SONAR_SCANNER_OPTS="-server"
- cd Sources - cd Sources
- sonar-scanner -D sonar.projectKey=HeartTrack -D sonar.host.url=https://codefirst.iut.uca.fr/sonar - sonar-scanner -D sonar.projectKey=HeartTrack -D sonar.host.url=https://codefirst.iut.uca.fr/sonar
#depends_on: [ test ] depends_on: [ test ]
# build image and push on the registry ✔️ # build image and push on the registry ✔️
- name: rewrite-urls - name: rewrite-urls
image: 'busybox:latest' image: 'busybox:latest'
commands: commands:
- cd Sources - cd Sources
- ls - ls
#- >- - >-
# find . -type f -exec sed -i -r find . -type f -exec sed -i -r
# "s@(href|src)=\"/@\1=\"$${PLUGIN_CONTAINER_PATH}@g" {} + "s@(href|src)=\"/@\1=\"$${PLUGIN_CONTAINER_PATH}@g" {} +
settings: settings:
container_path: https://codefirst.iut.uca.fr/containers/HeartDev-web/ container_path: https://codefirst.iut.uca.fr/containers/HeartDev-web/
@ -72,7 +71,20 @@ steps:
IMAGENAME: 'hub.codefirst.iut.uca.fr/david.d_almeida/web:latest' IMAGENAME: 'hub.codefirst.iut.uca.fr/david.d_almeida/web:latest'
CONTAINERNAME: web CONTAINERNAME: web
COMMAND: create COMMAND: create
#OVERWRITE: true OVERWRITE: true
ADMINS: davidd_almeida,kevinmonteiro,antoineperederii,paullevrault,antoinepinagot ADMINS: david.d_almeida
depends_on: depends_on:
- docker-build-and-push - docker-build-and-push
- name: notify
image: ruby:2.1
when:
status: [ success ]
ref:
include:
- refs/tags/*-demo
commands:
- sh ./notifymail.sh
depends_on: [ docker-build-and-push ]

@ -11,7 +11,6 @@ entity "Athlète" as athlete {
poids poids
motDePasse motDePasse
dateNaissance dateNaissance
isCoach
} }
entity "Amitié" as friendship{ entity "Amitié" as friendship{
@ -29,7 +28,11 @@ entity "Notification" as notif {
#athleteId #athleteId
} }
entity "Coach" as coach {
{static} idCoach
// attributs spécifiques au coach
#athleteId
}
entity "Statistique" as stats { entity "Statistique" as stats {
{static} idStatistique {static} idStatistique
@ -49,7 +52,7 @@ entity "Entraînement" as training {
latitude latitude
longitude longitude
feedback feedback
#athleteId #coachId
} }
entity "Participe" as takepart { entity "Participe" as takepart {
@ -98,12 +101,13 @@ entity "FréquenceCardiaque" as fc {
activity --> athlete activity --> athlete
activity --> source activity --> source
activity <-- fc activity <-- fc
coach --> athlete
athlete <-- source athlete <-- source
stats --> athlete stats --> athlete
takepart --> athlete takepart --> athlete
takepart --> training takepart --> training
friendship --> athlete friendship --> athlete
notif --> athlete notif --> athlete
athlete <-- training coach <-- training
athlete <-- friendship athlete <-- friendship
@enduml @enduml

@ -179,9 +179,10 @@ athlete <-- friendship
```plantuml ```plantuml
@startuml @startuml
skinparam classAttributeIconSize 0
class Athlete { package MCD{
idAthlete entity "Athlete" as athlete {
{static} idAthlete
username username
nom nom
prenom prenom
@ -194,65 +195,45 @@ class Athlete {
isCoach isCoach
} }
class Amitie { entity "Notification" as notif {
idAthlete1 {static} idNotif
idAthlete2
}
class Notification {
idNotif
message message
date date
statut statut
urgence urgence
athleteId #athleteId
}
class Envoi {
idAthlete
idNotif
} }
class Statistique { entity "Statistique" as stats {
idStatistique {static} idStatistique
poids poids
fcMoyenne fcMoyenne
fcMax fcMax
caloriesBruleesMoy caloriesBruleesMoy
date date
athleteId #athleteId
} }
class Entrainement { entity "Entrainement" as training {
idEntrainement {static} idEntrainement
date date
description description
latitude latitude
longitude longitude
feedback feedback
athleteId #athleteId
}
class Participe {
athleteId
entrainementId
}
class Donne {
coachId
entrainementId
} }
class SourceDonnee { entity "SourceDonnee" as source {
idSource {static} idSource
type type
modele modele
precision precision
athleteId #athleteId
} }
class Activite { entity "Activite" as activity {
idActivite {static} idActivité
type type
date date
heureDeDebut heureDeDebut
@ -265,29 +246,31 @@ class Activite {
maximum maximum
minimum minimum
temperatureMoyenne temperatureMoyenne
athleteId #athleteId
sourceId #sourceId
} }
class FrequenceCardiaque { entity "FréquenceCardiaque" as fc {
idFc {static} idFc
altitude altitude
temps temps : time
temperature température
bpm bpm
longitude longitude
latitude latitude
activiteId #activitéId
} }
Athlete "1" --o "0..*" Amitie }
Athlete "1" --o "0..*" Notification activity "0..n" --- "1..1" athlete : réalise
Athlete "1" --o "0..*" Statistique activity "1..n" --- "1..1" source : possede
Athlete "1" --o "0..*" Entrainement activity "1..1" --- "1..n" fc : enregistre
Entrainement "0..*" --o "0..*" Athlete : Participants athlete "1..n" --- "0..1" source : possede
Entrainement "0..*" --o "0..*" Athlete : Coachs stats "0..n" --- "1..1" athlete : possede
Athlete "1" --o "0..*" SourceDonnee training "0..n" --- "1..n" athlete : participe
Activite "1" --o "0..*" FrequenceCardiaque training "0..n" --- "1..1" athlete : donne
athlete "0..n" --- "1..n" athlete : est ami
notif "0..n" --- "1..n" athlete : recoit
notif "0..n" --- "1..1" athlete : envoie
@enduml @enduml
``` ```

@ -18,7 +18,7 @@ Bienvenue dans le cœur de notre système, où les données prennent vie à trav
- **NotificationRepository :** Responsable de la gestion des notifications, assurant un accès structuré et une manipulation sécurisée de ces informations cruciales. - **NotificationRepository :** Responsable de la gestion des notifications, assurant un accès structuré et une manipulation sécurisée de ces informations cruciales.
- **RelationshipRequestRepository :** Facilite la gestion des demandes de relations entre utilisateurs, garantissant une interaction claire et ordonnée. - **RelationshipRequestRepository :** Facilite la gestion des demandes de relations entre utilisateurs (amitiés), garantissant une interaction claire et ordonnée au sein de l'application.
- **TrainingRepository :** Permet l'accès et la manipulation des données liées aux entraînements, facilitant le suivi des performances athlétiques. - **TrainingRepository :** Permet l'accès et la manipulation des données liées aux entraînements, facilitant le suivi des performances athlétiques.
@ -26,7 +26,7 @@ Explorez ce diagramme pour découvrir la robustesse de notre architecture de ges
```plantuml ```plantuml
@startuml couche_acces_aux_donnees @startuml couche_acces_aux_donnees
abstract class IGenericRepository { interface IGenericRepository {
+ getItemById(int id) : object + getItemById(int id) : object
+ getNbItems() : int + getNbItems() : int
+ getItems(int index, int count, string orderingPropertyName, bool descending) : array + getItems(int index, int count, string orderingPropertyName, bool descending) : array

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 48 KiB

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 MiB

After

Width:  |  Height:  |  Size: 27 KiB

@ -71,7 +71,8 @@ Documentation et informations à propos de `HearthTrack` disponible [ici]()
### Prerequisites ### Prerequisites
* [Visual Studio code](https://code.visualstudio.com/) - exemple d'IDE gratuit * [Visual Studio code](https://code.visualstudio.com/) - exemple d'IDE gratuit
* [Git](https://git-scm.com/) - Versioning * [Git](https://git-scm.com/) - Versioning
* [XAMPP : X, Apache, MySQL, Perl, PHP](https://www.apachefriends.org/fr/index.html) - Langages * [XAMPP : X, Apache, MySQL, Perl, PHP](https://www.apachefriends.org/fr/index.html) - Languages
* [PostgreSQL](https://www.postgresql.org/) - Base de Donnée
## Getting Started ## Getting Started
1. Cloner le répos 1. Cloner le répos

@ -18,14 +18,13 @@
"Shared\\": "src/shared", "Shared\\": "src/shared",
"App\\Router\\": "src/app/router", "App\\Router\\": "src/app/router",
"App\\Controller\\": "src/app/controller", "App\\Controller\\": "src/app/controller",
"App\\Router\\Response\\": "src/app/router/response", "App\\Router\\Response\\" : "src/app/router/response",
"App\\Router\\Middleware\\": "src/app/router/middleware", "App\\Router\\Middleware\\" : "src/app/router/middleware",
"App\\Router\\Request\\": "src/app/router/request", "App\\Router\\Request\\" : "src/app/router/request",
"Shared\\Exception\\": "src/shared/exception", "Shared\\Exception\\": "src/shared/exception",
"Shared\\Attributes\\": "src/shared/attributes", "Shared\\Attributes\\": "src/shared/attributes",
"App\\Views\\Directives\\": "src/app/views/directives", "App\\Views\\Directives\\" : "src/app/views/directives",
"Data\\Core\\": "src/data/core/", "Data\\Core\\": "src/data/core/"
"Database\\": "src/data/core/database"
} }
}, },
"require": { "require": {
@ -35,15 +34,12 @@
"psr/container": "^2.0", "psr/container": "^2.0",
"adriangibbons/php-fit-file-analysis": "^3.2.0" "adriangibbons/php-fit-file-analysis": "^3.2.0"
}, },
"config": {
"process-timeout": 2000
},
"require-dev": { "require-dev": {
"phpunit/phpunit": "*" "phpunit/phpunit": "*"
}, },
"scripts": { "scripts": {
"dev": "php -S localhost:8080 -t public -d display_errors=1 -d error_reporting=E_ALL", "dev": "php -S localhost:8080 -t public -d display_errors=1 -d error_reporting=E_ALL",
"dev:console": "export APP_ENV=console && php public/index.php", "dev:console": "export APP_ENV=console && php public/index.php",
"dev:html": "export APP_ENV=html && php -S localhost:8080 -t public -d display_errors=1 -d error_reporting=E_ALL" "dev:html" : "export APP_ENV=html && php -S localhost:8080 -t public -d display_errors=1 -d error_reporting=E_ALL"
} }
} }

549
Sources/composer.lock generated

File diff suppressed because it is too large Load Diff

@ -28,4 +28,4 @@ RUN composer install
EXPOSE 80 EXPOSE 80
CMD composer dev CMD ["apache2-foreground"]

@ -1,17 +0,0 @@
FROM php:8.2-fpm
# Installation de dépendances nécessaires pour Composer
RUN apt-get update && apt-get install -y \
git \
unzip
# Installation de Composer
# TODO : should use a image with composer install
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
RUN docker-php-ext-install pdo pdo_mysql
COPY . /var/www/
WORKDIR /var/www/
RUN composer install

@ -5,18 +5,18 @@ use Shared\Log;
$dotenv = Dotenv::createUnsafeImmutable(__DIR__,'.env'); $dotenv = Dotenv::createUnsafeImmutable(__DIR__,'.env');
$dotenv->safeLoad(); $dotenv->safeLoad();
// echo($_ENV);
// apenrently getEnv is not a good thing cause // apenrently getEnv is not a good thing cause
// const DB_HOST = $_ENV['DB_HOST'] ?? 'localhost'; // const DB_HOST = $_ENV['DB_HOST'] ?? 'localhost';
// const DB_DATABASE = $_ENV['DB_DATABASE'] ?? 'heartTrack'; // const DB_DATABASE = $_ENV['DB_DATABASE'] ?? 'heartTrack';
// const DB_USER = $_ENV['DB_USER'] ?? 'toto'; // const DB_USER = $_ENV['DB_USER'] ?? 'toto';
// const DB_PASSWORD = $_ENV['DB_PASSWORD'] ?? 'achanger'; // const DB_PASSWORD = $_ENV['DB_PASSWORD'] ?? 'achanger';
define("APP_ENV", 'development');
define("APP_ENV", getenv('APP_ENV')); const DB_HOST = 'localhost';
const DB_DATABASE = 'heartTrack';
const DB_HOST = 'mysql'; const DB_USER = 'toto';
const DB_DATABASE = 'test'; const DB_PASSWORD = 'achanger';
const DB_USER = 'user';
const DB_PASSWORD = 'pass';
//const APP_ENV = 'console'; //const APP_ENV = 'console';
const DSN = "mysql:host=" . DB_HOST . ";dbname=" . DB_DATABASE; const DSN = "mysql:host=" . DB_HOST . ";dbname=" . DB_DATABASE;

@ -1,28 +1,19 @@
server { server {
listen 80; listen 80;
index index.php; index index.php index.html index.htm;
root /var/www/public; root /usr/share/nginx/html;
error_page 404 /index.php; error_page 404 /index.php;
location ~ ^/(images|javascript|js|css|flash|media|static)/ {
root /var/www/public;
}
location ~ \.php$ { location ~ \.php$ {
fastcgi_pass web:9000; # service name defined in docker-compose.yml file like web
fastcgi_param REQUEST_METHOD $request_method; fastcgi_param REQUEST_METHOD $request_method;
fastcgi_index index.php; fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params; include fastcgi_params;
} }
location ~ /\. {
deny all;
access_log off;
log_not_found off;
}
location / { location / {
try_files $uri $uri/ /index.php?$query_string; root /usr/share/nginx/html;
try_files $uri /index.php;
} }
} }

@ -1,91 +0,0 @@
<?php
namespace Database;
class AthleteEntity {
private $idAthlete;
private $nom;
private $prenom;
private $email;
private $sexe;
private $taille;
private $poids;
private $motDePasse;
private $dateNaissance;
// Getters
public function getIdAthlete() {
return $this->idAthlete;
}
public function getNom() {
return $this->nom;
}
public function getPrenom() {
return $this->prenom;
}
public function getEmail() {
return $this->email;
}
public function getSexe() {
return $this->sexe;
}
public function getTaille() {
return $this->taille;
}
public function getPoids() {
return $this->poids;
}
public function getMotDePasse() {
return $this->motDePasse;
}
public function getDateNaissance() {
return $this->dateNaissance;
}
// Setters
public function setIdAthlete($idAthlete) {
$this->idAthlete = $idAthlete;
}
public function setNom($nom) {
$this->nom = $nom;
}
public function setPrenom($prenom) {
$this->prenom = $prenom;
}
public function setEmail($email) {
$this->email = $email;
}
public function setSexe($sexe) {
$this->sexe = $sexe;
}
public function setTaille($taille) {
$this->taille = $taille;
}
public function setPoids($poids) {
$this->poids = $poids;
}
public function setMotDePasse($motDePasse) {
$this->motDePasse = $motDePasse;
}
public function setDateNaissance($dateNaissance) {
$this->dateNaissance = $dateNaissance;
}
}
?>

@ -1,131 +0,0 @@
<?php
namespace Database;
use \PDO;
class AthleteGateway {
private $connection;
public function __construct(Connexion $connection) {
$this->connection = $connection;
}
public function getAthlete() {
$query = "SELECT * FROM Athlete";
return $this->connection->executeWithErrorHandling($query);
}
public function getAthleteById(int $userId) {
$query = "SELECT * FROM Athlete WHERE idAthlete = :id";
$params = [':id' => [$userId, PDO::PARAM_INT]];
return $this->connection->executeWithErrorHandling($query, $params);
}
public function getAthleteByName(string $name) {
$query = "SELECT * FROM Athlete WHERE nom = :name";
$params = [':name' => [$name, PDO::PARAM_STR]];
return $this->connection->executeWithErrorHandling($query, $params);
}
public function getAthleteByFirstName(string $firstName) {
$query = "SELECT * FROM Athlete WHERE prenom = :firstName";
$params = [':firstName' => [$firstName, PDO::PARAM_STR]];
return $this->connection->executeWithErrorHandling($query, $params);
}
public function getAthleteByEmail(string $email) {
$query = "SELECT * FROM Athlete WHERE email = :email";
$params = [':email' => [$email, PDO::PARAM_STR]];
return $this->connection->executeWithErrorHandling($query, $params);
}
public function getAthleteByGender(string $gender) {
$query = "SELECT * FROM Athlete WHERE sexe = :gender";
$params = [':gender' => [$gender, PDO::PARAM_STR]];
return $this->connection->executeWithErrorHandling($query, $params);
}
public function getAthleteByHeight(int $height) {
$query = "SELECT * FROM Athlete WHERE taille = :height";
$params = [':height' => [$height, PDO::PARAM_INT]];
return $this->connection->executeWithErrorHandling($query, $params);
}
public function getAthleteByWeight(int $weight) {
$query = "SELECT * FROM Athlete WHERE poids = :weight";
$params = [':weight' => [$weight, PDO::PARAM_INT]];
return $this->connection->executeWithErrorHandling($query, $params);
}
public function getAthleteByBirthDate(string $birthdate) {
$query = "SELECT * FROM Athlete WHERE dateNaissance = :birthdate";
$params = [':birthdate' => [$birthdate, PDO::PARAM_STR]];
return $this->connection->executeWithErrorHandling($query, $params);
}
public function addAthlete(AthleteEntity $athlete) {
$query = "INSERT INTO Athlete (nom, prenom, email, sexe, taille, poids, motDePasse, dateNaissance)
VALUES (:nom, :prenom, :email, :sexe, :taille, :poids, :motDePasse, :dateNaissance)";
$params = [
':nom' => $athlete->getNom(),
':prenom' => $athlete->getPrenom(),
':email' => $athlete->getEmail(),
':sexe' => $athlete->getSexe(),
':taille' => $athlete->getTaille(),
':poids' => $athlete->getPoids(),
':motDePasse' => $athlete->getMotDePasse(),
':dateNaissance' => $athlete->getDateNaissance(),
];
return $this->connection->executeWithErrorHandling($query, $params);
}
public function updateAthlete(AthleteEntity $oldAthlete, AthleteEntity $newAthlete) {
$query = "UPDATE Athlete
SET nom = :nom, prenom = :prenom, email = :email, sexe = :sexe,
taille = :taille, poids = :poids, motDePasse = :motDePasse, dateNaissance = :dateNaissance
WHERE idAthlete = :idAthlete";
$params = [
':idAthlete' => $oldAthlete->getIdAthlete(),
':nom' => $newAthlete->getNom(),
':prenom' => $newAthlete->getPrenom(),
':email' => $newAthlete->getEmail(),
':sexe' => $newAthlete->getSexe(),
':taille' => $newAthlete->getTaille(),
':poids' => $newAthlete->getPoids(),
':motDePasse' => $newAthlete->getMotDePasse(),
':dateNaissance' => $newAthlete->getDateNaissance(),
];
return $this->connection->executeWithErrorHandling($query, $params);
}
public function deleteAthlete(int $idAthlete) {
$query = "DELETE FROM Athlete WHERE idAthlete = :idAthlete";
$params = [
':idAthlete' => $idAthlete,
];
return $this->connection->executeWithErrorHandling($query, $params);
}
}
// Exemple d'utilisation
//$dsn = "pgsql:host=localhost;port=5432;dbname=mydatabase;user=myuser;password=mypassword";
//$connection = new Connection($dsn);
//$gateway = new AthleteGateway($connection);
//$allAth = $gateway->getAthlete();
//print_r($allAth);
//$singleAth = $gateway->getAthleteById(1);
//print_r($singleAth);
?>

@ -1,99 +0,0 @@
<?php
namespace Database;
use Model\User;
use \PDO;
use \DateTime;
use Model\Role;
use Model\Athlete;
class AthleteMapper {
public function fromSqlToEntity(array $data): array {
$athleteEntities = [];
foreach ($data as $athleteData) {
$athlete = new AthleteEntity();
if (isset($athleteData['idAthlete'])) {
$athlete->setIdAthlete($athleteData['idAthlete']);
}
if (isset($athleteData['nom'])) {
$athlete->setNom($athleteData['nom']);
}
if (isset($athleteData['prenom'])) {
$athlete->setPrenom($athleteData['prenom']);
}
if (isset($athleteData['email'])) {
$athlete->setEmail($athleteData['email']);
}
if (isset($athleteData['sexe'])) {
$athlete->setSexe($athleteData['sexe']);
}
if (isset($athleteData['taille'])) {
$athlete->setTaille($athleteData['taille']);
}
if (isset($athleteData['poids'])) {
$athlete->setPoids($athleteData['poids']);
}
if (isset($athleteData['motDePasse'])) {
$athlete->setMotDePasse($athleteData['motDePasse']);
}
if (isset($athleteData['dateNaissance'])) {
$athlete->setDateNaissance($athleteData['dateNaissance']);
}
$athleteEntities[] = $athlete;
}
return $athleteEntities;
}
public function athleteEntityToModel(AthleteEntity $athleteEntity): User {
$role = new Athlete(); // Utilisez la classe Athlete
$dateSpecifique = $athleteEntity->getDateNaissance();
$date = new DateTime($dateSpecifique);
$user = new User(
$athleteEntity->getIdAthlete(),
$athleteEntity->getNom(),
$athleteEntity->getPrenom(),
$athleteEntity->getEmail(),
$athleteEntity->getMotDePasse(),
$athleteEntity->getSexe(),
$athleteEntity->getTaille(),
$athleteEntity->getPoids(),
$date,
$role
);
return $user;
}
public function athleteToEntity(User $user):AthleteEntity{
$ath = new AthleteEntity();
$ath->setIdAthlete($user->getId());
$ath->setNom($user->getNom());
$ath->setPrenom($user->getPrenom());
$ath->setEmail($user->getEmail());
$ath->setSexe($user->getSexe());
$ath->setTaille($user->getTaille());
$ath->setPoids($user->getPoids());
$ath->setMotDePasse($user->getMotDePasse());
$ath->setDateNaissance($user->getDateNaissance());
return $ath;
}
}
?>

@ -1,91 +0,0 @@
<?php
namespace Database;
class CoachEntity {
private $idCoach;
private $nom;
private $prenom;
private $email;
private $sexe;
private $taille;
private $poids;
private $motDePasse;
private $dateNaissance;
// Getters
public function getIdCoach() {
return $this->idCoach;
}
public function getNom() {
return $this->nom;
}
public function getPrenom() {
return $this->prenom;
}
public function getEmail() {
return $this->email;
}
public function getSexe() {
return $this->sexe;
}
public function getTaille() {
return $this->taille;
}
public function getPoids() {
return $this->poids;
}
public function getMotDePasse() {
return $this->motDePasse;
}
public function getDateNaissance() {
return $this->dateNaissance;
}
// Setters
public function setIdCoach($idCoach) {
$this->idCoach = $idCoach;
}
public function setNom($nom) {
$this->nom = $nom;
}
public function setPrenom($prenom) {
$this->prenom = $prenom;
}
public function setEmail($email) {
$this->email = $email;
}
public function setSexe($sexe) {
$this->sexe = $sexe;
}
public function setTaille($taille) {
$this->taille = $taille;
}
public function setPoids($poids) {
$this->poids = $poids;
}
public function setMotDePasse($motDePasse) {
$this->motDePasse = $motDePasse;
}
public function setDateNaissance($dateNaissance) {
$this->dateNaissance = $dateNaissance;
}
}
?>

@ -1,109 +0,0 @@
<?php
namespace Database;
use \PDO;
class CoachGateway {
private $connection;
public function __construct(Connexion $connection) {
$this->connection = $connection;
}
public function getCoach() {
$query = "SELECT * FROM Athlete WHERE isCoach = TRUE;";
return $this->connection->executeWithErrorHandling($query);
}
public function getCoachById(int $userId) {
$query = "SELECT * FROM Athlete WHERE idAthlete = :id AND isCoach = TRUE";
$params = [':id' => [$userId, PDO::PARAM_INT]];
return $this->connection->executeWithErrorHandling($query, $params);
}
public function getCoachByName(string $name) {
$query = "SELECT * FROM Athlete WHERE nom = :name AND isCoach = TRUE";
$params = [':name' => [$name, PDO::PARAM_STR]];
return $this->connection->executeWithErrorHandling($query, $params);
}
public function getCoachByFirstName(string $firstName) {
$query = "SELECT * FROM Athlete WHERE prenom = :firstName AND isCoach = TRUE";
$params = [':firstName' => [$firstName, PDO::PARAM_STR]];
return $this->connection->executeWithErrorHandling($query, $params);
}
public function getCoachByEmail(string $email) {
$query = "SELECT * FROM Athlete WHERE email = :email AND isCoach = TRUE";
$params = [':email' => [$email, PDO::PARAM_STR]];
return $this->connection->executeWithErrorHandling($query, $params);
}
public function getCoachByGender(string $gender) {
$query = "SELECT * FROM Athlete WHERE sexe = :gender AND isCoach = TRUE";
$params = [':gender' => [$gender, PDO::PARAM_STR]];
return $this->connection->executeWithErrorHandling($query, $params);
}
public function getCoachByHeight(int $height) {
$query = "SELECT * FROM Athlete WHERE taille = :height AND isCoach = TRUE";
$params = [':height' => [$height, PDO::PARAM_INT]];
return $this->connection->executeWithErrorHandling($query, $params);
}
public function getCoachByBirthDate(string $birthdate) {
$query = "SELECT * FROM Athlete WHERE dateNaissance = :birthdate AND isCoach = TRUE";
$params = [':birthdate' => [$birthdate, PDO::PARAM_STR]];
return $this->connection->executeWithErrorHandling($query, $params);
}
public function addCoach(CoachEntity $coach) {
$query = "INSERT INTO Athlete (nom, prenom, email, sexe, taille, poids, motDePasse, dateNaissance, isCoach)
VALUES (:nom, :prenom, :email, :sexe, :taille, :poids, :motDePasse, :dateNaissance, TRUE)";
$params = [
':nom' => $coach->getNom(),
':prenom' => $coach->getPrenom(),
':email' => $coach->getEmail(),
':sexe' => $coach->getSexe(),
':taille' => $coach->getTaille(),
':poids' => $coach->getPoids(),
':motDePasse' => $coach->getMotDePasse(),
':dateNaissance' => $coach->getDateNaissance(),
];
return $this->connection->executeWithErrorHandling($query, $params);
}
public function updateCoach(CoachEntity $oldCoach, CoachEntity $newCoach) {
$query = "UPDATE Athlete
SET nom = :nom, prenom = :prenom, email = :email, sexe = :sexe,
taille = :taille, poids = :poids, motDePasse = :motDePasse, dateNaissance = :dateNaissance, isCoach = TRUE
WHERE idCoach = :idCoach";
$params = [
':idAthlete' => $oldCoach->getIdCoach(),
':nom' => $newCoach->getNom(),
':prenom' => $newCoach->getPrenom(),
':email' => $newCoach->getEmail(),
':sexe' => $newCoach->getSexe(),
':taille' => $newCoach->getTaille(),
':poids' => $newCoach->getPoids(),
':motDePasse' => $newCoach->getMotDePasse(),
':dateNaissance' => $newCoach->getDateNaissance(),
];
return $this->connection->executeWithErrorHandling($query, $params);
}
public function deleteCoach(int $idCoach) {
$query = "DELETE FROM Athlete WHERE idAthlete = :idCoach";
$params = [
':idCoach' => $idCoach,
];
return $this->connection->executeWithErrorHandling($query, $params);
}
}

@ -1,62 +0,0 @@
<?php
namespace Database;
use Model\User;
use \PDO;
use \DateTime;
use Model\Role;
use Model\Coach;
class CoachMapper {
public function map(array $data) {
$coach = new CoachEntity();
$coach->setIdCoach($data['idCoach']);
$coach->setNom($data['nom']);
$coach->setPrenom($data['prenom']);
$coach->setEmail($data['email']);
$coach->setSexe($data['sexe']);
$coach->setTaille($data['taille']);
$coach->setPoids($data['poids']);
$coach->setMotDePasse($data['motDePasse']);
$coach->setDateNaissance($data['dateNaissance']);
return $coach;
}
public function CoachEntityToModel(CoachEntity $coachEntity):User{
$role = "Coach";
$user = new User(
$coachEntity->getIdCoach(),
$coachEntity->getNom(),
$coachEntity->getPrenom(),
$coachEntity->getEmail(),
$coachEntity->getMotDePasse(),
$coachEntity->getSexe(),
$coachEntity->getTaille(),
$coachEntity->getPoids(),
$coachEntity->getDateNaissance(),
$role
);
return $user;
}
public function CoachToEntity(User $user):CoachEntity{
$coach = new CoachEntity();
$coach->setIdCoach($user->getId());
$coach->setNom($user->getNom());
$coach->setPrenom($user->getPrenom());
$coach->setEmail($user->getEmail());
$coach->setSexe($user->getSexe());
$coach->setTaille($user->getTaille());
$coach->setPoids($user->getPoids());
$coach->setMotDePasse($user->getMotDePasse());
$coach->setDateNaissance($user->getDateNaissance());
return $coach;
}
}
?>

@ -1,49 +0,0 @@
<?php
namespace Database;
class Connexion extends \PDO {
private $stmt;
public function __construct(string $dsn,string $username, string $password) {
try {
parent::__construct($dsn,$username,$password);
$this->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
} catch (\PDOException $e) {
// Log error or handle it as needed
throw new \PDOException("Error connecting to the database: " . $e->getMessage());
}
}
public function executeQuery(string $query, array $parameters = []): bool {
$this->stmt = $this->prepare($query);
//foreach ($parameters as $name => $value) {
// $this->stmt->bindValue($name, $value[0], $value[1]);
//}
foreach ($parameters as $name => $value) {
$bindValueResult = $this->stmt->bindValue($name, $value, \PDO::PARAM_STR);
if (!$bindValueResult) {
// Gérez l'erreur, par exemple, en lançant une exception.
throw new \PDOException('Failed to bind value for parameter ' . $name);
}
}
return $this->stmt->execute();
}
public function executeWithErrorHandling(string $query, array $params = []): array {
try {
$this->beginTransaction();
$this->executeQuery($query, $params);
$this->commit();
return $this->getResults();
} catch (\PDOException $e) {
$this->rollBack();
throw new \PDOException('Unexpected error on database client: ' . $e->getMessage());
}
}
public function getResults(): array {
return $this->stmt->fetchAll(\PDO::FETCH_ASSOC);
}
}
?>

@ -1,133 +0,0 @@
DROP TABLE IF EXISTS Athlete, Friendship, Notification, Statistique, Entrainement, Participe, SourceDonnee, Activite, FrequenceCardiaque CASCADE;
CREATE TABLE Athlete (
idAthlete INT PRIMARY KEY,
nom VARCHAR(255),
prenom VARCHAR(255),
email VARCHAR(255) UNIQUE,
sexe CHAR(1),
taille DECIMAL,
poids DECIMAL,
motDePasse VARCHAR(255),
dateNaissance DATE,
isCoach BOOLEAN
);
CREATE TABLE Friendship (
idAthlete1 INT,
idAthlete2 INT,
debut DATE,
PRIMARY KEY (idAthlete1, idAthlete2),
FOREIGN KEY (idAthlete1) REFERENCES Athlete(idAthlete),
FOREIGN KEY (idAthlete2) REFERENCES Athlete(idAthlete)
);
CREATE TABLE Notification (
idNotif INT PRIMARY KEY,
message TEXT,
date DATE,
statut BOOLEAN,
urgence INT,
athleteId INT,
FOREIGN KEY (athleteId) REFERENCES Athlete(idAthlete)
);
CREATE TABLE Statistique (
idStatistique INT PRIMARY KEY,
poids DECIMAL,
fcMoyenne DECIMAL,
fcMax DECIMAL,
caloriesBruleesMoy DECIMAL,
date DATE,
athleteId INT,
FOREIGN KEY (athleteId) REFERENCES Athlete(idAthlete)
);
CREATE TABLE Entrainement (
idEntrainement INT PRIMARY KEY,
date DATE,
description TEXT,
latitude DECIMAL,
longitude DECIMAL,
feedback TEXT,
athleteId INT,
FOREIGN KEY (athleteId) REFERENCES Athlete(idAthlete)
);
CREATE TABLE Participe (
athleteId INT,
entrainementId INT,
PRIMARY KEY (athleteId, entrainementId),
FOREIGN KEY (athleteId) REFERENCES Athlete(idAthlete),
FOREIGN KEY (entrainementId) REFERENCES Entrainement(idEntrainement)
);
CREATE TABLE SourceDonnee (
idSource INT PRIMARY KEY,
type VARCHAR(255),
modele VARCHAR(255),
precision2 DECIMAL,
athleteId INT,
FOREIGN KEY (athleteId) REFERENCES Athlete(idAthlete)
);
CREATE TABLE Activite (
idActivite INT PRIMARY KEY,
type VARCHAR(255),
date DATE,
heureDeDebut TIME,
heureDeFin TIME,
effortRessent DECIMAL,
variabilite DECIMAL,
variance DECIMAL,
ecartType DECIMAL,
moyenne DECIMAL,
maximum DECIMAL,
minimum DECIMAL,
temperatureMoyenne DECIMAL,
athleteId INT,
sourceId INT,
FOREIGN KEY (athleteId) REFERENCES Athlete(idAthlete),
FOREIGN KEY (sourceId) REFERENCES SourceDonnee(idSource)
);
CREATE TABLE FrequenceCardiaque (
idFc INT PRIMARY KEY,
altitude DECIMAL,
temps TIME,
temperature DECIMAL,
bpm INT,
longitude DECIMAL,
latitude DECIMAL,
activiteId INT,
FOREIGN KEY (activiteId) REFERENCES Activite(idActivite)
);
INSERT INTO Athlete (idAthlete, nom, prenom, email, sexe, taille, poids, motDePasse, dateNaissance, isCoach) VALUES
(1, 'Doe', 'John', 'john.doe@example.com', 'M', 1.80, 70, 'password123', '1990-01-01', FALSE),
(2, 'Smith', 'Jane', 'jane.smith@example.com', 'F', 1.65, 60, 'password456', '1992-02-02', TRUE);
INSERT INTO Friendship (idAthlete1, idAthlete2, debut) VALUES
(1, 2, '2023-01-01');
INSERT INTO Notification (idNotif, message, date, statut, urgence, athleteId) VALUES
(1, 'Training session at 10 AM', '2023-03-10', TRUE, 1, 1);
INSERT INTO Statistique (idStatistique, poids, fcMoyenne, fcMax, caloriesBruleesMoy, date, athleteId) VALUES
(1, 70, 80, 150, 500, '2023-03-10', 1);
INSERT INTO Entrainement (idEntrainement, date, description, latitude, longitude, feedback, athleteId) VALUES
(1, '2023-03-12', 'Long run in the park', 40.7128, -74.0060, 'Good effort', 1);
INSERT INTO Participe (athleteId, entrainementId) VALUES
(1, 1);
INSERT INTO SourceDonnee (idSource, type, modele, precision2, athleteId) VALUES
(1, 'Heart Rate Monitor', 'HRM-Pro', 98.5, 1);
INSERT INTO Activite (idActivite, type, date, heureDeDebut, heureDeFin, effortRessent, variabilite, variance, ecartType, moyenne, maximum, minimum, temperatureMoyenne, athleteId, sourceId) VALUES
(1, 'Running', '2023-03-10', '08:00:00', '09:00:00', 7, 0.5, 1, 0.1, 140, 160, 120, 20, 1, 1);
INSERT INTO FrequenceCardiaque (idFc, altitude, temps, temperature, bpm, longitude, latitude, activiteId) VALUES
(1, 100, '08:15:00', 15, 130, -74.0060, 40.7128, 1);

@ -15,7 +15,7 @@ services:
web: web:
build: build:
context: . context: .
dockerfile: ./config/Dockerfile.local dockerfile: ./config/Dockerfile
ports: ports:
- 9000:9000 - 9000:9000
volumes: volumes:
@ -40,5 +40,3 @@ services:
MYSQL_PASSWORD: pass MYSQL_PASSWORD: pass
ports: ports:
- "3307:3306" - "3307:3306"
volumes:
- ./mysql-data:/var/lib/mysql

Binary file not shown.

Before

Width:  |  Height:  |  Size: 136 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 98 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 692 B

After

Width:  |  Height:  |  Size: 586 B

File diff suppressed because it is too large Load Diff

@ -12,7 +12,7 @@ use Manager\DataManager;
use Repository\IUserRepository; use Repository\IUserRepository;
use Shared\ArgumentControllerResolver; use Shared\ArgumentControllerResolver;
use Shared\IArgumentResolver; use Shared\IArgumentResolver;
use Network\AuthService; use Stub\AuthService;
use Stub\NotificationRepository; use Stub\NotificationRepository;
use Stub\TrainingRepository; use Stub\TrainingRepository;
use Stub\UserRepository; use Stub\UserRepository;
@ -23,25 +23,26 @@ use App\Router\Middleware\AuthMiddleware;
use Network\IAuthService; use Network\IAuthService;
use Network\IFriendRequestService; use Network\IFriendRequestService;
use Network\RelationshipService; use Network\RelationshipService;
use Network\INotificationService; use Network\INotificationService;
use Stub\NotificationService; use Stub\NotificationService;
use App\Router\Session;
use Stub\StubData; use Stub\StubData;
use Twig\Environment; use Twig\Environment;
use Twig\Loader\FilesystemLoader; use Twig\Loader\FilesystemLoader;
use Shared\IHashPassword; use Shared\IHashPassword;
use Shared\HashPassword; use Shared\HashPassword;
use Shared\Log;
$appFactory = new AppCreator(); $appFactory = new AppCreator();
$appFactory->registerService(IArgumentResolver::class, ArgumentControllerResolver::class); $appFactory->registerService(IArgumentResolver::class, ArgumentControllerResolver::class);
$appFactory->registerSingleton(UserManager::class, UserManager::class); $appFactory->registerService(UserManager::class, UserManager::class);
$appFactory->registerService(DataManager::class, StubData::class); $appFactory->registerService(DataManager::class, StubData::class);
$appFactory->registerSingleton(IAuthService::class, AuthService::class); $appFactory->registerService(IAuthService::class, AuthService::class);
$appFactory->registerService(IFriendRequestService::class, RelationshipService::class); $appFactory->registerService(IFriendRequestService::class, RelationshipService::class);
$appFactory->registerService(IHashPassword::class, HashPassword::class); $appFactory->registerService(IHashPassword::class, HashPassword::class);
$appFactory->registerService(INotificationService::class, NotificationService::class); $appFactory->registerService(INotificationService::class, NotificationService::class);
@ -49,6 +50,11 @@ $appFactory->registerService(INotificationRepository::class, NotificationReposit
$appFactory->registerService(IUserRepository::class, UserRepository::class); $appFactory->registerService(IUserRepository::class, UserRepository::class);
$appFactory->registerService(\Twig\Loader\LoaderInterface::class, function() { $appFactory->registerService(\Twig\Loader\LoaderInterface::class, function() {
return new FilesystemLoader(__DIR__ . '/../src/app/views/Templates'); return new FilesystemLoader(__DIR__ . '/../src/app/views/Templates');
}); });
@ -60,12 +66,3 @@ $appFactory->registerService(\Twig\Environment::class,\Twig\Environment::class);
$appFactory->AddControllers(); $appFactory->AddControllers();
$app = $appFactory->create();
if (!is_null($app)){
// Ajout des Middleware
/*$app->use(new LoggingMiddleware());*/
$app->use(new AuthMiddleware($appFactory->getDicontainer()->get(IAuthService::class) ));
$app->mapControllers();
$app->run(RequestFactory::createFromGlobals());
}

@ -1,34 +0,0 @@
/*!
* Start Bootstrap - New Age v6.0.7 (https://startbootstrap.com/theme/new-age)
* Copyright 2013-2023 Start Bootstrap
* Licensed under MIT (https://github.com/StartBootstrap/startbootstrap-new-age/blob/master/LICENSE)
*/
//
// Scripts
//
window.addEventListener('DOMContentLoaded', event => {
// Activate Bootstrap scrollspy on the main nav element
const mainNav = document.body.querySelector('#mainNav');
if (mainNav) {
new bootstrap.ScrollSpy(document.body, {
target: '#mainNav',
offset: 74,
});
};
// Collapse responsive navbar when toggler is visible
const navbarToggler = document.body.querySelector('.navbar-toggler');
const responsiveNavItems = [].slice.call(
document.querySelectorAll('#navbarResponsive .nav-link')
);
responsiveNavItems.map(function (responsiveNavItem) {
responsiveNavItem.addEventListener('click', () => {
if (window.getComputedStyle(navbarToggler).display !== 'none') {
navbarToggler.click();
}
});
});
});

@ -1,34 +0,0 @@
/*!
* Start Bootstrap - New Age v6.0.7 (https://startbootstrap.com/theme/new-age)
* Copyright 2013-2023 Start Bootstrap
* Licensed under MIT (https://github.com/StartBootstrap/startbootstrap-new-age/blob/master/LICENSE)
*/
//
// Scripts
//
window.addEventListener('DOMContentLoaded', event => {
// Activate Bootstrap scrollspy on the main nav element
const mainNav = document.body.querySelector('#mainNav');
if (mainNav) {
new bootstrap.ScrollSpy(document.body, {
target: '#mainNav',
offset: 74,
});
};
// Collapse responsive navbar when toggler is visible
const navbarToggler = document.body.querySelector('.navbar-toggler');
const responsiveNavItems = [].slice.call(
document.querySelectorAll('#navbarResponsive .nav-link')
);
responsiveNavItems.map(function (responsiveNavItem) {
responsiveNavItem.addEventListener('click', () => {
if (window.getComputedStyle(navbarToggler).display !== 'none') {
navbarToggler.click();
}
});
});
});

@ -9,7 +9,6 @@ use App\Router\Middleware\IHttpMiddleware;
use App\Router\Request\IRequest; use App\Router\Request\IRequest;
use App\Router\Route; use App\Router\Route;
use App\Views\Directives\Navigate; use App\Views\Directives\Navigate;
use Manager\UserManager;
use Shared\Attributes\Route as RouteAttribute; use Shared\Attributes\Route as RouteAttribute;
use App\Router\Router; use App\Router\Router;
use App\Router\Session; use App\Router\Session;
@ -30,6 +29,9 @@ class App
private FrontController $frontController; private FrontController $frontController;
private Session $session;
public function __construct(string $appName, int $version, \App\Container $diContainer) public function __construct(string $appName, int $version, \App\Container $diContainer)
{ {
$this->appName = $appName; $this->appName = $appName;
@ -37,7 +39,7 @@ class App
$this->container = $diContainer; $this->container = $diContainer;
$this->router = new Router(""); $this->router = new Router("");
$this->frontController = new FrontController($this->router,$this->container); $this->frontController = new FrontController($this->router,$this->container);
Session::getInstance(); $this->session = Session::getInstance();
} }
public function use(IHttpMiddleware $middleware) public function use(IHttpMiddleware $middleware)
@ -101,7 +103,6 @@ class App
// Exécutez le middleware en utilisant le pipeline // Exécutez le middleware en utilisant le pipeline
return $this->middlewarePipeline->handle($request, function($request) { return $this->middlewarePipeline->handle($request, function($request) {
// Logique de gestion principale de la requête ici // Logique de gestion principale de la requête ici
$this->frontController->dispatch($request); $this->frontController->dispatch($request);
}); });
@ -141,7 +142,7 @@ class App
$route = $attribute->newInstance(); $route = $attribute->newInstance();
$this->router->addControllerRoute( $this->router->addControllerRoute(
$route->getMethods(), implode('|', $route->getMethods()),
$prefix . $route->getPath(), $prefix . $route->getPath(),
$controllerClass, $controllerClass,
$method->getName(), $method->getName(),

@ -24,13 +24,6 @@ class AppCreator
return $this; return $this;
} }
public function registerSingleton(string $serviceId, $service): self
{
$this->container->set($serviceId, $service, Container::SINGLETON);
$this->services[] = $serviceId;
return $this;
}
/** /**
* Create an instance or perform actions based on the current application environment. * Create an instance or perform actions based on the current application environment.
* *
@ -40,7 +33,6 @@ class AppCreator
{ {
// Check the application environment // Check the application environment
switch (APP_ENV) { switch (APP_ENV) {
case 'console': case 'console':
// Load the Console.php file in case of the 'console' environment // Load the Console.php file in case of the 'console' environment
require_once __DIR__ . '/../console/Console.php'; require_once __DIR__ . '/../console/Console.php';
@ -48,6 +40,7 @@ class AppCreator
case 'development': case 'development':
// Create a new instance of the App class in the 'development' environment // Create a new instance of the App class in the 'development' environment
return new App("HeartTrack", 1, $this->container); return new App("HeartTrack", 1, $this->container);
break;
case 'html': case 'html':
// Load the index.test.php file in case of the 'html' environment // Load the index.test.php file in case of the 'html' environment
require_once __DIR__ . '/index.test.php'; require_once __DIR__ . '/index.test.php';
@ -60,6 +53,7 @@ class AppCreator
} }
function AddControllers($namespacePrefix = 'App\Controller', $pathToControllers = __DIR__ . '/controller'): self function AddControllers($namespacePrefix = 'App\Controller', $pathToControllers = __DIR__ . '/controller'): self
{ {
$controllerFiles = glob($pathToControllers . '/*.php'); $controllerFiles = glob($pathToControllers . '/*.php');
@ -77,8 +71,7 @@ class AppCreator
if ($reflectionClass->isSubclassOf(BaseController::class)) { if ($reflectionClass->isSubclassOf(BaseController::class)) {
// Register in DI container // Register in DI container
$this->container->set($fullClassName, function () use ($fullClassName) { $this->container->set($fullClassName, function () use ($fullClassName) {
/** @var $controllerInstance * */ $controllerInstance = new $fullClassName();
$controllerInstance = $this->container->resolve($fullClassName);
$controllerInstance->setContainer($this->container); $controllerInstance->setContainer($this->container);
return $controllerInstance; return $controllerInstance;
}); });
@ -88,15 +81,11 @@ class AppCreator
return $this; return $this;
} }
public function getServiceRegistered(): array public function getServiceRegistered(): array
{ {
return $this->services; return $this->services;
} }
public function getDicontainer()
{
return $this->container;
}
} }

@ -11,45 +11,31 @@ class Container implements ContainerInterface
{ {
private array $entries = []; private array $entries = [];
const SINGLETON = 'singleton';
const TRANSIENT = 'transient';
public function get(string $id) public function get(string $id)
{ {
if ($this->has($id)) { if ($this->has($id)) {
$entry = $this->entries[$id]; $entry = $this->entries[$id];
if (is_callable($entry)) {
if ($entry['lifecycle'] === self::SINGLETON) { return $entry($this);
if ($entry['instance'] === null) {
$entry['instance'] = $this->resolve($entry['concrete']);
}
return $entry['instance'];
} }
if (is_callable($entry['concrete'])) { $id = $entry;
return $entry['concrete']($this);
}
return $this->resolve($entry['concrete']);
} }
return $this->resolve($id); return $this->resolve($id);
} }
public function has(string $id): bool public function has(string $id): bool
{ {
return isset($this->entries[$id]); return isset($this->entries[$id]);
} }
public function set(string $id, callable|string $concrete, string $lifecycle = self::TRANSIENT): void public function set(string $id, callable|string $concrete): void
{ {
$this->entries[$id] = [ $this->entries[$id] = $concrete;
'concrete' => $concrete,
'lifecycle' => $lifecycle,
'instance' => null
];
} }
public function resolve(string $id) public function resolve(string $id)

@ -1,131 +0,0 @@
<?php
namespace App\Controller;
use App\Router\Request\IRequest;
use App\Router\Response\Response;
use Database\ActivityGateway;
use Database\ActivityMapper;
use Database\Connexion;
use Json\JsonSerializer;
use Manager\UserManager;
use Shared\Attributes\Route;
use Shared\Log;
class ApiController extends BaseController
{
private UserManager $userMgr;
public function __construct(UserManager $manager){
parent::__construct();
$this->userMgr = $manager;
}
#[Route(path: '/api/activities', name: 'api-activities', methods: ['GET'])]
public function apiActivities(IRequest $request)
{
$activityGateway = new ActivityGateway(new Connexion(DSN, DB_USER, DB_PASSWORD));
$listSearch = $activityGateway->getActivity();
$map = new ActivityMapper();
$activityGateway = $map->activitySqlToEntity($listSearch);
$listActivity = [];
foreach ($activityGateway as $entity) {
$activity = $map->activityEntityToModel($entity);
$listActivity[] = ['idactivity' => number_format($activity->getIdActivity()), 'type' => $activity->getType(),
'date' => $activity->getDate()->format("Y-m-d"), 'heureDebut' => $activity->getHeureDebut()->format("Y-m-d"), 'heureFin' => $activity->getHeureFin()->format("Y-m-d"),
'effortRessenti' => $activity->getEffortRessenti(), 'variabilite' => $activity->getVariability(), 'variance' => $activity->getVariance(),
'ecartType' => $activity->getStandardDeviation(), 'moyenne' => $activity->getAverage(),
'max' => $activity->getMaximum(), 'min' => $activity->getMinimum(), 'temperature' => $activity->getAvrTemperature()];
}
$jsonSerializer = new JsonSerializer();
$jsonData = $jsonSerializer::serialize($listActivity);
$response = new Response();
$response->setContent($jsonData);
$response->setHeader('Content-Type', 'application/json');
return $response;
}
// cela ne trouve pas la methode avec la route '/api/activities/1'
#[Route(path: '/api/activities/{id}', name: 'api-activities-by-id', methods: ['GET'])]
public function apiActivityById(IRequest $request, int $id)
{
$activityGateway = new ActivityGateway(new Connexion(DSN, DB_USER, DB_PASSWORD));
$listSearch = $activityGateway->getActivityById($id);
Log::dd($listSearch);
$map = new ActivityMapper();
$activityGateway = $map->activitySqlToEntity($listSearch);
$listActivity = [];
foreach ($activityGateway as $entity) {
$activity = $map->activityEntityToModel($entity);
$listActivity[] = ['idactivity' => number_format($activity->getIdActivity()), 'type' => $activity->getType(),
'date' => $activity->getDate()->format("Y-m-d"), 'heureDebut' => $activity->getHeureDebut()->format("Y-m-d"), 'heureFin' => $activity->getHeureFin()->format("Y-m-d"),
'effortRessenti' => $activity->getEffortRessenti(), 'variabilite' => $activity->getVariability(), 'variance' => $activity->getVariance(),
'ecartType' => $activity->getStandardDeviation(), 'moyenne' => $activity->getAverage(),
'max' => $activity->getMaximum(), 'min' => $activity->getMinimum(), 'temperature' => $activity->getAvrTemperature()];
}
$jsonSerializer = new JsonSerializer();
$jsonData = $jsonSerializer::serialize($listActivity);
$response = new Response();
$response->setContent($jsonData);
$response->setHeader('Content-Type', 'application/json');
// pour delete renvoyer 204 pour dire ok et supprimer
// update 200
return $response;
}
//
// #[Route(path: '/api/activities', name: 'api-activities-post', methods: ['POST'])]
// public function apiAddActivity(IRequest $request)
// {
// $activityGateway = new ActivityGateway(new Connexion(DSN, DB_USER, DB_PASSWORD));
// $listSearch = $activityGateway->getActivity();
// $map = new ActivityMapper();
// $activityGateway = $map->activitySqlToEntity($listSearch);
// $listActivity = [];
// foreach ($activityGateway as $entity) {
// $activity = $map->activityEntityToModel($entity);
// $listActivity[] = ['idactivity' => number_format($activity->getIdActivity()), 'type' => $activity->getType(),
// 'date' => $activity->getDate()->format("Y-m-d"), 'heureDebut' => $activity->getHeureDebut()->format("Y-m-d"), 'heureFin' => $activity->getHeureFin()->format("Y-m-d"),
// 'effortRessenti' => $activity->getEffortRessenti(), 'variabilite' => $activity->getVariability(), 'variance' => $activity->getVariance(),
// 'ecartType' => $activity->getStandardDeviation(), 'moyenne' => $activity->getAverage(),
// 'max' => $activity->getMaximum(), 'min' => $activity->getMinimum(), 'temperature' => $activity->getAvrTemperature()];
// }
//
// $jsonSerializer = new JsonSerializer();
// $jsonData = $jsonSerializer::serialize($listActivity);
//
// $response = new Response();
// $response->setContent($jsonData);
// $response->setHeader('Content-Type', 'application/json');
//
// return $response;
// }
// #[Route(path: '/api/activities/{id}', name: 'api-activities-post', methods: ['DELETE'])]
// public function apiDeleteActivity(IRequest $request, int $id)
// {
// $activityGateway = new ActivityGateway(new Connexion(DSN, DB_USER, DB_PASSWORD));
// $listSearch = $activityGateway->removeActivityById($id);
//
// $response = new Response();
// $response->setContent($jsonData);
// $response->setHeader('Content-Type', 'application/json');
//
// return $response;
// }
// #[Route(path: '/api/activities/{id}', name: 'api-activities-post', methods: ['PUT'])]
// public function apiUpdateActivity(IRequest $request, int $id)
// {
// $activityGateway = new ActivityGateway(new Connexion(DSN, DB_USER, DB_PASSWORD));
// $listSearch = $activityGateway->updateActivity($id);
//
// $response = new Response();
// $response->setContent($jsonData);
// $response->setHeader('Content-Type', 'application/json');
//
// return $response;
// }
}

@ -1,9 +1,7 @@
<?php <?php
namespace App\Controller;
namespace App\Controller; namespace App\Controller;
use Shared\Validation;
use App\Container; use App\Container;
use App\Router\Request\IRequest; use App\Router\Request\IRequest;
use App\Router\Response\Response; use App\Router\Response\Response;
@ -11,78 +9,62 @@ use Shared\Attributes\Route;
use Twig\Environment; use Twig\Environment;
use Data\Core\Preferences; use Data\Core\Preferences;
use Shared\Log; use Shared\Log;
use Manager\UserManager;
class AthleteController extends BaseController class AthleteController extends BaseController
{ {
private Environment $twig; #[Route(path: '/search-ath', name: 'search-ath', methods: ['GET'])]
protected Preferences $preference;
public function __construct()
{
//session_start();
$this->preference = new Preferences();
}
#[Route(path: '/search-user', name: 'search-user', methods: ['GET'])]
public function searchUser(string $username, IRequest $req): Response public function searchUser(string $username, IRequest $req): Response
{ {
$taberror = []; $taberror = [];
if(!Validation::val_string($username)){ $utiliArray = [
print("Nom invalide."); [
} 'nom' => 'John',
else { 'prenom' => 'Doe',
'img' => 'john_doe',
'username' => 'johndoe',
],
[
'nom' => 'Alice',
'prenom' => 'Smith',
'img' => 'alice_smith',
'username' => 'alicesmith',
],
];
// if(!Validation::val_string($name)){
try { try {
$listSearch=$this->container->get(UserManager::class)->searchUsersByName($username); //code...
$i=0; // $model->userMgr->getUser($name);
foreach ($listSearch as $user){ return $this->render('./page/addfriend.html.twig', [
$listUsers[$i++]=['nom' => $user->getNom(), 'prenom'=>$user->getPrenom(), 'img'=>'john_doe', 'username'=>$user->getUsername()];
}
//$currentUser=$this->container->get(UserManager::class)->getCurrentUser();
//$currentUser=$_SESSION['user'];
$response = $this->render('./page/addfriend.html.twig',[
'css' => $_COOKIE['preferences'],
'pp' => "test",
'user' => 'johndoe',//$currentUser->getUsername(),
'role' => 'Athlete',//$currentUser->getRole(),
'users' => $listUsers
]);
} catch (\Throwable $th) {
$th;
return $this->render("addfriend.html.twig", ['tabError' => $taberror ]);
}
}
return $response;
}
#[Route(path: '/analyses', name: 'analyses', methods: ['GET'])]
public function analyses(): Response
{
return $this->render('./page/analyze.html.twig',[
'css' => $this->preference->getCookie(), 'css' => $this->preference->getCookie(),
'pp' => "test2", 'pp' => "test2",
'user' => 'johndoe',//$currentUser->getUsername(), 'user' => "Doe",
'role' => 'Athlete',//$currentUser->getRole(), 'role' => "Athlète",
'friendship' => [], 'friendship' => [],
'analyzes' => [], 'analyzes' => [],
'mails' => [], 'mails' => [],
'users' => [], 'users' => $utiliArray,
'infoUser' => [], 'infoUser' => [],
'exos' => [], 'exos' => [],
'member' => [] 'member' => [],
'responce' => "Notification d'ajout envoyée à $username"
]); ]);
} catch (\Throwable $th) {
//throw $th;
// return $this->render("addfriend.html.twig", ['tabError' => $taberror ]);
} }
// }
#[Route(path: '/activity', name: 'activity', methods: ['GET'])] }
public function activity(): Response
#[Route(path: '/analyses', name: 'analyses', methods: ['GET'])]
public function analyses(): Response
{ {
return $this->render('./page/activity.html.twig',[ return $this->render('./page/analyze.html.twig', [
'css' => $this->preference->getCookie(), 'css' => $this->preference->getCookie(),
'pp' => "test", 'pp' => "test2",
'user' => 'johndoe',//$currentUser->getUsername(), 'user' => "Doe",
'role' => 'Athlete',//$currentUser->getRole(), 'role' => "Athlète",
'friendship' => [], 'friendship' => [],
'analyzes' => [], 'analyzes' => [],
'mails' => [], 'mails' => [],
@ -97,11 +79,11 @@ class AthleteController extends BaseController
#[Route(path: '/exercice', name: 'exercice', methods: ['GET'])] // 8 #[Route(path: '/exercice', name: 'exercice', methods: ['GET'])] // 8
public function exercice(): Response public function exercice(): Response
{ {
return $this->render('./page/exercice.html.twig',[ return $this->render('./page/exercice.html.twig', [
'css' => $this->preference->getCookie(), 'css' => $this->preference->getCookie(),
'pp' => "test2", 'pp' => "test2",
'user' => 'johndoe',//$currentUser->getUsername(), 'user' => "Doe",
'role' => 'Athlete',//$currentUser->getRole(), 'role' => "Athlète",
'friendship' => [], 'friendship' => [],
'analyzes' => [], 'analyzes' => [],
'mails' => [], 'mails' => [],
@ -112,84 +94,57 @@ class AthleteController extends BaseController
]); ]);
} }
#[Route(path: '/exercices', name: 'exercices', methods: ['POST'])] // 8
public function exercices(String $type, String $intensite, String $date, IRequest $req): Response
{
$exercicesArray = [
[
'date' => $date,
'type' => $type,
'intensite' => $intensite,
'status' => 'A venir',
]
];
return $this->render('./page/exercice.html.twig',[
'css' => $this->preference->getCookie(),
'pp' => "test2",
'user' => 'johndoe',//$currentUser->getUsername(),
'role' => 'Athlete',//$currentUser->getRole(),
'friendship' => [],
'analyzes' => [],
'mails' => [],
'users' => [],
'infoUser' => [],
'exos' => $exercicesArray,
'member' => []
]);
}
#[Route(path: '/add-friend', name: 'add-friend', methods: ['POST'])] #[Route(path: '/add-friend', name: 'add-friend', methods: ['POST'])]
public function addFriend(string $username, IRequest $req): Response public function addFriend(string $username, IRequest $req): Response
{ {
$taberror = [];
$utiliArray = [
[
'nom' => 'John',
'prenom' => 'Doe',
'img' => 'john_doe',
'username' => 'johndoe',
],
[
'nom' => 'Alice',
'prenom' => 'Smith',
'img' => 'alice_smith',
'username' => 'alicesmith',
],
];
// if(!Validation::val_string($name)){
try { try {
//Ajouter la personne sur laquelle on a clique dans la liste de currentuser //code...
$listSearch=$this->container->get(UserManager::class)->searchUsersByName($username); // $model->userMgr->addFriend($name);
$i=0; return $this->render('./page/addfriend.html.twig', [
foreach ($listSearch as $user){
$listUsers[$i++]=['nom' => $user->getNom(), 'prenom'=>$user->getPrenom(), 'img'=>'test', 'username'=>$user->getUsername()];
}
return $this->render('./page/addfriend.html.twig',[
'css' => $this->preference->getCookie(), 'css' => $this->preference->getCookie(),
'pp' => "test2", 'pp' => "test2",
'user' => 'johndoe',//$currentUser->getUsername(), 'user' => "Doe",
'role' => 'Athlete',//$currentUser->getRole(), 'role' => "Athlète",
'friendship' => [], 'friendship' => [],
'analyzes' => [], 'analyzes' => [],
'mails' => [], 'mails' => [],
'users' => $listUsers, 'users' => $utiliArray,
'infoUser' => [], 'infoUser' => [],
'exos' => [], 'exos' => [],
'member' => [], 'member' => [],
'responce' => "Notification d'ajout envoyée à $username" 'responce' => "Notification d'ajout envoyée à $username"
]); ]);
} catch (\Throwable $th) { } catch (\Throwable $th) {
throw $th; //throw $th;
return $this->render("addfriend.html.twig", ['tabError' => $taberror ]); // return $this->render("addfriend.html.twig", ['tabError' => $taberror ]);
} }
// }
} }
#[Route(path: '/friend', name: 'friend', methods: ['GET'])] #[Route(path: '/friend', name: 'friend', methods: ['GET'])]
public function friend(): Response public function friend(): Response
{ {
return $this->render('./page/addfriend.html.twig',[ $utiliArray = [
'css' => $this->preference->getCookie(),
'pp' => "test2",
'user' => 'John',//$currentUser->getUsername(),
'role' => 'Athlete',//$currentUser->getRole(),
'friendship' => [],
'analyzes' => [],
'mails' => [],
'users' => [],
'infoUser' => [],
'exos' => [],
'member' => [],
]);
}
/*#[Route(path: '/friendlist', name: 'friendlist', methods: ['POST'])]
public function friendlist(string $username, IRequest $req): Response
{
$friendList = [
[ [
'nom' => 'John', 'nom' => 'John',
'prenom' => 'Doe', 'prenom' => 'Doe',
@ -203,40 +158,19 @@ class AthleteController extends BaseController
'username' => 'alicesmith', 'username' => 'alicesmith',
], ],
]; ];
// TODO return $this->render('./page/addfriend.html.twig',[
// -> Enlever ou bloquer un utilisateur en fonction de son username
//$friendList = currentUser->getFriends();
return $this->render('./page/friend.html.twig',[
'css' => $this->preference->getCookie(),
'pp' => "test2",
'user' => 'johndoe',//$currentUser->getUsername(),
'role' => 'Athlete',//$currentUser->getRole(),
'friendship' => $friendList,
]);
}*/
#[Route(path: '/friendlist', name: 'friendlist2', methods: ['GET'])]
public function friendlist2(): Response
{
$friendList = $this->container->get(UserManager::class)->getFriends();//$currentUser->getFriends();
return $this->render('./page/friend.html.twig',[
'css' => $this->preference->getCookie(), 'css' => $this->preference->getCookie(),
'pp' => "test2", 'pp' => "test2",
'user' => "Doe", 'user' => "Doe",
'role' => "Athlète", 'role' => "Athlète",
'friendship' => $friendList, 'friendship' => [],
'analyzes' => [], 'analyzes' => [],
'mails' => [], 'mails' => [],
'users' => [], 'users' => $utiliArray,
'infoUser' => [], 'infoUser' => [],
'exos' => [], 'exos' => [],
'member' => [], 'member' => [],
]); ]);
} }
// #[Route(path: '/delete-friend', name: 'delete-friend', methods: ['POST'])]
} }
?>

@ -4,95 +4,98 @@ namespace App\Controller;
use App\Container; use App\Container;
use App\Router\Request\IRequest; use App\Router\Request\IRequest;
use App\Router\Response\RedirectResponse;
use App\Router\Response\Response; use App\Router\Response\Response;
use App\Router\Response\IResponse; use App\Router\Response\IResponse;
use App\Router\Session; use Couchbase\UserManager;
use Manager\UserManager;
use Shared\Attributes\Route; use Shared\Attributes\Route;
use Shared\Validation;
use Twig\Environment; use Twig\Environment;
use Data\Core\Preferences; use Data\Core\Preferences;
use Shared\Log; use Shared\Log;
use Shared\Validation;
use function PHPUnit\Framework\isEmpty;
class AuthController extends BaseController class AuthController extends BaseController
{ {
private UserManager $userMgr;
public function __construct(UserManager $manager){
parent::__construct();
$this->userMgr = $manager;
}
#[Route('/login', name: 'login',methods: ['POST'])] #[Route('/login', name: 'login',methods: ['POST'])]
public function login(string $email,string $password, IRequest $request): IResponse { public function login(IRequest $request): IResponse {
$error = []; $error = [];
try { try {
$log=$email; // should check email with verrify email $log=Validation::clean_string($request->getBody()['email']);
$mdp=Validation::clean_string($password); $mdp=Validation::clean_string($request->getBody()['password']);
} catch (\Throwable $th) {
$error = "Wrong cred";
}
if($this->userMgr->login($log,$mdp)){ if($this->container->get(UserManager::class)->login($log,$mdp)){
return new RedirectResponse('/home'); return $this->redirectToRoute('/');
} }
else{ else{
$error [] = "Erreur de connexion. Essayez encore"; $error [] = "Erreur de connexion. Essayez encore";
return $this->render('./page/login.html.twig',[
'css' => $this->preference->getCookie(),
'login_error'=> $error,
]);
} }
return $this->render('./page/login.html.twig', ['error' => $error]);
// should only cath a type of Exception not all
} catch (\Throwable $th) {
$error [] =$th->getMessage();
return $this->render('./page/login.html.twig',[
'css' => $this->preference->getCookie(),
'login_error'=> $error,
]);
}
} }
#[Route('/login', name: 'login2',methods: ['GET'])]
public function login2(IRequest $request): IResponse { #[Route('/log', name: 'baseLog',methods: ['GET'])]
public function index(IRequest $request): IResponse {
return $this->render('./page/login.html.twig',[ return $this->render('./page/login.html.twig',[
'css' => $this->preference->getCookie(), 'css' => $this->preference->getCookie(),
'pp' => "test2",
'user' => "Doe",
'role' => "Athlète",
'friendship' => [],
'analyzes' => [],
'mails' => [],
'users' => [],
'infoUser' => [],
'exos' => [],
'member' => []
]); ]);
} }
#[Route('/register', name: 'register2' , methods:['GET'])]
public function register2(IRequest $request): IResponse{
return $this->render('./page/register.html.twig',[
'css' => $this->preference->getCookie(),
]);
}
#[Route('/register', name: 'register' , methods:['POST'])] #[Route('/register', name: 'register' , methods:['GET'])]
public function register( public function register(IRequest $request): IResponse
string $nom,
string $prenom,
string $username,
string $mail,
string $motDePasse,
string $sexe,
float $taille,
float $poids,
string $dateNaissance,
string $roleName,
IRequest $request): IResponse
{ {
$error = []; if ($request->getMethod() == 'POST') {
$nom = $request->getBody()['nom'];
$prenom = $request->getBody()['prenom'];
$username = $request->getBody()['username'];
$email = $request->getBody()['email'];
$motDePasse = $request->getBody()['motDePasse'];
$sexe = $request->getBody()['sexe'];
$taille = $request->getBody()['taille'];
$poids = $request->getBody()['poids'];
$dateNaissanceStr = $request->getBody()['nom'];
$dateNaissance = new \DateTime($dateNaissanceStr);
if (!$dateNaissance) {
throw new \Exception("Date de naissance non valide. Format attendu : YYYY-MM-DD");
}
$roleName = $request->getBody()['roleName'];
try {
$registrationData = [ $registrationData = [
'nom' => $nom, 'nom' => $nom,
'prenom' => $prenom, 'prenom' => $prenom,
'username' => $username, 'username' => $username,
'email' => $mail, 'email' => $email,
'sexe' => $sexe, 'sexe' => $sexe,
'taille' => $taille, 'taille' => $taille,
'poids' => $poids, 'poids' => $poids,
@ -100,65 +103,45 @@ class AuthController extends BaseController
'roleName' => $roleName 'roleName' => $roleName
]; ];
if ($this->userMgr->register($mail, $motDePasse, $registrationData) ) { try {
return new RedirectResponse('/home'); if ($this->container->get(UserManager::class)->register($email, $motDePasse, $registrationData)) {
return $this->redirectToRoute('/');
} else { } else {
$error [] = 'L\'inscription a échoué. Veuillez réessayer.';
return $this->render('./page/register.html.twig',[ $error [] = 'L\'inscription a échoué. Veuillez réessayer.';
'css' => $this->preference->getCookie(),
'register_error'=> $error,
]);
} }
} catch (\Throwable $e) { } catch (\Exception $e) {
$error [] =$e->getMessage(); $error [] = 'Erreur lors de l\'inscription: ' . $e->getMessage();
return $this->render('./page/register.html.twig', ['css' => $this->preference->getCookie(),"register_error" => $error ]);
} }
} }
//string $ancienMotDePasse,string $nouveauMotDePasse,string $confirmerMotDePasse, return $this->render('/register.html.twig');
#[Route(path: '/forgetPassword', name: 'forget-password2', methods: ['GET'])]
public function forgetPassword2(IRequest $request): IResponse
{
return $this->render('./page/password.html.twig',[
'css' => $this->preference->getCookie(),
]);
} }
#[Route(path: '/forgetPassword', name: 'forget-password', methods: ['POST'])] #[Route(path: '/mdp', name: 'mdp', methods: ['POST'])]
public function forgetPassword(string $mail, IRequest $request): IResponse public function mdp(string $ancienMotDePasse,string $nouveauMotDePasse,string $confirmerMotDePasse, IRequest $req): Response
{ {
return $this->render('./page/password.html.twig',[ // CONFIRMER LES DONNESS !!!!! IMPORTANT
return $this->render('./page/settings.html.twig',[
'css' => $this->preference->getCookie(), 'css' => $this->preference->getCookie(),
'pp' => "test2",
'user' => "Doe",
'role' => "Athlète",
'friendship' => [],
'analyzes' => [],
'mails' => [],
'users' => [],
'infoUser' => [],
'exos' => [],
'member' => []
]); ]);
} }
#[Route(path: '/logout', name: 'logout', methods: ['POST'])]
public function logout(IRequest $request): IResponse
{
$error = [];
try {
if($this->userMgr->deconnecter()){
return new RedirectResponse('/');
}
else{
$error [] = "Erreur de deconnexion. Essayez encore";
return new RedirectResponse('/');
}
} catch (\Throwable $th) {
$error [] =$th->getMessage();
return new RedirectResponse('/');
}
}
} }
?>

@ -8,14 +8,13 @@ use App\Router\Response\RedirectResponse;
use App\Router\Response\Response; use App\Router\Response\Response;
use Psr\Container\ContainerInterface; use Psr\Container\ContainerInterface;
use Shared\Log;
abstract class BaseController abstract class BaseController
{ {
protected Preferences $preference; protected Preferences $preference;
public function __construct(){ public function __construct(){
$this->preference = new Preferences(); $this->preference = new Preferences();
} }
protected ContainerInterface $container; protected ContainerInterface $container;
@ -63,5 +62,18 @@ abstract class BaseController
return new RedirectResponse($url, $status); return new RedirectResponse($url, $status);
} }
protected function redirectToRoute(string $route, array $parameters = [], int $status = 302): RedirectResponse
{
return $this->redirect($this->generateUrl($route, $parameters), $status);
}
/*
* TODO : Should hanle ierror if the route is not existing
* */
protected function generateUrl(string $route, array $parameters = []): string
{
return $this->container->get(\App\Router\Router::class)->generate($route, $parameters);
}
} }

@ -1,50 +1,40 @@
<?php <?php
namespace App\Controller; // namespace App\Controller;
use App\Container; // use App\Container;
use App\Router\Request\IRequest; // use App\Router\Request\IRequest;
use App\Router\Response\Response; // use App\Router\Response\Response;
use App\Router\Response\IResponse; // use App\Router\Response\IResponse;
use Shared\Attributes\Route; // use Shared\Attributes\Route;
use Twig\Environment; // use Twig\Environment;
use Data\Core\Preferences; // use Data\Core\Preferences;
use Shared\Log; // use Shared\Log;
// #[Route(path: '/coach', name: 'coach')]
// class CoachController extends BaseController // class CoachController extends BaseController
// { // {
// private ICoachManager $coachManager; // private ICoachManager $coachManager;
// private $security; // private $security;
// private Environment $twig;
// protected Preferences $preference;
// public function __construct(DataManager $dataManager, Security $security) // public function __construct(DataManager $dataManager, Security $security)
// { // {
// session_start();
// $this->coachManager = $dataManager->coachMgr; // $this->coachManager = $dataManager->coachMgr;
// $this->security = $security; // $this->security = $security;
// $this->preference = new Preferences();
// } // }
// // #[Route('/global-stats', name: 'coach_global_stats', methods: ['GET'])] // #[Route(path: '/', name: 'home', methods: ['GET'])]
// // public function globalStats(): Response // public function index(): Response
// // {
// // // Add logic to fetch and process global stats
// // return $this->render('coach/global_stats.html.twig');
// // }
// #[Route(path: '/coaching', name: 'coaching', methods: ['GET'])]
// public function coaching(): Response
// { // {
// return $this->render('./page/coaching.html.twig',[ // return $this->render('./page/home.html.twig',[
// 'css' => $this->preference->getCookie(), // 'css' => $this->preference->getCookie(),
// 'pp' => "test2", // 'pp' => "test2",
// 'user' => "Doe", // 'user' => "Doe",
// 'role' => "Coach", // 'role' => "Athlète",
// 'friendship' => [], // 'friendship' => [],
// 'analyzes' => [], // 'analyzes' => [],
// 'mails' => [], // 'mails' => [],
@ -54,31 +44,17 @@ use Shared\Log;
// 'member' => [] // 'member' => []
// ]); // ]);
// } // }
// #[Route('/global-stats', name: 'coach_global_stats', methods: ['GET'])]
// public function globalStats(): Response
// {
// // Add logic to fetch and process global stats
// return $this->render('coach/global_stats.html.twig');
// }
// #[Route(path: '/search-member', name: 'search-member', methods: ['GET'])] // #[Route(path: '/exercice', name: 'exercice', methods: ['GET'])] // 8
// public function searchMember(string $username, IRequest $req): Response // public function exercice(): Response
// { // {
// $taberror = []; // return $this->render('./page/exercice.html.twig',[
// // FILTER
// $utiliArray = [
// [
// 'nom' => 'John',
// 'prenom' => 'Doe',
// 'img' => 'john_doe',
// 'username' => 'johndoe',
// ],
// [
// 'nom' => 'Alice',
// 'prenom' => 'Smith',
// 'img' => 'alice_smith',
// 'username' => 'alicesmith',
// ],
// ];
// // if(!Validation::val_string($name)){
// try {
// //code...
// // $model->userMgr->addFriend($name);
// return $this->render('./page/addmember.html.twig',[
// 'css' => $this->preference->getCookie(), // 'css' => $this->preference->getCookie(),
// 'pp' => "test2", // 'pp' => "test2",
// 'user' => "Doe", // 'user' => "Doe",
@ -86,43 +62,17 @@ use Shared\Log;
// 'friendship' => [], // 'friendship' => [],
// 'analyzes' => [], // 'analyzes' => [],
// 'mails' => [], // 'mails' => [],
// 'users' => $utiliArray, // 'users' => [],
// 'infoUser' => [], // 'infoUser' => [],
// 'exos' => [], // 'exos' => [],
// 'member' => [], // 'member' => []
// 'responce' => "Notification d'ajout envoyée à $username"
// ]); // ]);
// } catch (\Throwable $th) {
// //throw $th;
// // return $this->render("addfriend.html.twig", ['tabError' => $taberror ]);
// }
// // }
// } // }
// #[Route(path: '/add-member', name: 'add-member', methods: ['POST'])] // #[Route(path: '/coaching', name: 'coaching', methods: ['GET'])]
// public function addmember(string $username, IRequest $req): Response // public function coaching(): Response
// { // {
// $taberror = []; // return $this->render('./page/coaching.html.twig',[
// $utiliArray = [
// [
// 'nom' => 'John',
// 'prenom' => 'Doe',
// 'img' => 'john_doe',
// 'username' => 'johndoe',
// ],
// [
// 'nom' => 'Alice',
// 'prenom' => 'Smith',
// 'img' => 'alice_smith',
// 'username' => 'alicesmith',
// ],
// ];
// // if(!Validation::val_string($name)){
// try {
// //code...
// // $model->userMgr->addFriend($name);
// return $this->render('./page/addmember.html.twig',[
// 'css' => $this->preference->getCookie(), // 'css' => $this->preference->getCookie(),
// 'pp' => "test2", // 'pp' => "test2",
// 'user' => "Doe", // 'user' => "Doe",
@ -130,84 +80,45 @@ use Shared\Log;
// 'friendship' => [], // 'friendship' => [],
// 'analyzes' => [], // 'analyzes' => [],
// 'mails' => [], // 'mails' => [],
// 'users' => $utiliArray, // 'users' => [],
// 'infoUser' => [], // 'infoUser' => [],
// 'exos' => [], // 'exos' => [],
// 'member' => [], // 'member' => []
// 'responce' => "Notification d'ajout envoyée à $username"
// ]); // ]);
// } catch (\Throwable $th) {
// //throw $th;
// // return $this->render("addfriend.html.twig", ['tabError' => $taberror ]);
// } // }
// // }
// #[Route('/list-athletes', name: 'coach_list_athletes')]
// public function listAthletes(): Response
// {
// $coach = $this->security->getUser();
// $athletes = $this->coachManager->getAthletesForCoach($coach);
// return $this->render('coach/list_athletes.html.twig', [
// 'athletes' => $athletes,
// ]);
// } // }
// #[Route('/athlete-analysis/{athleteId}', name: 'coach_athlete_analysis', methods: ['GET'])]
// #[Route(path: '/member', name: 'member', methods: ['GET'])] // public function athleteAnalysis($athleteId): Response
// public function member(): Response
// { // {
// $utiliArray = [ // // Fetch and process data specific to the athlete
// [ // return $this->render('coach/athlete_analysis.html.twig', [
// 'nom' => 'John', // 'athleteId' => $athleteId,
// 'prenom' => 'Doe',
// 'img' => 'john_doe',
// 'username' => 'johndoe',
// ],
// [
// 'nom' => 'Alice',
// 'prenom' => 'Smith',
// 'img' => 'alice_smith',
// 'username' => 'alicesmith',
// ],
// ];
// return $this->render('./page/addmember.html.twig',[
// 'css' => $this->preference->getCookie(),
// 'pp' => "test2",
// 'user' => "Doe",
// 'role' => "Athlète",
// 'friendship' => [],
// 'analyzes' => [],
// 'mails' => [],
// 'users' => $utiliArray,
// 'infoUser' => [],
// 'exos' => [],
// 'member' => [],
// ]); // ]);
// } // }
// #[Route('/add-athlete/{athleteId}', name: 'coach_add_athlete', methods: ['POST'])]
// public function addAthlete(IRequest $request, $athleteId): IResponse
// {
// // Implement logic to add athlete
// // ...
// // #[Route('/list-athletes', name: 'coach_list_athletes')] // return $this->redirectToRoute('coach_list_athletes');
// // public function listAthletes(): Response // }
// // {
// // $coach = $this->security->getUser(); // // #[Route('/remove-athlete', name: 'coach_remove_athlete', methods: ['POST'])]
// // $athletes = $this->coachManager->getAthletesForCoach($coach); // // public function removeAthlete(int $athleteId, IRequest $request): IResponse
// // return $this->render('coach/list_athletes.html.twig', [
// // 'athletes' => $athletes,
// // ]);
// // }
// // #[Route('/athlete-analysis/{athleteId}', name: 'coach_athlete_analysis', methods: ['GET'])]
// // public function athleteAnalysis($athleteId): Response
// // {
// // // Fetch and process data specific to the athlete
// // return $this->render('coach/athlete_analysis.html.twig', [
// // 'athleteId' => $athleteId,
// // ]);
// // }
// // #[Route('/add-athlete/{athleteId}', name: 'coach_add_athlete', methods: ['POST'])]
// // public function addAthlete(IRequest $request, $athleteId): IResponse
// // { // // {
// // // Implement logic to add athlete
// // // ...
// // return $this->redirectToRoute('coach_list_athletes'); // // return $this->redirectToRoute("/athletes");
// // } // // }
// // // #[Route('/remove-athlete', name: 'coach_remove_athlete', methods: ['POST'])]
// // // public function removeAthlete(int $athleteId, IRequest $request): IResponse
// // // {
// // // return $this->redirectToRoute("/athletes");
// // // }
// } // }

@ -48,7 +48,6 @@ class FrontController {
$this->handleError(404, $e->getMessage()); $this->handleError(404, $e->getMessage());
} }
catch(\Throwable $e){ catch(\Throwable $e){
Log::dd($e->getLine() . $e->getFile() . $e->getMessage() );
$this->handleError(501, $e->getMessage()); $this->handleError(501, $e->getMessage());
} }
} }
@ -66,7 +65,7 @@ class FrontController {
// TODO : Don't work need Antoine help // TODO : Don't work need Antoine help
private function handleError(int $statusCode, $message) : void { private function handleError(int $statusCode, $message) : void {
if (!$this->container->has(\Twig\Environment::class)) { if (!$this->container->has(\Twig\Environment::class)) {
throw new \LogicException('You cannot use the "renderView" method if the Twig Bundle is not available. Try running "composer require ".'); throw new \LogicException('You cannot use the "renderView" method if the Twig Bundle is not available. Try running "composer require symfony/twig-bundle".');
} }
$response = new Response($this->container->get(\Twig\Environment::class)->render('./error/error.html.twig',['title'=> $message , "code" => $statusCode, "name" => $message, "descr" => $message ]),$statusCode); $response = new Response($this->container->get(\Twig\Environment::class)->render('./error/error.html.twig',['title'=> $message , "code" => $statusCode, "name" => $message, "descr" => $message ]),$statusCode);

@ -1,94 +1,36 @@
<?php <?php
namespace App\Controller; // namespace App\Controller;
use App\Container; // use App\Container;
use App\Router\Request\IRequest; // use App\Router\Request\IRequest;
use App\Router\Response\IResponse; // use App\Router\Response\Response;
use App\Router\Response\RedirectResponse; // use Shared\Attributes\Route;
use App\Router\Response\Response; // use Twig\Environment;
use Manager\ActivityManager; // use Data\Core\Preferences;
use Shared\Attributes\Route; // use Shared\Log;
use Twig\Environment;
use Data\Core\Preferences; // class HeartRateController extends BaseController
use Shared\Log; // {
class HeartRateController extends BaseController
{ // #[Route(path: '/import', name: 'import', methods: ['GET'])]
private ActivityManager $activityMgr; // public function import(): Response
// {
public function __construct(ActivityManager $manager) // return $this->render('./page/import.html.twig',[
{ // 'css' => $this->preference->getCookie(),
parent::__construct(); // 'pp' => "test2",
$this->activityMgr = $manager; // 'user' => "Doe",
} // 'role' => "Athlète",
// 'friendship' => [],
#[Route(path: '/import', name: 'import', methods: ['GET'])] // 'analyzes' => [],
public function import(): Response // 'mails' => [],
{ // 'users' => [],
return $this->render('./page/import.html.twig', [ // 'infoUser' => [],
'css' => $this->preference->getCookie(), // 'exos' => [],
'pp' => "test2", // 'member' => []
'user' => "Doe", // ]);
'role' => "Athlète", // }
'friendship' => [],
'analyzes' => [],
'mails' => [], // }
'users' => [],
'infoUser' => [],
'exos' => [],
'member' => []
]);
}
#[Route(path: '/upload', name: 'upload', methods: ['POST'])]
public function uploadFile(string $activityType, int $effort, IRequest $req): IResponse
{
$error = $this->validateRequest($effort);
if (!empty($error)) {
return $this->renderError($error);
}
$tmp_file = $_FILES['uploaded_file']['tmp_name'];
if (!$this->isValidFile($tmp_file)) {
return $this->renderError(['Failed to get file be sure that you provide the file']);
}
$content = file_get_contents($tmp_file);
try {
if ($this->activityMgr->uploadFile($activityType, 5, $content)) {
return new RedirectResponse('/home');
}
} catch (\Exception $e) {
return $this->renderError([$e->getMessage()]);
}
return $this->renderError(['Failed to save activity.']);
}
private function validateRequest(int $effort): array
{
$error = [];
if ($effort < 0 || $effort > 5) {
$error[] = 'Invalid effort level.';
}
$fileExtension = pathinfo($_FILES['uploaded_file']['name'], PATHINFO_EXTENSION);
if ($fileExtension !== 'fit') {
$error[] = 'Invalid file type. Only .fit files are allowed.';
}
return $error;
}
private function isValidFile(string $tmp_file): bool
{
return file_exists($tmp_file) && is_uploaded_file($tmp_file);
}
private function renderError(array $error): Response
{
// Consolidez la logique de rendu ici
return $this->render('./error/error.html.twig', ['title'=> "Failed" , "code" => 400, "name" => "error import", "descr" => $error[0] ], new Response('$error', 400));
}
}

@ -1,66 +1,19 @@
<?php <?php
namespace App\Controller; // namespace App\Controller;
use App\Container; // use App\Container;
use App\Router\Request\IRequest; // use App\Router\Request\IRequest;
use App\Router\Response\Response; // use App\Router\Response\Response;
use Database\AthleteGateway; // use App\Router\Response\IResponse;
use Database\AthleteMapper;
use Database\Connexion;
use Database\NotificationGateway;
use Database\NotificationMapper;
use Shared\Attributes\Route;
use Twig\Environment;
use Data\Core\Preferences;
use Shared\Log;
class SocialController extends BaseController // use Shared\Attributes\Route;
{ // use Twig\Environment;
protected Preferences $preference; // use Data\Core\Preferences;
// use Shared\Log;
public function __construct(){
$this->preference = new Preferences();
}
#[Route(path: '/notification', name: 'notification', methods: ['GET'])]
public function mail(): Response
{
try {
$notificationGateway = new NotificationGateway(new Connexion(DSN, DB_USER, DB_PASSWORD));
$listSearch = $notificationGateway->getNotifications();
$map = new NotificationMapper();
$notificationEntity = $map->notificationSqlToEntity($listSearch);
$listUsers = []; // #[Route(path: '/coach', name: 'coach')]
// class CoachController extends BaseController
foreach ($notificationEntity as $entity) { // {
$notification = $map->notificationEntityToModel($entity);
$listUsers[] = ['idnotif' => $notification->getId(), 'message' => $notification->getMessage(),
'date' => $notification->getDate()->format("D j F Y"),'statut' => $notification->getStatut(), 'urgence' => $notification->getUrgence(),
'idathlete' => $notification->getToUserId()];
}
$response = $this->render('./page/notification.html.twig',[
'css' => $this->preference->getCookie(),
'pp' => "test2",
'user' => "Doe",
'role' => "Athlète",
'friendship' => [],
'analyzes' => [],
'mails' => $listUsers,
'users' => [],
'infoUser' => [],
'exos' => [],
'member' => []
]);
} catch (\Throwable $th) {
throw $th;
return $this->render("notification.html.twig", ['tabError' => $taberror]);
}
return $response;
}
}

@ -4,37 +4,21 @@ namespace App\Controller;
use App\Container; use App\Container;
use App\Router\Request\IRequest; use App\Router\Request\IRequest;
use App\Router\Response\RedirectResponse;
use App\Router\Response\Response; use App\Router\Response\Response;
use App\Router\Response\IResponse;
use App\Router\Session;
use Manager\UserManager;
use Shared\Attributes\Route; use Shared\Attributes\Route;
use Shared\Validation;
use Twig\Environment; use Twig\Environment;
use Data\Core\Preferences; use Data\Core\Preferences;
use Shared\Log; use Shared\Log;
use Stub\AthleteGateway;
use Stub\Connexion;
use DateInterval;
use DateTime;
use \PDOException;
class UserController extends BaseController class UserController extends BaseController
{ {
private UserManager $userMgr;
public function __construct(UserManager $manager)
{
parent::__construct();
$this->userMgr = $manager;
}
#[Route(path: '/', name: 'index', methods: ['GET'])] #[Route(path: '/', name: 'home', methods: ['GET'])]
public function index(): Response public function index(): Response
{ {
return $this->render('./page/index.html', [
return $this->render('./page/home.html.twig',[
'css' => $this->preference->getCookie(), 'css' => $this->preference->getCookie(),
'pp' => "test2", 'pp' => "test2",
'user' => "Doe", 'user' => "Doe",
@ -49,111 +33,11 @@ class UserController extends BaseController
]); ]);
} }
#[Route(path: '/mock', name: 'mock', methods: ['GET'])]
public function createTablesFromMock()
{
try {
$connection = new Connexion(DSN, DB_USER, DB_PASSWORD);
echo "Connexion à la base de données réussie";
// Lire le contenu du fichier mock/tables.sql
$sql = file_get_contents(__DIR__ . '/../../data/core/database/data/tables.sql'); // Assurez-vous de spécifier le chemin correct
// Exécuter la requête SQL pour créer les tables
$result = $connection->executeQuery($sql);
if ($result) {
echo "Tables créées avec succès.";
} else {
Log::dd("Erreur lors de la création des tables.");
}
$sql = file_get_contents(__DIR__ . '/../../data/core/database/data/athlete.sql');
$result = $connection->executeQuery($sql);
if ($result) {
echo "Athlete créées avec succès.";
} else {
Log::dd("Erreur lors de la création des Athlete.");
}
$sql = file_get_contents(__DIR__ . '/../../data/core/database/data/friendship.sql');
$result = $connection->executeQuery($sql);
if ($result) {
echo "friendship créées avec succès.";
} else {
Log::dd("Erreur lors de la création des friendship.");
}
$sql = file_get_contents(__DIR__ . '/../../data/core/database/data/frequenceCardiaque.sql');
$result = $connection->executeQuery($sql);
if ($result) {
echo "frequenceCardiaque créées avec succès.";
} else {
Log::dd("Erreur lors de la création des friendship.");
}
} catch (PDOException $e) {
Log::dd("Erreur de connexion à la base de données : " . $e->getMessage());
}
Log::dd("Database Mock succesfully create");
}
#[Route(path: '/home', name: 'home', methods: ['GET'])]
public function home(): IResponse
{
$athleteGateway = new AthleteGateway(new Connexion(DSN, DB_USER, DB_PASSWORD));
$activity = $athleteGateway->getListActivity($this->userMgr->getCurrentUser()->getId());
$charts = [];
$currentDate = new DateTime();
$interval = new DateInterval('P1M'); // Période d'un mois
for ($i = 0; $i < 12; $i++) {
$currentMonth = $currentDate->format('n');
// Recherche de l'indice du mois dans le tableau $activity
$activityIndex = null;
for ($j = 0; $j < count($activity); $j++) {
if (!empty($activity[$j]['mois']) && $activity[$j]['mois'] == $currentMonth) {
$activityIndex = $j;
break;
}
}
// Récupération du nombre d'activités et réinitialisation à 0
$nbActivity = isset($activityIndex) ? $activity[$activityIndex]['nbactivite'] : 0;
if (isset($activityIndex)) {
$activity[$activityIndex]['nbactivite'] = 0;
}
$charts[] = ['act' => $nbActivity, 'mois' => $currentMonth];
$currentDate->sub($interval);
}
$charts = array_reverse($charts);
return $this->render('./page/home.html.twig', [
'css' => $this->preference->getCookie(),
'pp' => "test2",
'user' => $this->userMgr->getCurrentUser()->getNom(),
'role' => $this->userMgr->getCurrentUser()->getRole()::class,
'friendship' => $this->userMgr->getCurrentUser()->getRole()->getUsersList(),
'analyzes' => $this->userMgr->getCurrentUser()->getRole()->getUsersList(),
'charts' => $charts,
'mails' => [],
'users' => [],
'infoUser' => [],
'exos' => [],
'member' => []
]);
}
#[Route(path: '/settings', name: 'settings', methods: ['GET'])] #[Route(path: '/settings', name: 'settings', methods: ['GET'])]
public function settings(IRequest $req): Response public function settings(IRequest $req): Response
{ {
return $this->render('./page/settings.html.twig', [ return $this->render('./page/settings.html.twig',[
'css' => $this->preference->getCookie(), 'css' => $this->preference->getCookie(),
'pp' => "test2", 'pp' => "test2",
'user' => "Doe", 'user' => "Doe",
@ -168,33 +52,15 @@ class UserController extends BaseController
]); ]);
} }
#[Route(path: '/profile', name: 'profile', methods: ['GET'])]
public function profile(): Response
{
return $this->render('./page/profile.html.twig', [
'css' => $this->preference->getCookie(),
'pp' => "test2",
'user' => "Doe",
'role' => "Athlète",
'friendship' => [],
'analyzes' => [],
'mails' => [],
'users' => [],
'infoUser' => [],
'exos' => [],
'member' => []
]);
}
#[Route(path: '/preferences', name: 'preferences', methods: ['POST'])] #[Route(path: '/preferences', name: 'preferences', methods: ['POST'])]
public function preferences(string $theme, IRequest $req): Response public function preferences(string $theme, IRequest $req): Response
{ {
/*TODO*/
// VALIDER LES DONNEES // VALIDER LES DONNEES
$this->preference->majCookie($theme); $this->preference->majCookie($theme);
return $this->render('./page/settings.html.twig', [ return $this->render('./page/settings.html.twig',[
'css' => $this->preference->getCookie(), 'css' => $this->preference->getCookie(),
'pp' => "test2", 'pp' => "test2",
'user' => "Doe", 'user' => "Doe",

@ -1,15 +1,12 @@
<?php <?php
namespace App\Router; namespace App\Router;
use App\Router\Request\IRequest; use App\Router\Request\IRequest;
/** /**
* Router class to manage a collection of routes in the application. * Router class to manage a collection of routes in the application.
* It provides functionalities to add routes and check if a given URL matches any of the defined routes. * It provides functionalities to add routes and check if a given URL matches any of the defined routes.
*/ */
class Router class Router {
{
/** /**
* The base path for routing. * The base path for routing.
@ -37,8 +34,7 @@ class Router
* *
* @param string $path The base path for the router. * @param string $path The base path for the router.
*/ */
public function __construct(string $path = "/PHP/project/index.php") public function __construct(string $path = "/PHP/project/index.php") {
{
$this->path = $path; $this->path = $path;
$this->routes = new \AltoRouter(); $this->routes = new \AltoRouter();
} }
@ -50,8 +46,7 @@ class Router
* @param Route $route The route object. * @param Route $route The route object.
* @throws \InvalidArgumentException If method is not supported. * @throws \InvalidArgumentException If method is not supported.
*/ */
public function add(string $method, Route $route) public function add(string $method, Route $route) {
{
if (!in_array($method, self::$verbs)) { if (!in_array($method, self::$verbs)) {
throw new \InvalidArgumentException("Method not supported"); throw new \InvalidArgumentException("Method not supported");
} }
@ -60,28 +55,20 @@ class Router
/** /**
* Adds a route for a controller action. * Adds a route for a controller action.
* TODO : the problème is that AltoRouter is a map so i can't have mutilple Route just by doing this:(i need to find a logic to resolve this beavior) #[Route('/login', name: 'login',methods: ['POST','GET'])] *
* @param string|array $methods HTTP method. * @param string $method The HTTP method.
* @param string $path The path for the route. * @param string $path The path for the route.
* @param mixed $controller The controller object. * @param mixed $controller The controller object.
* @param string $action The action method in the controller. * @param string $action The action method in the controller.
* @param string $name (Optional) The name of the route. * @param string $name (Optional) The name of the route.
* @throws \InvalidArgumentException If method is not supported. * @throws \InvalidArgumentException If method is not supported.
*/ */
public function addControllerRoute(string|array $methods, string $path, $controller, string $action, string $name = '') public function addControllerRoute(string $method, string $path, $controller, string $action, string $name = '') {
{
if (is_string($methods)) {
$methods = [$methods]; // Convert to an array if it's a string
}
foreach ($methods as $method) {
if (!in_array($method, self::$verbs)) { if (!in_array($method, self::$verbs)) {
throw new \InvalidArgumentException("Method not supported"); throw new \InvalidArgumentException("Method not supported");
} }
$this->routes->map($method, $path, [$controller, $action], $name); $this->routes->map($method, $path, [$controller, $action], $name);
} }
}
// TODO: Implement the extractParams method. // TODO: Implement the extractParams method.
// public function extractParams(string $path) {} // public function extractParams(string $path) {}
@ -93,8 +80,7 @@ class Router
* @param callable $callable The callback function. * @param callable $callable The callback function.
* @param string $name The name of the route. * @param string $name The name of the route.
*/ */
public function get(string $path, callable $callable, $name) public function get(string $path, callable $callable, $name) {
{
$this->routes->map('GET', $path, $callable, $name); $this->routes->map('GET', $path, $callable, $name);
} }
@ -106,8 +92,7 @@ class Router
* @param IRequest $request The request object. * @param IRequest $request The request object.
* @return array|null The matched route or null if no match. * @return array|null The matched route or null if no match.
*/ */
public function match(IRequest $request): ?array public function match(IRequest $request): ?array {
{
return $this->routes->match($request->getRequestUri(), $request->getMethod()) ?: null; return $this->routes->match($request->getRequestUri(), $request->getMethod()) ?: null;
} }
@ -116,15 +101,14 @@ class Router
* *
* @return array The array of routes. * @return array The array of routes.
*/ */
public function getRoutes() public function getRoutes() {
{
return []; // TODO: Implement the actual logic to return routes. return []; // TODO: Implement the actual logic to return routes.
} }
public function generate(string $routeName, array $params = array()): string public function generate (string $routeName, array $params = array()): string
{ {
return $this->routes->generate($routeName, $params); return $this->routes->generate($routeName,$params);
} }
} }

@ -111,7 +111,8 @@ class Session
if ( $this->sessionState == self::SESSION_STARTED ) if ( $this->sessionState == self::SESSION_STARTED )
{ {
$this->sessionState = !session_destroy(); $this->sessionState = !session_destroy();
session_unset(); // Clear all session variables unset( $_SESSION );
return !$this->sessionState; return !$this->sessionState;
} }

@ -2,24 +2,26 @@
namespace App\Router\Middleware; namespace App\Router\Middleware;
use App\Router\Session; use App\Router\Session;
use Network\IAuthService;
use Shared\Log; use Shared\Log;
use App\Router\Request\IRequest; use App\Router\Request\IRequest;
use App\Router\Response\RedirectResponse; use App\Router\Response\RedirectResponse;
class AuthMiddleware extends Middleware { class AuthMiddleware extends Middleware {
private IAuthService $auth;
public function __construct(IAuthService $auth) {
$this->auth = $auth;
}
public function handle(IRequest $request, callable $next) { public function handle(IRequest $request, callable $next) {
$excludedUrls = ['/login', '/register','/forgetPassword', '/', '/mock']; // if (isset($_SESSION['user'])) {
if ($this->auth->getCurrentUser() === null && !in_array($request->getRequestUri(), $excludedUrls)) { // $resp =new RedirectResponse("/");
$resp = new RedirectResponse("/login"); // $resp->send();
$resp->send(); // exit;
exit; // }
} // La page nest pas redirigée correctement
// Firefox a détecté que le serveur redirige la demande pour cette adresse dune manière qui naboutira pas.
// La cause de ce problème peut être la désactivation ou le refus des cookies.
// if (!isset($_SESSION['user'])) {
// $resp =new RedirectResponse("/log");
// $resp->send();
// exit;
// }
return parent::handle($request, $next); return parent::handle($request, $next);
} }
} }

@ -2,9 +2,6 @@
namespace App\Router\Response; namespace App\Router\Response;
use App\Router\Session;
use Shared\Log;
class RedirectResponse implements IResponse class RedirectResponse implements IResponse
{ {
private $content; private $content;
@ -52,7 +49,6 @@ class RedirectResponse implements IResponse
public function send(): void public function send(): void
{ {
http_response_code($this->statusCode); http_response_code($this->statusCode);
foreach ($this->headers as $name => $value) { foreach ($this->headers as $name => $value) {

@ -1,8 +1,6 @@
<?php <?php
namespace App\Router\Response; namespace App\Router\Response;
use Shared\Log;
class Response implements IResponse { class Response implements IResponse {
private string $content; private string $content;
private int $statusCode; private int $statusCode;

@ -1,6 +1,5 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" />
@ -35,10 +34,14 @@
<input class="form-check-input" id="inputRememberPassword" type="checkbox" value="" /> <input class="form-check-input" id="inputRememberPassword" type="checkbox" value="" />
<label class="form-check-label" for="inputRememberPassword">Mémoriser le mot de passe</label> <label class="form-check-label" for="inputRememberPassword">Mémoriser le mot de passe</label>
</div> </div>
<div class="d-flex align-items-center justify-content-between mt-4 mb-0">
<a class="small" href="password.html">Mot de passe oublié ?</a>
<a class="btn btn-primary" href="index.html">Se connecter</a>
</div>
</form> </form>
</div> </div>
<div class="card-footer text-center py-3">
<div class="small"><a href="register.html">Besoin d'un compte ? Inscrivez-vous !</a></div>
</div> </div>
</div> </div>
</div> </div>
@ -61,8 +64,8 @@
</div> </div>
</footer> </footer>
</div> </div>
</div> </div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js" crossorigin="anonymous"></script> <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js" crossorigin="anonymous"></script>
<script src="js/scripts.js"></script> <script src="js/scripts.js"></script>
</body> </body>
</html> </html>

@ -7,12 +7,9 @@
<meta name="description" content="Accueil" /> <meta name="description" content="Accueil" />
<meta name="author" content="PINAGOT Antoine" /> <meta name="author" content="PINAGOT Antoine" />
<title>{% block title %}{% endblock %}</title> <title>{% block title %}{% endblock %}</title>
<link href="https://unpkg.com/tailwindcss@^2/dist/tailwind.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/simple-datatables@7.1.2/dist/style.min.css" rel="stylesheet" /> <link href="https://cdn.jsdelivr.net/npm/simple-datatables@7.1.2/dist/style.min.css" rel="stylesheet" />
<link href="/css/{% block css %}styles{% endblock %}.css" rel="stylesheet" /> <link href="/css/{% block css %}style{% endblock %}.css" rel="stylesheet" />
<script src="https://use.fontawesome.com/releases/v6.3.0/js/all.js" crossorigin="anonymous"></script> <script src="https://use.fontawesome.com/releases/v6.3.0/js/all.js" crossorigin="anonymous"></script>
<link rel="stylesheet" href="https://unpkg.com/leaflet/dist/leaflet.css" />
</head> </head>
<body class="sb-nav-fixed"> <body class="sb-nav-fixed">
<nav class="sb-topnav navbar navbar-expand navbar-dark bg-dark"> <nav class="sb-topnav navbar navbar-expand navbar-dark bg-dark">
@ -38,7 +35,7 @@
<li><a class="dropdown-item" href="/profile">Profile</a></li> <li><a class="dropdown-item" href="/profile">Profile</a></li>
<li><a class="dropdown-item" href="/settings">Paramètres</a></li> <li><a class="dropdown-item" href="/settings">Paramètres</a></li>
<li><hr class="dropdown-divider" /></li> <li><hr class="dropdown-divider" /></li>
<li><a class="dropdown-item" href="/">Déconnexion</a></li> <li><a class="dropdown-item" href="/logout">Déconnexion</a></li>
</ul> </ul>
</li> </li>
</ul> </ul>
@ -49,7 +46,7 @@
<div class="sb-sidenav-menu"> <div class="sb-sidenav-menu">
<div class="nav"> <div class="nav">
<div class="sb-sidenav-menu-heading">Menu</div> <div class="sb-sidenav-menu-heading">Menu</div>
<a class="nav-link" href="/home"> <a class="nav-link" href="/">
<div class="sb-nav-link-icon"><img src="/assets/img/house.png"></div> <div class="sb-nav-link-icon"><img src="/assets/img/house.png"></div>
Accueil Accueil
</a> </a>
@ -58,9 +55,9 @@
<div class="sb-nav-link-icon"><img src="/assets/img/sprinter.png"></div> <div class="sb-nav-link-icon"><img src="/assets/img/sprinter.png"></div>
Exercices Exercices
</a> </a>
<a class="nav-link" href="/activity"> <a class="nav-link" href="/analyses">
<div class="sb-nav-link-icon"><i class="fas fa-chart-area"></i></div> <div class="sb-nav-link-icon"><i class="fas fa-chart-area"></i></div>
Activités Analyses
</a> </a>
<div class="sb-sidenav-menu-heading">Social</div> <div class="sb-sidenav-menu-heading">Social</div>
<a class="nav-link" href="/friendlist"> <a class="nav-link" href="/friendlist">
@ -71,7 +68,7 @@
<div class="sb-nav-link-icon"><img src="/assets/img/coaching.png"></div> <div class="sb-nav-link-icon"><img src="/assets/img/coaching.png"></div>
Coaching Coaching
</a> </a>
<a class="nav-link" href="/notification"> <a class="nav-link" href="/mail">
<div class="sb-nav-link-icon"><img src="/assets/img/letter.png"></div> <div class="sb-nav-link-icon"><img src="/assets/img/letter.png"></div>
Messagerie Messagerie
</a> </a>
@ -111,6 +108,7 @@
<script src="js/scripts.js"></script> <script src="js/scripts.js"></script>
{# <script src="js/preference.js"></script> #} {# <script src="js/preference.js"></script> #}
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.8.0/Chart.min.js" crossorigin="anonymous"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.8.0/Chart.min.js" crossorigin="anonymous"></script>
<script src=".assets/demo/chart-area-demo.js"></script>
<script src="assets/demo/chart-bar-demo.js"></script> <script src="assets/demo/chart-bar-demo.js"></script>
<script src="https://cdn.jsdelivr.net/npm/simple-datatables@7.1.2/dist/umd/simple-datatables.min.js" crossorigin="anonymous"></script> <script src="https://cdn.jsdelivr.net/npm/simple-datatables@7.1.2/dist/umd/simple-datatables.min.js" crossorigin="anonymous"></script>
<script src="js/datatables-simple-demo.js"></script> <script src="js/datatables-simple-demo.js"></script>

@ -21,7 +21,7 @@
<h1 class="display-1">{% block nb %}{% endblock %}</h1> <h1 class="display-1">{% block nb %}{% endblock %}</h1>
<p class="lead">{% block name %}{% endblock %}</p> <p class="lead">{% block name %}{% endblock %}</p>
<p>{% block descr %}{% endblock %}</p> <p>{% block descr %}{% endblock %}</p>
<a href="/home"> <a href="/">
<i class="fas fa-arrow-left me-1"></i> <i class="fas fa-arrow-left me-1"></i>
Retour à l'accueil Retour à l'accueil
</a> </a>

@ -4,84 +4,30 @@
{% block css %}{{css}}{% endblock %} {% block css %}{{css}}{% endblock %}
{% block title %}Analyses - HearthTrack{% endblock %} {% block title %}Exercices - HearthTrack{% endblock %}
{% block user %}{{user}} - {{role}}{% endblock %} {% block user %}{{user}} - {{role}}{% endblock %}
{% block body %} {% block body %}
<div class="container-fluid px-4"> <div class="container-fluid px-4">
<h1 class="mt-4">Analyses</h1> <h1 class="mt-4">Exercices</h1>
<ol class="breadcrumb mb-4"> <ol class="breadcrumb mb-4">
<li class="breadcrumb-item"><a href="/home">Accueil</a></li> <li class="breadcrumb-item"><a href="/">Accueil</a></li>
<li class="breadcrumb-item active">Analyses</li> <li class="breadcrumb-item active">Exercices</li>
</ol> </ol>
<div class="card-body"> <div class="card-body">
<div class="datatable-container"> <div class="datatable-container">
<table id="datatablesSimple" class="datatable-table"> <form method="post" action="/exercices">
<thead> Type : <input type="text" name="type"/>
<tr> Intensité : <input type="text" name="intensite"/>
<th>Date</th> Date : <input type="text" name="date"/>
<th>Heure de début</th> <button class="btn btn-primary btn-mrg" id="btnNavbarSearch" type="submit">Ajouter l'exercice</button>
<th>Heure de fin</th> </form>
<th>Type</th>
<th>effort ressenti</th>
<th>Variabilité</th>
<th>Variance</th>
<th>Ecart type</th>
<th>Moyenne</th>
<th>Maximum</th>
<th>Minimum</th>
<th>Temperature moyenne</th>
<th></th>
</tr>
</thead>
<tfoot>
<tr>
<th>Date</th>
<th>Heure de début</th>
<th>Heure de fin</th>
<th>Type</th>
<th>effort ressenti</th>
<th>Variabilité</th>
<th>Variance</th>
<th>Ecart type</th>
<th>Moyenne</th>
<th>Maximum</th>
<th>Minimum</th>
<th>Temperature moyenne</th>
</tr><tr></tr>
</tfoot>
<tbody>
{% for analyze in analyzes %}
<tr>
<td>{{analyze.date}}</td>
<td>{{analyze.heureDebut}}</td>
<td>{{analyze.heureFin}}</td>
<td>{{analyze.type}}</td>
<td>{{analyze.effortRessenti}}</td>
<td>{{analyze.variabilite}}</td>
<td>{{analyze.variance}}</td>
<td>{{analyze.ecartType}}</td>
<td>{{analyze.moyenne}} Bpm</td>
<td>{{analyze.max}} Bpm</td>
<td>{{analyze.min}} Bpm</td>
<td>{{analyze.temperature}} °C</td>
<td><a href="/analyze?id={{ analyze.idactivity }}">En savoir plus</a></td>
</tr>
{% endfor %}
</tbody>
</table>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
{% endblock %} <h1>{{responce}}</h1>
{% block script %}
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js" crossorigin="anonymous"></script>
<script src="js/scripts.js"></script>
<script src="https://cdn.jsdelivr.net/npm/simple-datatables@7.1.2/dist/umd/simple-datatables.min.js" crossorigin="anonymous"></script>
<script src="js/datatables-simple-demo.js"></script>
{% endblock %} {% endblock %}

@ -12,7 +12,7 @@
<div class="container-fluid px-4"> <div class="container-fluid px-4">
<h1 class="mt-4">Liste d'ami</h1> <h1 class="mt-4">Liste d'ami</h1>
<ol class="breadcrumb mb-4"> <ol class="breadcrumb mb-4">
<li class="breadcrumb-item"><a href="/home">Accueil</a></li> <li class="breadcrumb-item"><a href="/">Accueil</a></li>
<li class="breadcrumb-item active">Ami</li> <li class="breadcrumb-item active">Ami</li>
</ol> </ol>

@ -12,7 +12,7 @@
<div class="container-fluid px-4"> <div class="container-fluid px-4">
<h1 class="mt-4">Coaching</h1> <h1 class="mt-4">Coaching</h1>
<ol class="breadcrumb mb-4"> <ol class="breadcrumb mb-4">
<li class="breadcrumb-item"><a href="/home">Accueil</a></li> <li class="breadcrumb-item"><a href="/">Accueil</a></li>
<li class="breadcrumb-item active">Coaching</li> <li class="breadcrumb-item active">Coaching</li>
</ol> </ol>

@ -4,151 +4,63 @@
{% block css %}{{css}}{% endblock %} {% block css %}{{css}}{% endblock %}
{% block title %}Exercices - HearthTrack{% endblock %} {% block title %}Analyses - HearthTrack{% endblock %}
{% block user %}{{user}} - {{role}}{% endblock %} {% block user %}{{user}} - {{role}}{% endblock %}
{% block body %} {% block body %}
<div class="container-fluid px-4"> <div class="container-fluid px-4">
<h1 class="mt-4">Exercices</h1> <h1 class="mt-4">Analyses</h1>
<ol class="breadcrumb mb-4"> <ol class="breadcrumb mb-4">
<li class="breadcrumb-item"><a href="/home">Accueil</a></li> <li class="breadcrumb-item"><a href="/">Accueil</a></li>
<li class="breadcrumb-item active">Exercices</li> <li class="breadcrumb-item active">Analyses</li>
<script src="https://unpkg.com/leaflet/dist/leaflet.js"></script>
</ol> </ol>
<div class="card-body"> <div class="card-body">
{# <table id="datatablesSimple" class="datatable-table">#} <div class="datatable-container">
{# <thead>#} <table id="datatablesSimple" class="datatable-table">
{# <tr>#} <thead>
{# <th>id FC</th>#} <tr>
{# <th>altitude</th>#} <th>Date</th>
{# <th>temps</th>#} <th>Type</th>
{# <th>Temperature</th>#} <th>BMP</th>
{# <th>bpm</th>#} <th>KM/H</th>
{# <th>longitude</th>#} <th>Distance</th>
{# <th>latitude</th>#} <th></th>
{# <th>activiteid</th>#} </tr>
{# <th></th>#} </thead>
{# </tr>#} <tfoot>
{# </thead>#} <tr>
{# {% for analyze in analyzes %}#} <th>Date</th>
{# <tbody>#} <th>Type</th>
{# <tr>#} <th>BPM</th>
{# <td>{{analyze.idfc}}</td>#} <th>KM/H</th>
{# <td>{{analyze.altitude}}</td>#} <th>Distance</th>
{# <td>{{analyze.temps}}</td>#} </tr><tr></tr>
{# <td>{{analyze.temperature}}</td>#}
{# <td>{{analyze.bpm}}</td>#}
{# <td>{{analyze.longitude}}</td>#}
{# <td>{{analyze.latitude}}</td>#}
{# <td>{{analyze.activiteid}}</td>#}
{# <td><a href="/home">Home</a></td>#}
{# </tr>#}
{# </tbody>#}
{# {% endfor %}#}
{# </table>#}
{# <div>#}
{# <canvas id="myChart" width="400" height="200">#}
{# <p>Hello Fallback World</p>#}
{# </canvas>#}
{# </div>#}
{# <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>#}
{# <script>#}
{# const ctx = document.getElementById('myChart');#}
{# new Chart(ctx, {#}
{# type: 'line',#}
{# data: {#}
{# labels: [#}
{# {% for analyze in analyzes %}#}
{# {{analyze.temps}}#}
{# {% endfor %}#}
{# ],#}
{# datasets: [{#}
{# label: 'Batement par minute',#}
{# data: [#}
{# {% for analyze in analyzes %}#}
{# {{analyze.bpm}}#}
{# {% endfor %}#}
{# ],#}
{# borderWidth: 1#}
{# }]#}
{# },#}
{# options: {#}
{# scales: {#}
{# y: {#}
{# beginAtZero: true#}
{# }#}
{# }#}
{# }#}
{# });#}
{# </script>#}
<div>
<canvas id="myChart" height="50">
<p>Hello Fallback World</p>
</canvas>
</div>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script>
const ctx = document.getElementById('myChart');
const labels = [
{% for analyze in analyzes %}
'{{ analyze.temps }}',
{% endfor %}
];
const data = [
{% for analyze in analyzes %}
{{ analyze.bpm }},
{% endfor %}
];
new Chart(ctx, {
type: 'line',
data: {
labels: labels,
datasets: [{
label: 'Batement par minute',
data: data,
borderWidth: 1,
tension: 0.2,
fill: false,
borderColor: 'rgb(255, 0, 0)'
}]
},
options: {
scales: {
y: {
beginAtZero: false
}
}
}
});
</script>
<div class="card-body">
<div id="map" style="height: 500px;"></div>
<script>
document.addEventListener("DOMContentLoaded", function () {
{#var lat = {{ analyze.latitude }}#}
var map = L.map('map').setView([45.75771709151474, 3.113484980409329], 14);
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '© OpenStreetMap contributors'
}).addTo(map);
</tfoot>
<tbody>
{% for analyze in analyzes %} {% for analyze in analyzes %}
var marker = L.marker([{{ analyze.latitude }}, {{ analyze.longitude }}]).addTo(map); <tr>
marker.bindPopup(` <td>{{analyze.date}}</td>
<strong>Date:</strong> {{ analyze.temps }}<br> <td>{{analyze.type}}</td>
<strong>FC:</strong> {{ analyze.bpm }}<br> <td>{{analyze.bpm}}</td>
<strong>Altitude:</strong> {{ analyze.altitude }}<br> <td>{{analyze.kmh}} Km/H</td>
<strong>Temperature:</strong> {{ analyze.temperature }} <td>{{analyze.distance}} Km</td>
`); <td><a href="#about">En savoir plus</a></td>
</tr>
{% endfor %} {% endfor %}
}); </tbody>
</script> </table>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<h1>{{responce}}</h1> {% endblock %}
{% block script %}
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js" crossorigin="anonymous"></script>
<script src="js/scripts.js"></script>
<script src="https://cdn.jsdelivr.net/npm/simple-datatables@7.1.2/dist/umd/simple-datatables.min.js" crossorigin="anonymous"></script>
<script src="js/datatables-simple-demo.js"></script>
{% endblock %} {% endblock %}

@ -13,7 +13,7 @@
<div class="container-fluid px-4"> <div class="container-fluid px-4">
<h1 class="mt-4">Coaching</h1> <h1 class="mt-4">Coaching</h1>
<ol class="breadcrumb mb-4"> <ol class="breadcrumb mb-4">
<li class="breadcrumb-item"><a href="/home">Accueil</a></li> <li class="breadcrumb-item"><a href="/">Accueil</a></li>
<li class="breadcrumb-item active">Coaching</li> <li class="breadcrumb-item active">Coaching</li>
</ol> </ol>
<style>.btn-mrg{margin:15px; margin-left:83%}</style> <style>.btn-mrg{margin:15px; margin-left:83%}</style>

@ -9,11 +9,10 @@
{% block user %}{{user}} - {{role}}{% endblock %} {% block user %}{{user}} - {{role}}{% endblock %}
{% block body %} {% block body %}
<div class="container-fluid px-4"> <div class="container-fluid px-4">
<h1 class="mt-4">Exercices</h1> <h1 class="mt-4">Exercices</h1>
<ol class="breadcrumb mb-4"> <ol class="breadcrumb mb-4">
<li class="breadcrumb-item"><a href="/home">Accueil</a></li> <li class="breadcrumb-item"><a href="/">Accueil</a></li>
<li class="breadcrumb-item active">Exercices</li> <li class="breadcrumb-item active">Exercices</li>
</ol> </ol>
<style>.btn-mrg{margin:15px; margin-left:85%}</style> <style>.btn-mrg{margin:15px; margin-left:85%}</style>
@ -26,39 +25,18 @@
<thead> <thead>
<tr> <tr>
<th>Date</th> <th>Date</th>
<th>Description</th> <th>Type</th>
<th>Localisation</th> <th>Intensité prévue</th>
<th>FeedBack</th> <th>Status</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<script src="https://unpkg.com/leaflet/dist/leaflet.js"></script>
{% for exo in exos %} {% for exo in exos %}
<tr> <tr>
<td>{{ exo.date }}</td> <td>{{exo.date}}</td>
<td>{{ exo.description }}</td> <td>{{exo.type}}</td>
<td> <td>{{exo.intensite}}</td>
<div id="map-{{ loop.index }}" <td>{{exo.status}}</td>
data-lat=45.758285982369415
data-lng=3.110223414416445
style="height: 300px; width: 650px;"></div>
<script>
document.addEventListener("DOMContentLoaded", function() {
var map{{ loop.index }} = L.map('map-{{ loop.index }}').setView([45.75771709151474, 3.113484980409329], 14);
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '© OpenStreetMap contributors'
}).addTo(map{{ loop.index }});
var marker{{ loop.index }} = L.marker([45.75771709151474, 3.113484980409329]).addTo(map{{ loop.index }});
marker{{ loop.index }}.bindPopup(`
<strong>Date:</strong> {{ exo.date }}<br>
<strong>Description:</strong> {{ exo.description }}<br>
<strong>Feedback:</strong> {{ exo.feedback }}
`);
});
</script>
</td>
<td>{{ exo.feedback }}</td>
</tr> </tr>
{% endfor %} {% endfor %}
</tbody> </tbody>

@ -12,7 +12,7 @@
<div class="container-fluid px-4"> <div class="container-fluid px-4">
<h1 class="mt-4">Liste d'ami</h1> <h1 class="mt-4">Liste d'ami</h1>
<ol class="breadcrumb mb-4"> <ol class="breadcrumb mb-4">
<li class="breadcrumb-item"><a href="/home">Accueil</a></li> <li class="breadcrumb-item"><a href="/">Accueil</a></li>
<li class="breadcrumb-item active">Ami</li> <li class="breadcrumb-item active">Ami</li>
</ol> </ol>
<style>.btn-mrg{margin:15px; margin-left:87%}</style> <style>.btn-mrg{margin:15px; margin-left:87%}</style>

@ -21,42 +21,9 @@
<i class="fas fa-chart-area me-1"></i> <i class="fas fa-chart-area me-1"></i>
Stastiques globales Stastiques globales
</div> </div>
<div> <div class="card-body">
<canvas id="myChart" height="50" width="100"> {# <canvas id="myAreaChart" width="100%" height="40"></canvas> #}
</canvas> </div>
</div>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script>
var ctx = document.getElementById('myChart');
var chartsData = {{ charts|json_encode|raw }};
var labels = chartsData.map((m) => m.mois);
var data = chartsData.map((m) => m.act);
new Chart(ctx, {
type: 'line',
data: {
labels: labels,
datasets: [{
label: 'Activité du mois',
data: data,
borderWidth: 1,
tension: 0.2,
fill: false,
borderColor: 'rgb(255, 0, 0)'
}]
},
options: {
scales: {
x: {
// type: 'linear', // Utiliser une échelle linéaire pour les mois
position: 'bottom'
},
y: {
beginAtZero: true
}
}
}
});
</script>
</div> </div>
</div> </div>

@ -9,56 +9,33 @@
{% block user %}{{user}} - {{role}}{% endblock %} {% block user %}{{user}} - {{role}}{% endblock %}
{% block body %} {% block body %}
<div class="container-fluid px-4"> <div class="container-fluid px-4">
<h1 class="mt-4">Importer</h1> <h1 class="mt-4">Importer</h1>
<ol class="breadcrumb mb-4"> <ol class="breadcrumb mb-4">
<li class="breadcrumb-item"><a href="/">Accueil</a></li> <li class="breadcrumb-item"><a href="home.html">Accueil</a></li>
<li class="breadcrumb-item active">Importer</li> <li class="breadcrumb-item active">Importer</li>
</ol> </ol>
<div class="flex items-center justify-center">
<div class="sm:max-w-lg w-full p-10 bg-white rounded-xl z-10 "> <div class="row">
<div class="text-center"> <div class="col">
<h2 class="mt-5 text-3xl font-bold text-gray-900"> <div class="card mb-4">
Importer un fichier .fit ! <div class="card-header">
</h2> <img src="/assets/img/bupload.png"></i>
<p class="mt-2 text-sm text-gray-400">Let's go</p> Importer un fichier .fit
</div> </div>
<form class="mt-8 space-y-3" action="/upload" method="POST" enctype="multipart/form-data"> <div class="card-body">
<div class="grid grid-cols-1 space-y-2">
<label class="text-sm font-bold text-gray-500 tracking-wide">Veuillez renseigner le type d'activité</label> <div style="text-align:center; margin-bottom: 15px;">
<input class="text-base p-2 border border-gray-300 rounded-lg focus:outline-none focus:border-indigo-500" type="text" name="activityType" placeholder="Course à pied"> <label for="file-input">
</div> <img src="/assets/img/uploadW.svg"/>
<div class="grid grid-cols-1 space-y-2">
<label class="text-sm font-bold text-gray-500 tracking-wide">Effort Level (0-5)</label>
<input class="text-base p-2 border border-gray-300 rounded-lg focus:outline-none focus:border-indigo-500" type="number" name="effort" min="0" max="5" placeholder="Enter effort level (0-5)">
</div>
<div class="grid grid-cols-1 space-y-2">
<label class="text-sm font-bold text-gray-500 tracking-wide">Attach Document</label>
<div class="flex items-center justify-center w-full">
<label class="flex flex-col rounded-lg border-4 border-dashed w-full h-60 p-10 group text-center cursor-pointer">
<div class="h-full w-full text-center flex flex-col items-center justify-center items-center ">
<div class="flex flex-auto max-h-48 w-2/5 mx-auto -mt-10">
<img class="has-mask h-36 object-center" src="https://img.freepik.com/free-vector/image-upload-concept-landing-page_52683-27130.jpg?size=338&ext=jpg" alt="freepik image">
</div>
<p class="pointer-none text-gray-500 "><span class="text-sm">Drag and drop</span> files here <br /> or
<span class="text-blue-600 hover:underline">select a file</span>
from your computer</p>
</div>
<input type="file" class="hidden" id="file-input" name="uploaded_file" accept=".fit">
</label> </label>
<p id="file-name-display" class="text-sm text-gray-500"></p> <form action="/analyses" method="post">
<input id="file-input" type="file" name="fileToUpload" value=""style="visibility: hidden; width:0; height:0;"/>
<input type="submit" value="Soumettre le fichier" name="submit"/>
</form>
</div> </div>
</div> </div>
<p class="text-sm text-gray-300">
<span>File type: .fit</span>
</p>
<div class="flex justify-center">
<button type="submit" class="my-5 w-3/4 flex justify-center bg-blue-500 text-gray-100 p-4 rounded-full tracking-wide
font-semibold focus:outline-none focus:shadow-outline hover:bg-blue-600 shadow-lg cursor-pointer transition ease-in duration-300">
Upload
</button>
</div> </div>
</form>
</div> </div>
</div> </div>
</div> </div>

@ -1,338 +1 @@
<!DOCTYPE html> <a href="/log">Se connecter</button>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
<meta name="description" content="index page du site web" />
<meta name="author" content="PINAGOT Antoine" />
<title>HeartTrack - Getting Started</title>
<link rel="icon" type="image/x-icon" href="assets/favicon.ico" />
<!-- Bootstrap icons-->
<link href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.5.0/font/bootstrap-icons.css" rel="stylesheet" />
<!-- Google fonts-->
<link rel="preconnect" href="https://fonts.gstatic.com" />
<link href="https://fonts.googleapis.com/css2?family=Newsreader:ital,wght@0,600;1,600&amp;display=swap"
rel="stylesheet" />
<link
href="https://fonts.googleapis.com/css2?family=Mulish:ital,wght@0,300;0,500;0,600;0,700;1,300;1,500;1,600;1,700&amp;display=swap"
rel="stylesheet" />
<link href="https://fonts.googleapis.com/css2?family=Kanit:ital,wght@0,400;1,400&amp;display=swap"
rel="stylesheet" />
<!-- Core theme CSS (includes Bootstrap)-->
<link href="css/styles2.css" rel="stylesheet" />
</head>
<body id="page-top">
<!-- Navigation-->
<nav class="navbar navbar-expand-lg navbar-light fixed-top shadow-sm" id="mainNav">
<div class="container px-5">
<a class="navbar-brand fw-bold" href="/">HeartTrack</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarResponsive"
aria-controls="navbarResponsive" aria-expanded="false" aria-label="Toggle navigation">
Menu
<i class="bi-list"></i>
</button>
<div class="collapse navbar-collapse" id="navbarResponsive">
<ul class="navbar-nav ms-auto me-4 my-3 my-lg-0">
<li class="nav-item"><a class="nav-link me-lg-3" href="/login">Se connecter</a></li>
<li class="nav-item"><a class="nav-link me-lg-3" href="/register">S'inscire</a></li>
</ul>
<button class="btn btn-primary rounded-pill px-3 mb-2 mb-lg-0" data-bs-toggle="modal"
data-bs-target="#feedbackModal">
<span class="d-flex align-items-center">
<i class="bi-chat-text-fill me-2"></i>
<span class="small">Donnez votre avis</span>
</span>
</button>
</div>
</div>
</nav>
<!-- Mashead header-->
<header class="masthead">
<div class="container px-5">
<div class="row gx-5 align-items-center">
<div class="col-lg-6">
<!-- Mashead text and app badges-->
<div class="mb-5 mb-lg-0 text-center text-lg-start">
<h1 class="display-1 lh-1 mb-3">HeartTrack pour mobile !</h1>
<p class="lead fw-normal text-muted mb-5">Une application pour suivre vos analyses en direct,
est en cours de développement.</p>
<!-- <div class="d-flex flex-column flex-lg-row align-items-center">
<a class="me-lg-3 mb-4 mb-lg-0" href="#!"><img class="app-badge" src="assets/img/google-play-badge.svg" alt="..." /></a>
<a href="#!"><img class="app-badge" src="assets/img/app-store-badge.svg" alt="..." /></a>
</div> -->
</div>
</div>
<div class="col-lg-6">
<!-- Masthead device mockup feature-->
<div class="masthead-device-mockup">
<svg class="circle" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient id="circleGradient" gradientTransform="rotate(45)">
<stop class="gradient-start-color" offset="0%"></stop>
<stop class="gradient-end-color" offset="100%"></stop>
</linearGradient>
</defs>
<circle cx="50" cy="50" r="50"></circle>
</svg><svg class="shape-1 d-none d-sm-block" viewBox="0 0 240.83 240.83"
xmlns="http://www.w3.org/2000/svg">
<rect x="-32.54" y="78.39" width="305.92" height="84.05" rx="42.03"
transform="translate(120.42 -49.88) rotate(45)"></rect>
<rect x="-32.54" y="78.39" width="305.92" height="84.05" rx="42.03"
transform="translate(-49.88 120.42) rotate(-45)"></rect>
</svg><svg class="shape-2 d-none d-sm-block" viewBox="0 0 100 100"
xmlns="http://www.w3.org/2000/svg">
<circle cx="50" cy="50" r="50"></circle>
</svg>
<div class="device-wrapper">
<div class="device" data-device="iPhoneX" data-orientation="portrait" data-color="black">
<div class="screen bg-black">
<!-- PUT CONTENTS HERE:-->
<!-- * * This can be a video, image, or just about anything else.-->
<!-- * * Set the max width of your media to 100% and the height to-->
<!-- * * 100% like the demo example below.-->
<video muted="muted" autoplay="" loop="" style="max-width: 100%; height: 100%">
<source src="assets/img/demo-screen.mp4" type="video/mp4" />
</video>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</header>
<!-- Quote/testimonial aside-->
<aside class="text-center bg-gradient-primary-to-secondary">
<div class="container px-5">
<div class="row gx-5 justify-content-center">
<div class="col-xl-8">
<div class="h2 fs-1 text-white mb-4">"Une solution gratuite pour analyser vos données de fréquences
cardiaques !"</div>
<img src="assets/img/tnw-logo.svg" alt="..." style="height: 3rem" />
</div>
</div>
</div>
</aside>
<!-- App features section-->
<section id="features">
<div class="container px-5">
<div class="row gx-5 align-items-center">
<div class="col-lg-8 order-lg-1 mb-5 mb-lg-0">
<div class="container-fluid px-5">
<div class="row gx-5">
<div class="col-md-6 mb-5">
<!-- Feature item-->
<div class="text-center">
<i class="bi-phone icon-feature text-gradient d-block mb-3"></i>
<h3 class="font-alt">Web/Mobile</h3>
<p class="text-muted mb-0">Gardez les informations tant bien dans l'application que
sur le site web avec la synchronisation des données !</p>
</div>
</div>
<div class="col-md-6 mb-5">
<!-- Feature item-->
<div class="text-center">
<i class="bi-cast icon-feature text-gradient d-block mb-3"></i>
<h3 class="font-alt">Importez vos données</h3>
<p class="text-muted mb-0">Importez vos données directement depuis un fichier .FIT !
</p>
</div>
</div>
</div>
<div class="row">
<div class="col-md-6 mb-5 mb-md-0">
<!-- Feature item-->
<div class="text-center">
<i class="bi-gift icon-feature text-gradient d-block mb-3"></i>
<h3 class="font-alt">Gratuit</h3>
<p class="text-muted mb-0">Ce site et cette application sont entièrement gratuites !
</p>
</div>
</div>
<div class="col-md-6">
<!-- Feature item-->
<div class="text-center">
<i class="bi-patch-check icon-feature text-gradient d-block mb-3"></i>
<h3 class="font-alt">Open Source</h3>
<p class="text-muted mb-0">Ce projet est fait en Open Source, tout le monde peut y
accéder !</p>
</div>
</div>
</div>
</div>
</div>
<div class="col-lg-4 order-lg-0">
<!-- Features section device mockup-->
<div class="features-device-mockup">
<svg class="circle" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient id="circleGradient" gradientTransform="rotate(45)">
<stop class="gradient-start-color" offset="0%"></stop>
<stop class="gradient-end-color" offset="100%"></stop>
</linearGradient>
</defs>
<circle cx="50" cy="50" r="50"></circle>
</svg><svg class="shape-1 d-none d-sm-block" viewBox="0 0 240.83 240.83"
xmlns="http://www.w3.org/2000/svg">
<rect x="-32.54" y="78.39" width="305.92" height="84.05" rx="42.03"
transform="translate(120.42 -49.88) rotate(45)"></rect>
<rect x="-32.54" y="78.39" width="305.92" height="84.05" rx="42.03"
transform="translate(-49.88 120.42) rotate(-45)"></rect>
</svg><svg class="shape-2 d-none d-sm-block" viewBox="0 0 100 100"
xmlns="http://www.w3.org/2000/svg">
<circle cx="50" cy="50" r="50"></circle>
</svg>
<div class="device-wrapper">
<div class="device" data-device="iPhoneX" data-orientation="portrait" data-color="black">
<div class="screen bg-black">
<!-- PUT CONTENTS HERE:-->
<!-- * * This can be a video, image, or just about anything else.-->
<!-- * * Set the max width of your media to 100% and the height to-->
<!-- * * 100% like the demo example below.-->
<video muted="muted" autoplay="" loop="" style="max-width: 100%; height: 100%">
<source src="assets/img/demo-screen.mp4" type="video/mp4" />
</video>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
<!-- Basic features section-->
<section class="bg-light">
<div class="container px-5">
<div class="row gx-5 align-items-center justify-content-center justify-content-lg-between">
<div class="col-12 col-lg-5">
<h2 class="display-4 lh-1 mb-4">Fonctionnalité supplémentaire de notre application</h2>
<p class="lead fw-normal text-muted mb-5 mb-lg-0">Notre application propose un service de coaching
personnalisé en fonction du besoin que vous avez en tant qu'athelète. Vous pouvez aussi fournir
un service de coaching aux autres utilisateurs en vous inscrivant en tant que coach sportif.</p>
</div>
<div class="col-sm-8 col-md-6">
<div class="px-5 px-sm-0"><img class="img-fluid rounded-circle" src="./assets/img/bg1.png"
alt="..." /></div>
</div>
</div>
</div>
</section>
<!-- Call to action section-->
<section class="cta">
<div class="cta-content">
<div class="container px-5">
<h2 class="text-white display-1 lh-1 mb-4">
Arrêtez d'attendre...
<br />
Inscrivez-vous !
</h2>
<!-- <a class="btn btn-outline-light py-3 px-4 rounded-pill" href="#" target="_blank">Download for free</a> -->
</div>
</div>
</section>
<!-- App badge section-->
<section class="bg-gradient-primary-to-secondary" id="download">
<div class="container px-5">
<h2 class="text-center text-white font-alt mb-4">Application bientôt disponible !</h2>
<!-- <div class="d-flex flex-column flex-lg-row align-items-center justify-content-center">
<a class="me-lg-3 mb-4 mb-lg-0" href="#!"><img class="app-badge" src="assets/img/google-play-badge.svg" alt="..." /></a>
<a href="#!"><img class="app-badge" src="assets/img/app-store-badge.svg" alt="..." /></a>
</div> -->
</div>
</section>
<!-- Footer-->
<footer class="bg-black text-center py-5">
<div class="container px-5">
<div class="text-white-50 small">
<div class="mb-2">&copy; HeartTrack 2023. Tous droits réservé.</div>
<a href="#!">Politique de confidentialité</a>
<span class="mx-1">&middot;</span>
<a href="#!">Termes & Conditions d'utilisation</a>
</div>
</div>
</footer>
<!-- Feedback Modal-->
<div class="modal fade" id="feedbackModal" tabindex="-1" aria-labelledby="feedbackModalLabel" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content">
<div class="modal-header bg-gradient-primary-to-secondary p-4">
<h5 class="modal-title font-alt text-white" id="feedbackModalLabel">Envoyez votre avis</h5>
<button class="btn-close btn-close-white" type="button" data-bs-dismiss="modal"
aria-label="Close"></button>
</div>
<div class="modal-body border-0 p-4">
<!-- * * * * * * * * * * * * * * *-->
<!-- * * SB Forms Contact Form * *-->
<!-- * * * * * * * * * * * * * * *-->
<!-- This form is pre-integrated with SB Forms.-->
<!-- To make this form functional, sign up at-->
<!-- https://startbootstrap.com/solution/contact-forms-->
<!-- to get an API token!-->
<form id="contactForm" data-sb-form-api-token="API_TOKEN">
<!-- Name input-->
<div class="form-floating mb-3">
<input class="form-control" id="name" type="text" placeholder="Entrez votre nom complet..."
data-sb-validations="required" />
<label for="name">Nom complet</label>
<div class="invalid-feedback" data-sb-feedback="name:required">Un nom est requis.</div>
</div>
<!-- Email address input-->
<div class="form-floating mb-3">
<input class="form-control" id="email" type="email" placeholder="nom@exemple.com"
data-sb-validations="required,email" />
<label for="email">Adresse email</label>
<div class="invalid-feedback" data-sb-feedback="email:required">Adresse email requis.</div>
<div class="invalid-feedback" data-sb-feedback="email:email">L'adresse email n'est pas
valide.</div>
</div>
<!-- Phone number input-->
<div class="form-floating mb-3">
<input class="form-control" id="phone" type="tel" placeholder="06 12 34 56 78"
data-sb-validations="required" />
<label for="phone">Numéro de téléphone</label>
<div class="invalid-feedback" data-sb-feedback="phone:required">Numéro de téléphone requis.
</div>
</div>
<!-- Message input-->
<div class="form-floating mb-3">
<textarea class="form-control" id="message" type="text"
placeholder="Entrez votre message..." style="height: 10rem"
data-sb-validations="required"></textarea>
<label for="message">Message</label>
<div class="invalid-feedback" data-sb-feedback="message:required">Un message est requis.
</div>
</div>
<!-- Submit success message-->
<!---->
<!-- This is what your users will see when the form-->
<!-- has successfully submitted-->
<div class="d-none" id="submitSuccessMessage">
<div class="text-center mb-3">
<div class="fw-bolder">Avis envoyé !</div>
</div>
</div>
<!-- Submit error message-->
<!---->
<!-- This is what your users will see when there is-->
<!-- an error submitting the form-->
<div class="d-none" id="submitErrorMessage">
<div class="text-center text-danger mb-3">Erreur du formulaire !</div>
</div>
<!-- Submit Button-->
<div class="d-grid"><button class="btn btn-primary rounded-pill btn-lg disabled"
id="submitButton" type="submit">Envoyer</button></div>
</form>
</div>
</div>
</div>
</div>
<!-- Bootstrap core JS-->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js"></script>
<!-- Core theme JS-->
<script src="js/scripts2.js"></script>
<script src="https://cdn.startbootstrap.com/sb-forms-latest.js"></script>
</body>
</html>

@ -1,79 +1,40 @@
{% extends "authbase.html.twig" %} {% extends "authbase.html.twig" %}
{% block css %}{{ css }}{% endblock %} {% block css %}{{css}}{% endblock %}
{% block title %}Connexion - HearthTrack{% endblock %} {% block title %}Connexion - HearthTrack{% endblock %}
{% block main %} {% block main %}
{#<<<<<<< HEAD#}
<div class="container"> <div class="container">
<div class="row justify-content-center"> <div class="row justify-content-center">
<div class="col-lg-5"> <div class="col-lg-5">
<div class="card shadow-lg border-0 rounded-lg mt-5"> <div class="card shadow-lg border-0 rounded-lg mt-5">
<div class="card-header"><h3 class="text-center font-weight-light my-4">Connexion</h3></div> <div class="card-header"><h3 class="text-center font-weight-light my-4">Connexion</h3></div>
<div class="card-body"> <div class="card-body">
{% if login_error %} <form>
{% for value in login_error %}
<div class="alert alert-danger" role="alert">
{{ value }}
{#=======#}
{# <div class="container">#}
{# <div class="row justify-content-center">#}
{# <div class="col-lg-5">#}
{# <div class="card shadow-lg border-0 rounded-lg mt-5">#}
{# <div class="card-header"><h3 class="text-center font-weight-light my-4">Connexion</h3></div>#}
{# <div class="card-body">#}
{# <form>#}
{# <div class="form-floating mb-3">#}
{# <input class="form-control" id="inputEmail" type="email" placeholder="nom@exemple.com" />#}
{# <label for="inputEmail">Adresse eMail</label>#}
{# </div>#}
{# <div class="form-floating mb-3">#}
{# <input class="form-control" id="inputPassword" type="password" placeholder="Mot de passe" />#}
{# <label for="inputPassword">Mot de passe</label>#}
{# </div>#}
{# <div class="form-check mb-3">#}
{# <input class="form-check-input" id="inputRememberPassword" type="checkbox" value="" />#}
{# <label class="form-check-label" for="inputRememberPassword">Mémoriser le mot de passe</label>#}
{# </div>#}
{# <div class="d-flex align-items-center justify-content-between mt-4 mb-0">#}
{# <a class="small" href="/pass">Mot de passe oublié ?</a>#}
{# <a class="btn btn-primary" href="/home">Se connecter</a>#}
{# </div>#}
{# </form>#}
{# </div>#}
{# <div class="card-footer text-center py-3">#}
{# <div class="small"><a href="/regist">Besoin d'un compte ? Inscrivez-vous !</a></div>#}
{# </div>#}
{#>>>>>>> origin/merged_PLE#}
</div>
{% endfor %}
{% endif %}
<form method="post" action="/login">
<div class="form-floating mb-3"> <div class="form-floating mb-3">
<input class="form-control" id="email" name="email" type="text" placeholder="Nom d'utilisateur" /> <input class="form-control" id="inputEmail" type="email" placeholder="nom@exemple.com" />
<label for="email">Nom d'utilisateur</label> <label for="inputEmail">Adresse eMail</label>
</div> </div>
<div class="form-floating mb-3"> <div class="form-floating mb-3">
<input class="form-control" id="password" name="password" type="password" placeholder="Mot de passe" /> <input class="form-control" id="inputPassword" type="password" placeholder="Mot de passe" />
<label for="password">Mot de passe</label> <label for="inputPassword">Mot de passe</label>
</div> </div>
<div class="form-check mb-3"> <div class="form-check mb-3">
<input class="form-check-input" id="inputRememberPassword" type="checkbox" value="" /> <input class="form-check-input" id="inputRememberPassword" type="checkbox" value="" />
<label class="form-check-label" for="inputRememberPassword">Mémoriser le mot de passe</label> <label class="form-check-label" for="inputRememberPassword">Mémoriser le mot de passe</label>
</div> </div>
<div class="d-flex align-items-center justify-content-between mt-4 mb-0"> <div class="d-flex align-items-center justify-content-between mt-4 mb-0">
<a class="small" href="/forgetPassword">Mot de passe oublié ?</a> <a class="small" href="password.html">Mot de passe oublié ?</a>
<button class="btn btn-primary" type="submit">Se connecter</button> <a class="btn btn-primary" href="index.html">Se connecter</a>
</div> </div>
</form> </form>
</div> </div>
<div class="card-footer text-center py-3"> <div class="card-footer text-center py-3">
<div class="small"><a href="/register">Besoin d'un compte ? Inscrivez-vous !</a></div> <div class="small"><a href="register.html">Besoin d'un compte ? Inscrivez-vous !</a></div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
{% endblock %} {% endblock %}

@ -23,16 +23,14 @@
<th>Lu</th> <th>Lu</th>
<th>De:</th> <th>De:</th>
<th>Description</th> <th>Description</th>
<th>Date</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{% for mail in mails %} {% for mail in mails %}
<tr> <tr>
<td><img src="/assets/img/verif/{{mail.idnotif}}.png" width="25px" height="25px"></td> <td><img src="/assets/img/verif/{{mail.lu}}.png" width="25px" height="25px"></td>
<td>{{mail.idathlete}}</td> <td>{{mail.nom}} {{mail.prenom}}</td>
<td><a href="#">{{mail.message}}</a></td> <td><a href="#">{{mail.message}}</a></td>
<td>{{ mail.date }}</td>
</tr> </tr>
{% endfor %} {% endfor %}
</tbody> </tbody>

@ -18,13 +18,13 @@
<label for="email">Adresse eMail</label> <label for="email">Adresse eMail</label>
</div> </div>
<div class="d-flex align-items-center justify-content-between mt-4 mb-0"> <div class="d-flex align-items-center justify-content-between mt-4 mb-0">
<a class="small" href="/login">Retour à la connexion</a> <a class="small" href="/log">Retour à la connexion</a>
<button class="btn btn-primary" type="submit">Réinitialiser votre mot de passe</button> <button class="btn btn-primary" type="submit">Réinitialiser votre mot de passe</a>
</div> </div>
</form> </form>
</div> </div>
<div class="card-footer text-center py-3"> <div class="card-footer text-center py-3">
<div class="small"><a href="/register">Besoin d'un compte ? Inscrivez-vous !</a></div> <div class="small"><a href="/regist">Besoin d'un compte ? Inscrivez-vous !</a></div>
</div> </div>
</div> </div>
</div> </div>

@ -12,7 +12,7 @@
<div class="container-fluid px-4"> <div class="container-fluid px-4">
<h1 class="mt-4">Profile</h1> <h1 class="mt-4">Profile</h1>
<ol class="breadcrumb mb-4"> <ol class="breadcrumb mb-4">
<li class="breadcrumb-item"><a href="/home">Accueil</a></li> <li class="breadcrumb-item"><a href="/">Accueil</a></li>
<li class="breadcrumb-item active">Profile</li> <li class="breadcrumb-item active">Profile</li>
</ol> </ol>
<div class="row"> <div class="row">

@ -11,106 +11,82 @@
<div class="card shadow-lg border-0 rounded-lg mt-5"> <div class="card shadow-lg border-0 rounded-lg mt-5">
<div class="card-header"><h3 class="text-center font-weight-light my-4">Créer un compte</h3></div> <div class="card-header"><h3 class="text-center font-weight-light my-4">Créer un compte</h3></div>
<div class="card-body"> <div class="card-body">
{# Display error message if register_error is set #}
{% if register_error %}
{% for value in register_error %}
<div class="alert alert-danger" role="alert">
{{ value }}
</div>
{% endfor %}
{% endif %}
<form method="post" action="/register"> <form method="post" action="/register">
<div class="row mb-3"> <div class="row mb-3">
<div class="col-md-6"> <div class="col-md-6">
<div class="form-floating mb-3 mb-md-0"> <div class="form-floating mb-3 mb-md-0">
<input class="form-control" id="nom" name="nom" type="text" placeholder="Entrez votre nom" /> <input class="form-control" id="inputFirstName" type="text" placeholder="Entrez votre nom" />
<label for="nom">Nom de famille</label> <label for="inputFirstName">Nom de famille</label>
</div> </div>
</div> </div>
<div class="col-md-6"> <div class="col-md-6">
<div class="form-floating"> <div class="form-floating">
<input class="form-control" id="prenom" name="prenom" type="text" placeholder="Entrez votre prénom" /> <input class="form-control" id="inputLastName" type="text" placeholder="Entrez votre prénom" />
<label for="prenom">Prénom</label> <label for="inputLastName">Prénom</label>
</div> </div>
</div> </div>
</div> </div>
<div class="row mb-3"> <div class="row mb-3">
<div class="col-md-6"> <div class="col-md-6">
<div class="form-floating mb-3 mb-md-0"> <div class="form-floating mb-3 mb-md-0">
<input class="form-control" id="username" name="username" type="text" placeholder="Entrez votre pseudonyme" /> <label for="inputUsername"></label><input class="form-control" id="inputUsername" type="text" placeholder="Entrez votre pseudonyme" />
<label for="username">Nom d'utilisateur</label> <label for="inputFirstName">Nom d'utilisateur</label>
</div> </div>
</div> </div>
<div class="col-md-6"> <div class="col-md-6">
<label for="sexe" >Sexe:</label>
<div class="form-floating"> <div class="form-floating">
<select id="sexe" name="sexe"> <label for="inputLastName">Sexe</label>
<option value="M">Homme</option> <label for="gender"></label><select id="gender" name="gender">
<option value="H">Femme</option> <option value="male">Homme</option>
<option value="M">Ne se prononce pas</option> <option value="female">Femme</option>
<option value="unknown">Ne se prononce pas</option>
</select> </select>
</div> </div>
</div> </div>
</div> </div>
<div class="form-floating mb-3"> <div class="form-floating mb-3">
<input class="form-control" id="mail" name="mail" type="mail" placeholder="nom@exemple.com" /> <input class="form-control" id="inputEmail" type="email" placeholder="nom@exemple.com" />
<label for="mail">Adresse eMail</label> <label for="inputEmail">Adresse eMail</label>
</div> </div>
<div class="form-floating mb-3"> <div class="form-floating mb-3">
<input class="form-control" id="dateNaissance" name="dateNaissance" type="date" placeholder="" /> <input class="form-control" id="inputDateNaissance" type="date" placeholder="" />
<label for="dateNaissance">Date de naissance</label> <label for="inputEmail">Date de naissance</label>
</div> </div>
<div class="row mb-3"> <div class="row mb-3">
<div class="col-md-6"> <div class="col-md-6">
<div class="form-floating mb-3 mb-md-0"> <div class="form-floating mb-3 mb-md-0">
<input class="form-control" id="taille" name="taille" type="text" placeholder="Entrez votre taille" /> <input class="form-control" id="inputTaille" type="text" placeholder="Entrez votre taille" />
<label for="taille">Taille</label> <label for="inputPassword">Taille</label>
</div> </div>
</div> </div>
<div class="col-md-6"> <div class="col-md-6">
<div class="form-floating mb-3 mb-md-0"> <div class="form-floating mb-3 mb-md-0">
<input class="form-control" id="poids" name="poids" type="text" placeholder="Entrez votre poids" /> <label for="inputPoids"></label><input class="form-control" id="inputPoids" type="text" placeholder="Entrez votre poids" />
<label for="poids">Poids</label> <label for="inputPasswordConfirm">Poids</label>
</div> </div>
</div> </div>
</div> </div>
<div class="row mb-3"> <div class="row mb-3">
<div class="col-md-6"> <div class="col-md-6">
<div class="form-floating mb-3 mb-md-0"> <div class="form-floating mb-3 mb-md-0">
<input class="form-control" id="motDePasse" name="motDePasse" type="password" placeholder="Créez un mot de passe" /> <input class="form-control" id="inputPassword" type="password" placeholder="Créez un mot de passe" />
<label for="motDePasse">Mot de passe</label> <label for="inputPassword">Mot de passe</label>
</div> </div>
</div> </div>
<div class="col-md-6"> <div class="col-md-6">
<div class="form-floating mb-3 mb-md-0"> <div class="form-floating mb-3 mb-md-0">
<input class="form-control" id="confirmMdp" name="confirmMdp" type="password" placeholder="Confirmez votre mot de passe" /> <input class="form-control" id="inputPasswordConfirm" type="password" placeholder="Confirmez votre mot de passe" />
<label for="confirmMdp">Confirmer le mot de passe</label> <label for="inputPasswordConfirm">Confirmer le mot de passe</label>
</div> </div>
</div> </div>
</div> </div>
<div class="row mb-3">
<div class="col-md-6">
<label for="roleName" >Role:</label>
<div class="form-floating">
<select id="roleName" name="roleName">
<option value="Athlete">Athlete</option>
<option value="Coach">Coach</option>
</select>
</div>
</div>
</div>
<div class="mt-4 mb-0"> <div class="mt-4 mb-0">
<div class="d-grid"> <div class="d-grid"><a class="btn btn-primary btn-block" href="login.html.twig">Créer un compte</a></div>
<button type="submit" class="btn btn-primary btn-block">Créer un compte</button>
</div>
</div> </div>
</form> </form>
</div> </div>
<div class="card-footer text-center py-3"> <div class="card-footer text-center py-3">
<div class="small"><a href="/login">Avez-vous déjà un compte ? Connectez-vous ?</a></div> <div class="small"><a href="login.html.twig">Avez-vous déjà un compte ? Connectez-vous ?</a></div>
</div> </div>
</div> </div>
</div> </div>

@ -12,7 +12,7 @@
<div class="container-fluid px-4"> <div class="container-fluid px-4">
<h1 class="mt-4">Paramètres</h1> <h1 class="mt-4">Paramètres</h1>
<ol class="breadcrumb mb-4"> <ol class="breadcrumb mb-4">
<li class="breadcrumb-item"><a href="/home">Accueil</a></li> <li class="breadcrumb-item"><a href="/">Accueil</a></li>
<li class="breadcrumb-item active">Paramètres</li> <li class="breadcrumb-item active">Paramètres</li>
</ol> </ol>
<div class="row"> <div class="row">

@ -763,13 +763,7 @@ function profileMenu(Model $model)
do { do {
$effort = trim(fgets(STDIN)); $effort = trim(fgets(STDIN));
} while ($effort < 0 || $effort > 5); } while ($effort < 0 || $effort > 5);
try {
$isAddActivity = $model->activityMgr->uploadFile($typeActivity, $effort, $passFile); $isAddActivity = $model->activityMgr->uploadFile($typeActivity, $effort, $passFile);
}catch (\Throwable $exception){
echo $exception;
}
echo $isAddActivity ? "Activité ajoutée avec succès" : "Erreur lors de l'ajout de l'activité"; echo $isAddActivity ? "Activité ajoutée avec succès" : "Erreur lors de l'ajout de l'activité";
case '0': case '0':
return; return;
@ -799,7 +793,7 @@ while (true) {
}*/ }*/
break; break;
case '2': // S'inscrire case '2': // S'inscrire
if($model->userMgr->login("bruce.lee@example.com", "password123")) if($model->userMgr->login("bruce.lee@example.com", "hello321"))
$loggedIn = true; $loggedIn = true;
// if (registerUser($model)) { // if (registerUser($model)) {
// $loggedIn = true; // $loggedIn = true;

@ -1,44 +1,34 @@
<?php <?php
namespace Network; namespace Data\Core;
use App\Router\Session;
use Model\User; use Model\User;
use Model\Athlete; use Model\Athlete;
use Model\CoachAthlete; use Model\CoachAthlete;
use Repository\IUserRepository; use Repository\IUserRepository;
use Shared\IHashPassword; use Shared\IHashPassword;
use Shared\Log;
const USER = 'USER'; class AuthService implements IAuthService {
class AuthService implements IAuthService
{
private IUserRepository $userRepository; private IUserRepository $userRepository;
private IHashPassword $passwordHacher; private IHashPassword $passwordHacher;
private ?User $currentUser = null; private ?User $currentUser = null;
public function __construct(IUserRepository $userRepository, IHashPassword $passwordHacher) public function __construct(IUserRepository $userRepository, IHashPassword $passwordHacher) {
{
$this->userRepository = $userRepository; $this->userRepository = $userRepository;
$this->passwordHacher = $passwordHacher; $this->passwordHacher = $passwordHacher;
} }
public function login(string $email, string $password): bool public function login(string $email, string $password): bool {
{
$user = $this->userRepository->getItemByEmail($email); $user = $this->userRepository->getItemByEmail($email);
if ($user === null || !$this->passwordHacher->isPasswordValid( $user->getMotDePasse(),$password)) { if ($user === null || !$this->validatePassword($password, $user->getPasswordHash())) {
return false; return false;
} }
$this->currentUser = $user; $this->currentUser = $user;
$id = $this->currentUser->getId(); // Add session handling logic here
Session::getInstance()->__set(USER, $id);
Session::getInstance()->__get(USER);
return true; return true;
} }
public function register(string $email, string $password, array $data): bool {
public function register(string $email, string $password, $data): bool
{
if ($this->userRepository->getItemByEmail($email)) { if ($this->userRepository->getItemByEmail($email)) {
throw new \Exception('User already exists'); throw new \Exception('User already exists');
} }
@ -47,18 +37,20 @@ class AuthService implements IAuthService
$prenom = $data['prenom']; $prenom = $data['prenom'];
$username = $data['username']; $username = $data['username'];
$nom = $data['nom']; $nom = $data['nom'];
$email = $data['email'];
$sexe = $data['sexe']; $sexe = $data['sexe'];
$taille = $data['taille']; $taille = $data['taille'];
$poids = $data['poids']; $poids = $data['poids'];
$dateNaissance = $data['dateNaissance']; $dateNaissance = $data['dateNaissance'] ;
$roleName = $data['roleName']; $roleName = $data['roleName'];
$role = null; $role = null;
if ($roleName == "Coach") { if($roleName == "Coach"){
$role = new CoachAthlete(); $role = new CoachAthlete();
} else if ($roleName == "Athlete") { }
else if($roleName == "Athlete"){
$role = new Athlete(); $role = new Athlete();
} }
// Create a new user instance (you should expand on this with more data as needed)
$user = new User( $user = new User(
random_int(0, 100), random_int(0, 100),
$nom, $nom,
@ -75,26 +67,20 @@ class AuthService implements IAuthService
); );
$this->userRepository->addItem($user); $this->userRepository->addItem($user);
$this->currentUser = $user; $this->currentUser = $user;
Session::getInstance()->__set(USER,$this->currentUser->getId()); // Add session handling logic here
return true; return true;
} }
public function logoutUser(): bool public function logout(): void {
{
$this->currentUser = null; $this->currentUser = null;
Session::getInstance()->destroy(); // Add session handling logic here
return true;
} }
public function getCurrentUser(): ?User public function getCurrentUser(): ?User {
{
if (!empty(Session::getInstance()->__get(USER)) && $this->currentUser === null) {
$this->currentUser = $this->userRepository->getItemById(Session::getInstance()->__get(USER));
}
return $this->currentUser; return $this->currentUser;
} }
private function validatePassword(string $password, string $hash): bool {
// Implement password validation logic (e.g., using password_verify if using bcrypt)
}
} }

@ -2,19 +2,15 @@
namespace Data\Core; namespace Data\Core;
use Shared\Log;
class Preferences { class Preferences {
private string $cookie; private String $cookie;
private array $theme; private Array $theme;
public function __construct(){ public function __construct(){
if (isset($_COOKIE['preferences'])){ if (isset($_COOKIE['preferences'])){
$this->cookie = $_COOKIE['preferences']; $this->cookie = $_COOKIE['preferences'];
} else { } else {
if(setcookie('preferences', 'base_theme', time()+(3600*24)*7)){ $this->cookie = setcookie('preferences', 'base_theme', time()+(3600*24)*7);
$this->cookie = 'base_theme';
}
} }
$this->theme = array( $this->theme = array(
'base_theme', 'base_theme',
@ -23,7 +19,7 @@
); );
} }
public function majCookie(string $maj){ public function majCookie(String $maj){
try{ try{
foreach($this->theme as $t){ foreach($this->theme as $t){
$this->cookie = $maj; $this->cookie = $maj;
@ -34,8 +30,8 @@
} }
} }
public function getCookie():string{ public function getCookie():String{
return $this->cookie ?? "base_theme"; return $this->cookie;
} }
} }

@ -71,7 +71,7 @@ class ActiviteEntity {
} }
// Setters // Setters
public function setIdActivite($idActivity) { public function setIdActivite($idActivite) {
$this->idActivity = $idActivity; $this->idActivity = $idActivity;
} }

@ -1,129 +0,0 @@
<?php
namespace Database;
use DateTime;
class ActivityEntity {
private $idActivity;
private $type;
private DateTime $date;
private DateTime $heureDebut;
private DateTime $heureFin;
private $effortRessenti;
private $variabilite;
private $variance;
private $ecartType;
private $moyenne;
private $maximum;
private $minimum;
private $temperatureMoyenne;
// Getters
public function getIdActivity() {
return $this->idActivity;
}
public function getType() {
return $this->type;
}
public function getDate() {
return $this->date;
}
public function getHeureDebut() {
return $this->heureDebut;
}
public function getHeureFin() {
return $this->heureFin;
}
public function getEffortRessenti() {
return $this->effortRessenti;
}
public function getVariability() {
return $this->variabilite;
}
public function getVariance() {
return $this->variance;
}
public function getEcartType() {
return $this->ecartType;
}
public function getMoyenne() {
return $this->moyenne;
}
public function getMaximum() {
return $this->maximum;
}
public function getMinimum() {
return $this->minimum;
}
public function getTemperatureMoyenne() {
return $this->temperatureMoyenne;
}
// Setters
public function setIdActivity($idActivity) {
$this->idActivity = $idActivity;
}
public function setType($type) {
$this->type = $type;
}
public function setDate($date) {
$this->date = $date;
}
public function setHeureDebut($heureDebut) {
$this->heureDebut = $heureDebut;
}
public function setHeureFin($heureFin) {
$this->heureFin = $heureFin;
}
public function setEffortRessenti($effortRessenti) {
$this->effortRessenti = $effortRessenti;
}
public function setVariabilite($variabilite) {
$this->variabilite = $variabilite;
}
public function setVariance($variance) {
$this->variance = $variance;
}
public function setEcartType($ecartType) {
$this->ecartType = $ecartType;
}
public function setMoyenne($moyenne) {
$this->moyenne = $moyenne;
}
public function setMaximum($maximum) {
$this->maximum = $maximum;
}
public function setMinimum($minimum) {
$this->minimum = $minimum;
}
public function setTemperatureMoyenne($temperatureMoyenne) {
$this->temperatureMoyenne = $temperatureMoyenne;
}
}
?>

@ -1,124 +0,0 @@
<?php
namespace Database;
use \PDO;
use Shared\Log;
class ActivityGateway {
private Connexion $connection;
public function __construct(Connexion $connection) {
$this->connection = $connection;
}
public function getActivity() {
$query = "SELECT * FROM Activite";
return $this->connection->executeWithErrorHandling($query);
}
public function getActivityById(int $activityId) {
$query = "SELECT * FROM Activite WHERE idActivite = :id";
$params = [':id' => $activityId];
return $this->connection->executeWithErrorHandling($query, $params);
}
public function getActivityByType(string $type) {
$query = "SELECT * FROM Activite WHERE type = :type";
$params = [':type' => [$type, PDO::PARAM_STR]];
return $this->connection->executeWithErrorHandling($query, $params);
}
public function getActivityByDate(string $date) {
$query = "SELECT * FROM Activite WHERE date = :date";
$params = [':date' => [$date, PDO::PARAM_STR]];
return $this->connection->executeWithErrorHandling($query, $params);
}
public function getActivityByTimeRange(string $startTime, string $endTime) {
$query = "SELECT * FROM Activite WHERE heureDebut >= :startTime AND heureFin <= :endTime";
$params = [
':startTime' => [$startTime, PDO::PARAM_STR],
':endTime' => [$endTime, PDO::PARAM_STR]
];
return $this->connection->executeWithErrorHandling($query, $params);
}
public function getActivityByEffort(int $effortRessenti) {
$query = "SELECT * FROM Activite WHERE effortRessenti = :effort";
$params = [':effort' => [$effortRessenti, PDO::PARAM_INT]];
return $this->connection->executeWithErrorHandling($query, $params);
}
public function getActivityByVariability(int $variabilite) {
$query = "SELECT * FROM Activite WHERE variabilite = :variability";
$params = [':variability' => [$variabilite, PDO::PARAM_INT]];
return $this->connection->executeWithErrorHandling($query, $params);
}
public function getActivityByTemperature(int $temperatureMoyenne) {
$query = "SELECT * FROM Activite WHERE temperatureMoyenne = :temperature";
$params = [':temperature' => [$temperatureMoyenne, PDO::PARAM_INT]];
return $this->connection->executeWithErrorHandling($query, $params);
}
public function addActivity(ActivityEntity $activity) {
$query = "INSERT INTO Activite (idactivite, type, date, heurededebut, heuredefin, effortressent, variabilite, variance, ecarttype, moyenne, maximum, minimum, temperaturemoyenne, athleteid, sourceid)
VALUES (:idactivite, :type, :date, :heureDebut, :heureDeFin, :effortRessenti, :variabilite, :variance, :ecartType, :moyenne, :maximum, :minimum, :temperatureMoyenne, :athleteid, :sourceid)";
$params = [
':idactivite' => $activity->getIdActivity(),
':type' => $activity->getType(),
':date' => $activity->getDate()->format('Y-m-d'), // Format date pour SQL
':heureDebut' => $activity->getHeureDebut()->format('H:i:s'), // Format heure pour SQL
':heureDeFin' => $activity->getHeureFin()->format('H:i:s'), // Format heure pour SQL
':effortRessenti' => $activity->getEffortRessenti(),
':variabilite' => $activity->getVariability(),
':variance' => $activity->getVariance(),
':ecartType' => $activity->getEcartType(),
':moyenne' => $activity->getMoyenne(),
':maximum' => $activity->getMaximum(),
':minimum' => $activity->getMinimum(),
':temperatureMoyenne' => $activity->getTemperatureMoyenne(),
':athleteid' => 1,
':sourceid' => 1,
];
return $this->connection->executeWithErrorHandling($query, $params);
}
public function updateActivity(ActivityEntity $oldActivity, ActivityEntity $newActivity) {
$query = "UPDATE Activite
SET type = :type, date = :date, heureDebut = :heureDebut, heureDeFin = :heureDeFin,
effortRessenti = :effortRessenti, variabilite = :variabilite, variance = :variance, ecartType = :ecartType, moyenne = :moyenne, maximum = :maximum, minimum = :minimum, temperatureMoyenne = :temperatureMoyenne
WHERE idActivite = :idActivite";
$params = [
':idActivite' => $oldActivity->getIdActivity(),
':type' => $newActivity->getType(),
':date' => $newActivity->getDate()->format('Y-m-d'), // Format date pour SQL
':heureDebut' => $newActivity->getHeureDebut()->format('H:i:s'), // Format heure pour SQL
':heureDeFin' => $newActivity->getHeureFin()->format('H:i:s'), // Format heure pour SQL
':effortRessenti' => $newActivity->getEffortRessenti(),
':variabilite' => $newActivity->getVariabilite(),
':variance' => $newActivity->getVariance(),
':ecartType' => $newActivity->getEcartType(),
':moyenne' => $newActivity->getMoyenne(),
':maximum' => $newActivity->getMaximum(),
':minimum' => $newActivity->getMinimum(),
':temperatureMoyenne' => $newActivity->getTemperatureMoyenne(),
];
return $this->connection->executeWithErrorHandling($query, $params);
}
public function deleteActivity(int $idActivity) {
$query = "DELETE FROM Activite WHERE idActivite = :idActivity";
$params = [
':idActivity' => $idActivity,
];
return $this->connection->executeWithErrorHandling($query, $params);
}
}
?>

@ -1,126 +0,0 @@
<?php
namespace Database;
use DateTime;
use Model\Activity;
use Shared\Log;
class ActivityMapper {
public function activitySqlToEntity(array $data):array
{
$activityEntities = [];
foreach ($data as $activityData) {
$activity = new ActivityEntity();
if (isset($activityData['idActivite'])) {
$activity->setIdActivity($activityData['idActivite']);
}
if (isset($activityData['type'])) {
$activity->setType($activityData['type']);
}
if (isset($activityData['date'])) {
$activity->setDate(new DateTime($activityData['date']));
}
if (isset($activityData['heureDeDebut'])) {
$activity->setHeureDebut(new DateTime($activityData['heureDeDebut']));
}
if (isset($activityData['heureDeFin'])) {
$activity->setHeureFin(new DateTime($activityData['heureDeFin']));
}
if (isset($activityData['effortRessent'])) {
$activity->setEffortRessenti($activityData['effortRessent']);
}
if (isset($activityData['variabilite'])) {
$activity->setVariabilite($activityData['variabilite']);
}
if (isset($activityData['variance'])) {
$activity->setVariance($activityData['variance']);
}
if (isset($activityData['ecartType'])) {
$activity->setEcartType($activityData['ecartType']);
}
if (isset($activityData['moyenne'])) {
$activity->setMoyenne($activityData['moyenne']);
}
if (isset($activityData['maximum'])) {
$activity->setMaximum($activityData['maximum']);
}
if (isset($activityData['minimum'])) {
$activity->setMinimum($activityData['minimum']);
}
if (isset($activityData['temperatureMoyenne'])) {
$activity->setTemperatureMoyenne($activityData['temperatureMoyenne']);
}
$activityEntities[] = $activity;
}
return $activityEntities;
}
/**
* @throws \Exception
*/
public function ActivityEntityToModel(ActivityEntity $activiteEntity):Activity {
$date = new DateTime($activiteEntity->getDate()->format('Y-m-d'));
$heureDebut = new \DateTime($activiteEntity->getHeureDebut()->format('H:i:s'));
$heureFin = new \DateTime($activiteEntity->getHeureFin()->format('H:i:s'));
$effortRessenti = intval($activiteEntity->getEffortRessenti());
$variability = floatval($activiteEntity->getVariability());
$variance = floatval($activiteEntity->getVariance());
$ecartType = floatval($activiteEntity->getEcartType());
$act = new Activity(
$activiteEntity->getType(),
$date,
$heureDebut,
$heureFin,
$effortRessenti,
$variability,
$variance,
$ecartType,
$activiteEntity->getMoyenne(),
$activiteEntity->getMaximum(),
$activiteEntity->getMinimum(),
$activiteEntity->getTemperatureMoyenne(),
'false'
);
return $act;
}
//public function ActivityToEntity(Activity model): ActivityEntity;
public function activityToEntity(Activity $act):ActivityEntity{
$actEntity = new ActivityEntity();
$actEntity->setIdActivity($act->getIdActivity());
$actEntity->setType($act->getType());
$actEntity->setDate($act->getDate());
$actEntity->setHeureDebut($act->getHeureDebut());
$actEntity->setHeureFin($act->getHeureFin());
$actEntity->setEffortRessenti($act->getEffortRessenti());
$actEntity->setVariabilite($act->getVariability());
$actEntity->setVariance($act->getVariance());
$actEntity->setEcartType($act->getStandardDeviation());
$actEntity->setMoyenne($act->getAverage());
$actEntity->setMaximum($act->getMaximum());
$actEntity->setMinimum($act->getMinimum());
$actEntity->setTemperatureMoyenne($act->getAvrTemperature());
return $actEntity;
}
}
?>

@ -1,79 +0,0 @@
<?php
namespace Database;
class AnalyzeEntity
{
private $idFc;
private $altitude;
private $time;
private $temperature;
private $bpm;
private $longitude;
private $latitude;
private $idactivity;
public function getIdFC()
{
return $this->idFc;
}
public function getAltitude()
{
return $this->altitude;
}
public function getTime()
{
return $this->temps;
}
public function getTemperature()
{
return $this->temperature;
}
public function getBpm()
{
return $this->bpm;
}
public function getLongitude()
{
return $this->longitude;
}
public function getLatitude()
{
return $this->latitude;
}
public function getIdActivity()
{
return $this->idactivity;
}
public function setIdFC($idFc)
{
$this->idFc = $idFc;
}
public function setAltitude($altitude)
{
$this->altitude = $altitude;
}
public function setTime($time)
{
$this->time = $time;
}
public function setTemperature($temperature)
{
$this->temperature = $temperature;
}
public function setBpm($bpm)
{
$this->bpm = $bpm;
}
public function setLongitude($longitude)
{
$this->longitude = $longitude;
}
public function setLatitude($latitude)
{
$this->latitude = $latitude;
}
public function setIdActivity($idactivity)
{
$this->idactivity = $idactivity;
}
}

@ -1,24 +0,0 @@
<?php
namespace Database;
class AnalyzeGateway
{
private Connexion $connection;
public function __construct(Connexion $connection) {
$this->connection = $connection;
}
public function getFrequenceCardiaque() {
$query = "SELECT * FROM FrequenceCardiaque";
return $this->connection->executeWithErrorHandling($query);
}
public function getFrequenceCardiaqueByIdActivity(int $activityId)
{
$query = "SELECT * FROM FrequenceCardiaque WHERE activiteid = :id";
$params = [':id' => $activityId];
return $this->connection->executeWithErrorHandling($query, $params);
}
}

@ -1,125 +0,0 @@
<?php
namespace Database;
use Shared\Log;
class AnalyzeMapper
{
public function analyzeSqlToEntity(array $data):array
{
$analyzeEntities = [];
foreach ($data as $analyzeData) {
$analyze = new ActivityEntity();
if (isset($analyzeData['idactivite'])) {
$analyze->setIdActivity($analyzeData['idactivite']);
}
if (isset($analyzeData['type'])) {
$analyze->setType($analyzeData['type']);
}
if (isset($analyzeData['date'])) {
$analyze->setDate($analyzeData['date']);
}
if (isset($analyzeData['heurededebut'])) {
$analyze->setHeureDebut($analyzeData['heurededebut']);
}
if (isset($analyzeData['heuredefin'])) {
$analyze->setHeureFin($analyzeData['heuredefin']);
}
if (isset($analyzeData['effortressent'])) {
$analyze->setEffortRessenti($analyzeData['effortressent']);
}
if (isset($analyzeData['variabilite'])) {
$analyze->setVariabilite($analyzeData['variabilite']);
}
if (isset($analyzeData['variance'])) {
$analyze->setVariance($analyzeData['variance']);
}
if (isset($analyzeData['ecarttype'])) {
$analyze->setEcartType($analyzeData['ecarttype']);
}
if (isset($analyzeData['moyenne'])) {
$analyze->setMoyenne($analyzeData['moyenne']);
}
if (isset($analyzeData['maximum'])) {
$analyze->setMaximum($analyzeData['maximum']);
}
if (isset($analyzeData['minimum'])) {
$analyze->setMinimum($analyzeData['minimum']);
}
if (isset($analyzeData['temperaturemoyenne'])) {
$analyze->setTemperatureMoyenne($analyzeData['temperaturemoyenne']);
}
$analyzeEntities[] = $analyze;
}
return $analyzeEntities;
}
/**
* @throws \Exception
*/
// public function ActivityEntityToModel(ActivityEntity $activiteEntity):Activity {
// $date = new DateTime($activiteEntity->getDate());
// $heureDebut = new \DateTime($activiteEntity->getHeureDebut());
// $heureFin = new \DateTime($activiteEntity->getHeureFin());
// $effortRessenti = intval($activiteEntity->getEffortRessenti());
// $variability = floatval($activiteEntity->getVariability());
// $variance = floatval($activiteEntity->getVariance());
// $ecartType = floatval($activiteEntity->getEcartType());
//
// $act = new Activity(
// $activiteEntity->getIdActivity(),
// $activiteEntity->getType(),
// $date,
// $heureDebut,
// $heureFin,
// $effortRessenti,
// $variability,
// $variance,
// $ecartType,
// $activiteEntity->getMoyenne(),
// $activiteEntity->getMaximum(),
// $activiteEntity->getMinimum(),
// $activiteEntity->getTemperatureMoyenne(),
// 'false'
// );
//
// return $act;
// }
//public function ActivityToEntity(Activity model): ActivityEntity;
// public function activityToEntity( $act):ActivityEntity{
//
// $act = new ActivityEntity();
// $act->setIdActivity($act->getIdActivity()());
// $act->setType($act->getType());
// $act->setDate($act->getDate());
// $act->setHeureDebut($act->getHeureDebut());
// $act->setHeureFin($act->getHeureFin());
// $act->setEffortRessenti($act->getEffortRessenti());
// $act->setVariabilite($act->getVariability());
// $act->setVariance($act->getVariance());
// $act->setEcartType($act->getEcartType());
// $act->setMoyenne($act->getMoyenne());
// $act->setMaximum($act->getMaximum());
// $act->setMinimum($act->getMinimum());
// $act->setTemperatureMoyenne($act->getTemperatureMoyenne());
//
// return $act;
// }
}

@ -6,14 +6,12 @@ class AthleteEntity {
private $idAthlete; private $idAthlete;
private $nom; private $nom;
private $prenom; private $prenom;
private $username;
private $email; private $email;
private $sexe; private $sexe;
private $taille; private $taille;
private $poids; private $poids;
private $motDePasse; private $motDePasse;
private $dateNaissance; private $dateNaissance;
private $isCoach;
// Getters // Getters
public function getIdAthlete() { public function getIdAthlete() {
@ -28,10 +26,6 @@ class AthleteEntity {
return $this->prenom; return $this->prenom;
} }
public function getUsername(){
return $this->username;
}
public function getEmail() { public function getEmail() {
return $this->email; return $this->email;
} }
@ -56,10 +50,6 @@ class AthleteEntity {
return $this->dateNaissance; return $this->dateNaissance;
} }
public function getIsCoach(){
return $this->isCoach;
}
// Setters // Setters
public function setIdAthlete($idAthlete) { public function setIdAthlete($idAthlete) {
$this->idAthlete = $idAthlete; $this->idAthlete = $idAthlete;
@ -73,10 +63,6 @@ class AthleteEntity {
$this->prenom = $prenom; $this->prenom = $prenom;
} }
public function setUsername($username){
$this->username = $username;
}
public function setEmail($email) { public function setEmail($email) {
$this->email = $email; $this->email = $email;
} }
@ -100,8 +86,6 @@ class AthleteEntity {
public function setDateNaissance($dateNaissance) { public function setDateNaissance($dateNaissance) {
$this->dateNaissance = $dateNaissance; $this->dateNaissance = $dateNaissance;
} }
public function setIsCoach($isCoach){
$this->isCoach = $isCoach;
}
} }
?>

@ -1,133 +1,71 @@
<?php <?php
namespace Database; namespace Database;
use \PDO; use \PDO;
use Shared\Log;
class AthleteGateway { class AthleteGateway {
private Connexion $connection; private $connection;
public function __construct(Connexion $connection) { public function __construct(Connexion $connection) {
$this->connection = $connection; $this->connection = $connection;
} }
public function getAthlete(): array public function getAthlete() {
{ $query = "SELECT * FROM Athlete";
$query = "SELECT * FROM Athlete WHERE isCoach=FALSE"; return $this->connection->executeWithErrorHandling($query);
$res = $this->connection->executeWithErrorHandling($query);
return $res;
}
public function getAthleteById(int $userId): array
{
$query = "SELECT * FROM Athlete WHERE idAthlete = :id AND isCoach=FALSE";
$params = [':id' => $userId];
// log::dd($params);
$res = $this->connection->executeWithErrorHandling($query, $params);
return $res;
} }
public function getAthleteByName(string $name): array public function getAthleteById(int $userId) {
{ $query = "SELECT * FROM Athlete WHERE idAthlete = :id";
$query = "SELECT * FROM Athlete WHERE nom = :name AND isCoach=FALSE"; $params = [':id' => [$userId, PDO::PARAM_INT]];
$params = [':name' => $name];
return $this->connection->executeWithErrorHandling($query, $params); return $this->connection->executeWithErrorHandling($query, $params);
} }
public function getAthleteByFirstName(string $firstName): array public function getAthleteByName(string $name) {
{ $query = "SELECT * FROM Athlete WHERE nom = :name";
$query = "SELECT * FROM Athlete WHERE prenom = :firstName AND isCoach=FALSE"; $params = [':name' => [$name, PDO::PARAM_STR]];
$params = [':firstName' => $firstName];
return $this->connection->executeWithErrorHandling($query, $params); return $this->connection->executeWithErrorHandling($query, $params);
} }
public function getAthleteByEmail(string $email): array public function getAthleteByFirstName(string $firstName) {
{ $query = "SELECT * FROM Athlete WHERE prenom = :firstName";
$query = "SELECT * FROM Athlete WHERE email = :email AND isCoach=FALSE"; $params = [':firstName' => [$firstName, PDO::PARAM_STR]];
$params = [':email' => $email];
return $this->connection->executeWithErrorHandling($query, $params); return $this->connection->executeWithErrorHandling($query, $params);
} }
public function getUserByEmail(string $email): array
{ public function getAthleteByEmail(string $email) {
$query = "SELECT * FROM Athlete WHERE email = :email"; $query = "SELECT * FROM Athlete WHERE email = :email";
$params = [':email' => $email]; $params = [':email' => [$email, PDO::PARAM_STR]];
return $this->connection->executeWithErrorHandling($query, $params); return $this->connection->executeWithErrorHandling($query, $params);
} }
public function getAthleteByGender(string $gender): array public function getAthleteByGender(string $gender) {
{ $query = "SELECT * FROM Athlete WHERE sexe = :gender";
$query = "SELECT * FROM Athlete WHERE sexe = :gender AND isCoach=FALSE"; $params = [':gender' => [$gender, PDO::PARAM_STR]];
$params = [':gender' => $gender];
return $this->connection->executeWithErrorHandling($query, $params); return $this->connection->executeWithErrorHandling($query, $params);
} }
public function getAthleteByHeight(int $height): array public function getAthleteByHeight(int $height) {
{ $query = "SELECT * FROM Athlete WHERE taille = :height";
$query = "SELECT * FROM Athlete WHERE taille = :height AND isCoach=FALSE";
$params = [':height' => [$height, PDO::PARAM_INT]]; $params = [':height' => [$height, PDO::PARAM_INT]];
return $this->connection->executeWithErrorHandling($query, $params); return $this->connection->executeWithErrorHandling($query, $params);
} }
public function getAthleteByWeight(int $weight): array public function getAthleteByWeight(int $weight) {
{ $query = "SELECT * FROM Athlete WHERE poids = :weight";
$query = "SELECT * FROM Athlete WHERE poids = :weight AND isCoach=FALSE";
$params = [':weight' => [$weight, PDO::PARAM_INT]]; $params = [':weight' => [$weight, PDO::PARAM_INT]];
return $this->connection->executeWithErrorHandling($query, $params); return $this->connection->executeWithErrorHandling($query, $params);
} }
public function getAthleteByBirthDate(string $birthdate): array public function getAthleteByBirthDate(string $birthdate) {
{ $query = "SELECT * FROM Athlete WHERE dateNaissance = :birthdate";
$query = "SELECT * FROM Athlete WHERE dateNaissance = :birthdate AND isCoach=FALSE";
$params = [':birthdate' => [$birthdate, PDO::PARAM_STR]]; $params = [':birthdate' => [$birthdate, PDO::PARAM_STR]];
return $this->connection->executeWithErrorHandling($query, $params); return $this->connection->executeWithErrorHandling($query, $params);
} }
public function getListIdFriends(int $idAthlete): array public function addAthlete(AthleteEntity $athlete) {
{ $query = "INSERT INTO Athlete (nom, prenom, email, sexe, taille, poids, motDePasse, dateNaissance)
$query = "SELECT idAthlete1, idAthlete2 FROM Friendship WHERE idAthlete1 = :idAthlete OR idAthlete2= :idAthlete"; VALUES (:nom, :prenom, :email, :sexe, :taille, :poids, :motDePasse, :dateNaissance)";
$params = [
':idAthlete' => $idAthlete,
];
return $this->connection->executeWithErrorHandling($query, $params);
}
public function getListActivity(int $idAthlete): array
{
/*$query = "SELECT count(ac.idActivite) AS nbActivite, EXTRACT(MONTH FROM ac.date) AS mois
FROM Athlete at, Activite ac
WHERE at.idAthlete = :idAthlete
AND ac.date > CURRENT_DATE - INTERVAL '1 YEAR'
AND ac.athleteId = at.idAthlete
GROUP BY mois";*/
$query = "SELECT COUNT(ac.idActivite) AS nbActivite, EXTRACT(MONTH FROM ac.date) AS mois
FROM Athlete at
JOIN Activite ac ON ac.athleteId = at.idAthlete
WHERE at.idAthlete = :idAthlete
AND ac.date > CURRENT_DATE - INTERVAL 1 YEAR
GROUP BY mois";
// $query = "SELECT count(ac.idActivite) AS nbActivite, EXTRACT(MONTH FROM ac.date) AS mois
// FROM Athlete at, Activite ac
// WHERE at.idAthlete = :idAthlete
// AND ac.date > CURRENT_DATE - INTERVAL '1 YEAR'
// AND ac.athleteId = at.idAthlete
// GROUP BY mois";
$params = [
':idAthlete' => $idAthlete,
];
return $this->connection->executeWithErrorHandling($query, $params);
}
public function addAthlete(AthleteEntity $athlete): array
{
$query = "INSERT INTO Athlete (nom, prenom, email, sexe, taille, poids, motDePasse, dateNaissance, isCoach)
VALUES (:nom, :prenom, :email, :sexe, :taille, :poids, :motDePasse, :dateNaissance, :isCoach)";
$params = [ $params = [
':nom' => $athlete->getNom(), ':nom' => $athlete->getNom(),
@ -138,22 +76,19 @@ class AthleteGateway {
':poids' => $athlete->getPoids(), ':poids' => $athlete->getPoids(),
':motDePasse' => $athlete->getMotDePasse(), ':motDePasse' => $athlete->getMotDePasse(),
':dateNaissance' => $athlete->getDateNaissance(), ':dateNaissance' => $athlete->getDateNaissance(),
':isCoach' => $athlete->getIsCoach(),
]; ];
return $this->connection->executeWithErrorHandling($query, $params); return $this->connection->executeWithErrorHandling($query, $params);
} }
public function updateAthlete(AthleteEntity $oldAthlete, AthleteEntity $newAthlete): array public function updateAthlete(AthleteEntity $oldAthlete, AthleteEntity $newAthlete) {
{
$query = "UPDATE Athlete $query = "UPDATE Athlete
SET username = :username, nom = :nom, prenom = :prenom, email = :email, sexe = :sexe, SET nom = :nom, prenom = :prenom, email = :email, sexe = :sexe,
taille = :taille, poids = :poids, motDePasse = :motDePasse, dateNaissance = :dateNaissance, isCoach = :isCoach taille = :taille, poids = :poids, motDePasse = :motDePasse, dateNaissance = :dateNaissance
WHERE idAthlete = :idAthlete"; WHERE idAthlete = :idAthlete";
$params = [ $params = [
':idAthlete' => $oldAthlete->getIdAthlete(), ':idAthlete' => $oldAthlete->getIdAthlete(),
':username' => $newAthlete->getUsername(),
':nom' => $newAthlete->getNom(), ':nom' => $newAthlete->getNom(),
':prenom' => $newAthlete->getPrenom(), ':prenom' => $newAthlete->getPrenom(),
':email' => $newAthlete->getEmail(), ':email' => $newAthlete->getEmail(),
@ -162,14 +97,12 @@ class AthleteGateway {
':poids' => $newAthlete->getPoids(), ':poids' => $newAthlete->getPoids(),
':motDePasse' => $newAthlete->getMotDePasse(), ':motDePasse' => $newAthlete->getMotDePasse(),
':dateNaissance' => $newAthlete->getDateNaissance(), ':dateNaissance' => $newAthlete->getDateNaissance(),
':isCoach' => $newAthlete->getIsCoach(),
]; ];
return $this->connection->executeWithErrorHandling($query, $params); return $this->connection->executeWithErrorHandling($query, $params);
} }
public function deleteAthlete(int $idAthlete): array public function deleteAthlete(int $idAthlete) {
{
$query = "DELETE FROM Athlete WHERE idAthlete = :idAthlete"; $query = "DELETE FROM Athlete WHERE idAthlete = :idAthlete";
$params = [ $params = [

@ -6,14 +6,14 @@ use \PDO;
use \DateTime; use \DateTime;
use Model\Role; use Model\Role;
use Model\Athlete; use Model\Athlete;
use Shared\Log;
class AthleteMapper { class AthleteMapper {
public function athleteSqlToEntity(array $data): array { public function fromSqlToEntity(array $data): array {
$athleteEntities = []; $athleteEntities = [];
foreach ($data as $athleteData) { foreach ($data as $athleteData) {
$athlete = new AthleteEntity(); $athlete = new AthleteEntity();
if (isset($athleteData['idAthlete'])) { if (isset($athleteData['idAthlete'])) {
$athlete->setIdAthlete($athleteData['idAthlete']); $athlete->setIdAthlete($athleteData['idAthlete']);
} }
@ -26,10 +26,6 @@ class AthleteMapper {
$athlete->setPrenom($athleteData['prenom']); $athlete->setPrenom($athleteData['prenom']);
} }
if (isset($athleteData['username'])) {
$athlete->setUsername($athleteData['username']);
}
if (isset($athleteData['email'])) { if (isset($athleteData['email'])) {
$athlete->setEmail($athleteData['email']); $athlete->setEmail($athleteData['email']);
} }
@ -54,10 +50,6 @@ class AthleteMapper {
$athlete->setDateNaissance($athleteData['dateNaissance']); $athlete->setDateNaissance($athleteData['dateNaissance']);
} }
if (isset($athleteData['isCoach'])) {
$athlete->setIsCoach($athleteData['isCoach']);
}
$athleteEntities[] = $athlete; $athleteEntities[] = $athlete;
} }
@ -66,19 +58,19 @@ class AthleteMapper {
public function athleteEntityToModel(AthleteEntity $athleteEntity): User { public function athleteEntityToModel(AthleteEntity $athleteEntity): User {
$role = new Athlete(); // Utilisez la classe Athlete $role = new Athlete(); // Utilisez la classe Athlete
$date = new DateTime($athleteEntity->getDateNaissance());
$poids = floatval($athleteEntity->getPoids()); $dateSpecifique = $athleteEntity->getDateNaissance();
$taille = floatval($athleteEntity->getTaille()); $date = new DateTime($dateSpecifique);
$user = new User( $user = new User(
$athleteEntity->getIdAthlete(),
$athleteEntity->getNom(), $athleteEntity->getNom(),
$athleteEntity->getPrenom(), $athleteEntity->getPrenom(),
$athleteEntity->getUsername(),
$athleteEntity->getEmail(), $athleteEntity->getEmail(),
$athleteEntity->getMotDePasse(), $athleteEntity->getMotDePasse(),
$athleteEntity->getSexe(), $athleteEntity->getSexe(),
$taille, $athleteEntity->getTaille(),
$poids, $athleteEntity->getPoids(),
$date, $date,
$role $role
); );
@ -92,15 +84,12 @@ class AthleteMapper {
$ath->setIdAthlete($user->getId()); $ath->setIdAthlete($user->getId());
$ath->setNom($user->getNom()); $ath->setNom($user->getNom());
$ath->setPrenom($user->getPrenom()); $ath->setPrenom($user->getPrenom());
$ath->setUsername($user->getUsername());
$ath->setEmail($user->getEmail()); $ath->setEmail($user->getEmail());
$ath->setSexe($user->getSexe()); $ath->setSexe($user->getSexe());
$ath->setTaille($user->getTaille()); $ath->setTaille($user->getTaille());
$ath->setPoids($user->getPoids()); $ath->setPoids($user->getPoids());
$ath->setMotDePasse($user->getMotDePasse()); $ath->setMotDePasse($user->getMotDePasse());
$ath->setDateNaissance($user->getDateNaissance()); $ath->setDateNaissance($user->getDateNaissance());
$ath->setIsCoach(FALSE);
$ath->setCoachId(NULL);
return $ath; return $ath;
} }

@ -6,14 +6,12 @@ class CoachEntity {
private $idCoach; private $idCoach;
private $nom; private $nom;
private $prenom; private $prenom;
private $username;
private $email; private $email;
private $sexe; private $sexe;
private $taille; private $taille;
private $poids; private $poids;
private $motDePasse; private $motDePasse;
private $dateNaissance; private $dateNaissance;
private $isCoach;
// Getters // Getters
public function getIdCoach() { public function getIdCoach() {
@ -28,10 +26,6 @@ class CoachEntity {
return $this->prenom; return $this->prenom;
} }
public function getUsername(){
return $this->username;
}
public function getEmail() { public function getEmail() {
return $this->email; return $this->email;
} }
@ -56,11 +50,6 @@ class CoachEntity {
return $this->dateNaissance; return $this->dateNaissance;
} }
public function getIsCoach(){
return $this->isCoach;
}
// Setters // Setters
public function setIdCoach($idCoach) { public function setIdCoach($idCoach) {
$this->idCoach = $idCoach; $this->idCoach = $idCoach;
@ -74,10 +63,6 @@ class CoachEntity {
$this->prenom = $prenom; $this->prenom = $prenom;
} }
public function setUsername($username){
$this->username = $username;
}
public function setEmail($email) { public function setEmail($email) {
$this->email = $email; $this->email = $email;
} }
@ -101,11 +86,6 @@ class CoachEntity {
public function setDateNaissance($dateNaissance) { public function setDateNaissance($dateNaissance) {
$this->dateNaissance = $dateNaissance; $this->dateNaissance = $dateNaissance;
} }
public function setIsCoach($isCoach){
$this->isCoach = $isCoach;
}
} }
?> ?>

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save