Compare commits

..

5 Commits

BIN
.DS_Store vendored

Binary file not shown.

2
.gitignore vendored

@ -438,4 +438,4 @@ php/composer.lock
php/.idea/
##### Images :
php/public/uploads/
###php/public/uploads/

@ -1,48 +0,0 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "Listen for Xdebug",
"type": "php",
"request": "launch",
"port": 9003
},
{
"name": "Launch currently open script",
"type": "php",
"request": "launch",
"program": "${file}",
"cwd": "${fileDirname}",
"port": 0,
"runtimeArgs": [
"-dxdebug.start_with_request=yes"
],
"env": {
"XDEBUG_MODE": "debug,develop",
"XDEBUG_CONFIG": "client_port=${port}"
}
},
{
"name": "Launch Built-in web server",
"type": "php",
"request": "launch",
"runtimeArgs": [
"-dxdebug.mode=debug",
"-dxdebug.start_with_request=yes",
"-S",
"localhost:0"
],
"program": "",
"cwd": "${workspaceRoot}",
"port": 9003,
"serverReadyAction": {
"pattern": "Development Server \\(http://localhost:([0-9]+)\\) started",
"uriFormat": "http://localhost:%s",
"action": "openExternally"
}
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 100 KiB

BIN
php/.DS_Store vendored

Binary file not shown.

@ -12,8 +12,8 @@
}
.custom-button {
background-color: #00DBFF;
border-color: #00DBFF;
background-color: #7fb4bd;
border-color: #7fb4bd;
color: #fff;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 80 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 74 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 162 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 124 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 164 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 149 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

@ -96,50 +96,6 @@ class Validation
return false;
}
public static function validerExperience(int $idProfil, string $intitule, string $dateDeb, ?string $dateFin, string $nomEntreprise, ?bool $currendJob)
{
if(!empty($idProfil) && !empty($intitule) && !empty($dateDeb) && !empty($nomEntreprise))
{
self::nettoyerString($intitule, $dateDeb, $nomEntreprise);
if ($currendJob == false) {
if (!empty($dateFin)) {
self::nettoyerString($dateFin);
return true;
}
return false;
/*} else {
if (empty($dateFin)) {
return true;
}
return false;
*/}
return true;
}
return false;
}
public static function validerFormation(int $idProfil, string $nom, string $ville, string $dateDeb, ?string $dateFin, ?bool $currendFormation)
{
if(!empty($idProfil) && !empty($nom)&& !empty($ville) && !empty($dateDeb))
{
self::nettoyerString($nom, $dateDeb, $ville);
if ($currendFormation == false) {
if (!empty($dateFin)) {
self::nettoyerString($dateFin);
return true;
}
return false;
} else {
if (empty($dateFin)) {
return true;
}
return false;
}
return true;
}
return false;
}
public static function validateNumber($number) : bool
{
if(preg_match("/^[0-9]{10}$/", $number))
@ -198,4 +154,5 @@ class Validation
}
return null;
}
}

@ -5,7 +5,6 @@ namespace App\controleur;
use App\router\AltoRouter;
use App\controleur\Error;
use ErrorException;
class FrontControleur
{
@ -19,7 +18,7 @@ class FrontControleur
$_SESSION['nom'] = NULL;
$_SESSION['prenom'] = NULL;
$_SESSION['role'] = "guest";
$_SESSION['id'] = "ttttttttttttttttttttt";
$_SESSION['id'] = NULL;
}
else{
$twig->addGlobal('nom', $_SESSION['nom']);
@ -39,9 +38,10 @@ class FrontControleur
$router->map('POST','/[a:action]?','UtilisateurControleur');
$router->map('GET','/[a:action]/[i:id]?','UtilisateurControleur');
$router->map('GET|POST','/[a:action]/[i:id]?','UtilisateurControleur');
$router->map('GET|POST', '/user/[a:action]?', 'MembreControleur');
$router->map('GET|POST', '/user/[i:id]/[a:action]?', 'MembreControleur');
$router->map('GET|POST', '/user/[i:id]/[a:action]/[i:id2]?', 'MembreControleur');
@ -60,8 +60,6 @@ class FrontControleur
$id = array();
try{
$twig->render("accueil.html",[]);
if (!$match) {
$dVueErreur[] = "Error 404 Page not found";
@ -118,14 +116,14 @@ class FrontControleur
echo $twig->render('accueil.html');
}
} catch (ErrorException $error) {
} catch (Error $error) {
$dVueErreur = ['Erreur : Action inconnue'];
echo $twig->render('erreur.html', ['dVueErreur' => $dVueErreur]);
}
}
}
catch(ErrorException $e)
catch(Error $e)
{
$dVueErreur = ['Erreur : Action inconnue'];

@ -4,7 +4,6 @@ namespace App\controleur;
use App\config\Validation;
use App\gateway\ImageManager;
use App\modele\MembreModele;
use Exception;
class MembreControleur extends UtilisateurControleur
{
@ -13,13 +12,13 @@ class MembreControleur extends UtilisateurControleur
public function deconnexion()
{
global $twig;
session_unset();
session_destroy();
header("Location: /SAE_2A_FA-Reseau_ALICA/php/");
exit();
}
public function createOfferForm()
{
global $twig;
@ -79,7 +78,7 @@ class MembreControleur extends UtilisateurControleur
$offre = $mbrModel->publishOffer($saveImg1[1], $saveImg2[1]);
echo $twig->render("OffreDetailTest.html", ['offre' => $offre]);
echo $twig->render("OffreDetail.html", ['offre' => $offre]);
}
else
{
@ -102,166 +101,24 @@ class MembreControleur extends UtilisateurControleur
$MemberModel->deleteOffer($offre);
}
$this->consultOffers(null);
/*$offre = $MemberModel->getOfferFromId($id);
if($offre->getOffreur()->getId() == $_SESSION['id']
|| $_SESSION['role'] == "admin")
{
$MemberModel = new MembreModele();
$MemberModel->deleteOffer($offre);
$this->consultOffers();
}*/
$this->consultOffers(NULL);
}
public function proposerOffre()
{
//TODO
}
public function consulterProfil()
{
//TODO
}
public function modifierProfil()
{
//TODO
}
public function signaler()
{
//TODO
echo "not implement yet";
}
public function displayProfil()
{
global $twig;
$profilModel = new MembreModele();
$experienceModel = new MembreModele();
$formationModel = new MembreModele();
$profil = $profilModel->getProfilById($_SESSION["id"]);
//var_dump($profil);
$exp = $experienceModel->getExperienceByProfil($_SESSION["id"]);
//var_dump($exp);
$form = $formationModel->getFormationByProfil($_SESSION["id"]);
// var_dump($profil);
if(isset($profil))
{
echo $twig->render("monProfil.html",['profil' => $profil, 'experience' => $exp, 'formation'=>$form]);
return;
}
}
public function displayFormation()
{
global $twig;
$formationModel = new MembreModele();
$form = $formationModel->getFormationByProfil($_SESSION["id"]);
var_dump($form);
echo "Je rentre dans la formation";
if(isset($form))
{
echo $twig->render("detailFormation.html",['formation' => $form]);
return;
}
}
public function formationForm()
{
global $twig;
echo $twig->render("creerFormation.html", []);
}
public function addFormation()
{
global $twig;
try {
if (Validation::validerFormation($_SESSION["id"], $_POST["nom"], $_POST["ville"], $_POST["dateDeb"], $_POST["dateFin"], $_POST["currentFormation"])) {
$modele = new MembreModele();
$form = $modele->addExperience($_SESSION["id"], $_POST["nom"], $_POST["ville"], $_POST["dateDeb"], $_POST["dateFin"], $_POST["currentFormation"]);
var_dump($form);
$this->displayProfil($_SESSION["id"]);
echo $twig->render('creerFormation.html', ['formation' => $form]);
} else {
$dVueErreur[] ="Veillez entrer des valeurs correctes";
echo $twig->render("erreur.html",['dVueErreur' => $dVueErreur]);
}
} catch(Exception $e) {
$dVueErreur[] ="Erreur lors de la création de la formation";
echo $twig->render("erreur.html",['dVueErreur' => $dVueErreur]);
}
}
public function deleteFormation(?array $params)
{
global $twig;
try {
$mdl = new MembreModele();
$mdl->deleteFormation($params['id']);
$this->displayProfil($_SESSION["id"]);
} catch(Exception $e) {
$dVueErreur[] ="Erreur lors de la supression de la formation";
echo $twig->render("erreur.html",['dVueErreur' => $dVueErreur]);
}
}
public function displayExperience()
{
global $twig;
$experienceModel = new MembreModele();
$exp = $experienceModel->getExperienceByProfil($_SESSION["id"]);
var_dump($exp);
echo "Je rentres dans les expériences";
if(isset($exp))
{
echo $twig->render("detailExperience.html",['experience' => $exp]);
return;
}
}
public function experienceForm()
{
global $twig;
echo $twig->render("creerExperience.html", []);
}
public function addExperience()
{
global $twig;
try {
if (Validation::validerExperience($_SESSION["id"], $_POST["intitule"], $_POST["dateDeb"], $_POST["dateFin"], $_POST["nomEntreprise"], $_POST["currentJob"]?? null)) {
$modele = new MembreModele();
$exp = $modele->addExperience($_SESSION["id"], $_POST["intitule"], $_POST["dateDeb"], $_POST["dateFin"], $_POST["nomEntreprise"], $_POST["currentJob"]?? null);
// var_dump($exp);
$this->displayProfil($_SESSION["id"]);
echo $twig->render('creerExperience.html', ['experience' => $exp]);
} else {
$dVueErreur[] ="Veillez entrer des valeurs correctes";
echo $twig->render("erreur.html",['dVueErreur' => $dVueErreur]);
}
} catch (Exception $e){
$dVueErreur[] ="Erreur lors de la création de l'expérience";
echo $twig->render("erreur.html",['dVueErreur' => $dVueErreur]);
}
}
public function deleteExperience(?array $params)
{
global $twig;
try {
$mdl = new MembreModele();
$mdl->deleteExperience($params['id']);
$this->displayProfil($_SESSION["id"]);
} catch(Exception $e) {
$dVueErreur[] ="Erreur lors de la supression de l'expérience ";
echo $twig->render("erreur.html",['dVueErreur' => $dVueErreur]);
}
}
}
}

@ -84,7 +84,7 @@ class UtilisateurControleur
echo $twig->render('inscription.html', ['dVueErreur' => $dVueErreur]);
}
protected function accueil()
public function accueil()
{
global $twig;
// Ajout d'un var_dump pour déboguer
@ -104,6 +104,23 @@ class UtilisateurControleur
echo 'not implemented yet';
}
/**
* @return void
* @description afficher la liste des offres
*/
public function resetFilters()
{
unset($_SESSION["niveauEtudes"]);
unset($_SESSION["typeContrat"]);
unset($_SESSION["experience"]);
$this->consultOffers(null);
}
/**
* @param array|null $params paramètres / filtres de la rehcerhce
* @return void
* @description afficher la liste des offres
*/
public function consultOffers(?array $params)
{
$userMdl = new UtilisateurModele();
@ -117,16 +134,29 @@ class UtilisateurControleur
$nbOffers = 5 ;
if(isset($_POST["niveauEtudes"]) && Validation::validateTypeStudies($_POST["niveauEtudes"])) {
$niveauEtudes = $_POST["niveauEtudes"];
//$niveauEtudes = $_POST["niveauEtudes"];
$_SESSION["niveauEtudes"] = $_POST["niveauEtudes"];
$niveauEtudes = $_SESSION["niveauEtudes"];
}
else if(isset($_SESSION["niveauEtudes"]))
{$niveauEtudes = $_SESSION["niveauEtudes"];}
if(isset($_POST["typeContrat"]) && Validation::validateTypeContract($_POST["typeContrat"])) {
$typeContrat = $_POST["typeContrat"];
//$typeContrat = $_POST["typeContrat"];
$_SESSION["typeContrat"] = $_POST["typeContrat"];
$typeContrat = $_SESSION["typeContrat"];
}
else if(isset($_SESSION["typeContrat"]))
{$typeContrat = $_SESSION["typeContrat"];}
if(isset($_POST["experience"]) && Validation::validateExperience($_POST["experience"])) {
$exp = $_POST["experience"];
//$exp = $_POST["experience"];
$_SESSION["experience"] = $_POST["experience"];
$exp = $_SESSION["experience"];
}
else if(isset($_SESSION["experience"]))
{$exp = $_SESSION["experience"];}
if ($niveauEtudes == null && $typeContrat == null && $exp == null) {
$totalOffers = $userMdl->getNbOffers();
@ -144,8 +174,14 @@ class UtilisateurControleur
$numberPages = ceil($totalOffers / 5);
if (isset($_GET["page"]) && intval($_GET["page"]) != null) {
$page = intval($_GET["page"]);
//var_dump($params);
//echo "page : ".$params["id"];
/*if (isset($params["id"]) && intval($params["id"]) != null)*/
if(isset($_GET['id']) && intval($_GET['id']) != null)
{
$page = intval($_GET['id']);
//echo "page : ".$page;
if ($page > $numberPages || $page < 1) {
$dVueErreur[] = "Page introuvable";
echo $twig->render("erreur.html", ['dVueErreur' => $dVueErreur ]);
@ -182,17 +218,22 @@ class UtilisateurControleur
]);
}
/**
* @param array|null $params paramètres
* @return void
* @description afficher le détail d'une offre
*/
public function displayOffer(?array $params)
{
global $twig;
if (isset($params['id']) && ($params['id']) != null)
if (isset($params['id']) && intval($params['id']) != null)
{
$uttilsMdl = new UtilisateurModele();
$offre = $uttilsMdl->getOfferFromId(intval($params["id"]));
if($offre != NULL)
{
echo $twig->render("OffreDetailTest.html",['offre' => $offre]);
echo $twig->render("OffreDetail.html",['offre' => $offre]);
return;
}
}
@ -268,6 +309,4 @@ class UtilisateurControleur
echo $twig->render('erreur.html', ['dVueErreur' => $dVueErreur]);
}
}
}

@ -1,78 +0,0 @@
<?php
namespace App\gateway;
use App\metier\Profil;
use App\metier\Experience;
class ExperienceGateway
{
private \App\gateway\Connection $con;
/**
* @param $con
*/
public function __construct(\App\gateway\Connection $con){
$this->con = $con;
}
public function getNewId() : int
{
$query='SELECT MAX(id) FROM Experience';
$this->con->executeQuery($query);
$res=$this->con->getResults();
return $res[0]['MAX(id)']+1;
}
public function getNbExperience(): int
{
$query = 'SELECT COUNT(*) FROM Experience';
$this->con->executeQuery($query, array());
$res = $this->con->getResults();
return intval($res[0]['COUNT(*)']);
}
public function getExperienceFromId(int $id) : array
{
$query = "SELECT * FROM experience WHERE id=:id";
$this->con->executeQuery($query, array(
':id' => array($id, \PDO::PARAM_INT)
));
return $this->con->getResults();
}
public function getExperienceFromProfil(int $profil) : array
{
$query = "SELECT * FROM experience WHERE profil=:profil" ;
$this->con->executeQuery($query, array(
':profil' => array($profil, \PDO::PARAM_INT)
));
// var_dump($profil);
// var_dump($this->con->getResults());
return $this->con->getResults();
}
public function addExperience(Experience $exp)
{
$query = 'INSERT INTO experience VALUES (:id, :profil, :intitule, :dateBegin, :dateEnd, :nameIndustry, :currentJobb)';
$this->con->executeQuery($query, array(
':id' => array($exp->getId(), \PDO::PARAM_INT),
//':profil' => array($exp->getProfil(), \PDO::PARAM_INT),
':profil' => array(33,\PDO::PARAM_INT),
':intitule' => array($exp->getIntitule(), \PDO::PARAM_STR),
':dateBegin' => array($exp->getDateDebut(), \PDO::PARAM_STR),
':dateEnd' => array($exp->getDateFin(), \PDO::PARAM_STR),
':nameIndustry' => array($exp->getNomEntreprise(), \PDO::PARAM_STR),
':currentJobb' => array($exp->isTravailActuel(), \PDO::PARAM_BOOL),
));
}
public function deleteExperience(int $id)
{
$query = 'DELETE FROM experience WHERE id=:id';
$this->con->executeQuery($query, array(
':id' => array($id, \PDO::PARAM_INT)
));
}
}

@ -1,78 +0,0 @@
<?php
namespace App\gateway;
use App\metier\Profil;
use App\metier\Formation;
class FormationGateway
{
private \App\gateway\Connection $con;
/**
* @param $con
*/
public function __construct(\App\gateway\Connection $con){
$this->con = $con;
}
public function getNewId() : int
{
$query='SELECT MAX(id) FROM Formation';
$this->con->executeQuery($query);
$res=$this->con->getResults();
return $res[0]['MAX(id)']+1;
}
public function getNbFormation(): int
{
$query = 'SELECT COUNT(*) FROM Formation';
$this->con->executeQuery($query, array());
$res = $this->con->getResults();
return intval($res[0]['COUNT(*)']);
}
public function getFormationFromId(int $id) : array
{
$query = "SELECT * FROM Formation WHERE id=:id";
$this->con->executeQuery($query, array(
':id' => array($id, \PDO::PARAM_INT)
));
return $this->con->getResults();
}
public function getFormationFromProfil(int $profil) : array
{
$query = "SELECT * FROM Formation WHERE profil=:profil" ;
$this->con->executeQuery($query, array(
':profil' => array($profil, \PDO::PARAM_INT)
));
// var_dump($profil);
// var_dump($this->con->getResults());
return $this->con->getResults();
}
public function addFormation(Formation $form)
{
$query = 'INSERT INTO Formation VALUES (:id, :profil, :nom, :ville,:dateDeb, :dateFin, :currentFormation)';
$this->con->executeQuery($query, array(
':id' => array($form->getId(), \PDO::PARAM_INT),
//':profil' => array($exp->getProfil(), \PDO::PARAM_INT),
':profil' => array(33,\PDO::PARAM_INT),
':nom' => array($form->getNom(), \PDO::PARAM_STR),
':ville' => array($form->getville(), \PDO::PARAM_STR),
':dateBegin' => array($form->getDateDebut(), \PDO::PARAM_STR),
':dateEnd' => array($form->getDateFin(), \PDO::PARAM_STR),
':currentFormation' => array($form->isFormationActuelle(), \PDO::PARAM_BOOL),
));
}
public function deleteFormation(int $id)
{
$query = 'DELETE FROM Formation WHERE id=:id';
$this->con->executeQuery($query, array(
':id' => array($id, \PDO::PARAM_INT)
));
}
}

@ -4,18 +4,34 @@ namespace App\gateway;
class ImageManager
{
/**
* @return int id aléatoire
* @description générer un id aléatoire
*/
public static function getId() : int
{
return rand(10000,19999);
}
/**
* @description sauvegarder une image
* @param string $filename
* @return array [bool,string] tableau de retour avec le booléen et le nom de l'image
*/
public static function SaveImage(string $filename) : array
{
try {
$return=[];
$name = substr($_FILES[$filename]["name"], 0, 45);
$name = self::getId().$name;
$name = $_FILES[$filename]["name"];
$path = "public/uploads/".$name;
while(file_exists($path))
{
$name = substr($_FILES[$filename]["name"], 0, 45);
$name = self::getId().$name;
$path = "public/uploads/".$name;
}
move_uploaded_file($_FILES[$filename]['tmp_name'], "public/uploads/$name");
$return[]=true;
@ -28,6 +44,11 @@ class ImageManager
}
}
/**
* @param string $img
* @return bool true si l'image a été supprimée, false sinon
* @description supprimer une image
*/
public static function deleteImg(string $img) : bool
{
$path = "public/uploads/$img";

@ -11,7 +11,7 @@ class Experience
/**
* @var Profil profil
*/
private int $profil;
private Profil $profil;
/**
* @var string Intitule
@ -34,20 +34,20 @@ class Experience
private string $nomEntreprise;
/**
* @var ?bool Travail Actuel
* @var bool Travail Actuel
*/
private ?bool $travailActuel;
private bool $travailActuel;
/**
* @param int $id
* @param int $profil
* @param Profil $profil
* @param string $intitule
* @param string $dateDebut
* @param string $dateFin
* @param string $nomEntreprise
* @param bool $travailActuel
*/
public function __construct(int $id, int $profil, string $intitule, string $dateDebut, string $dateFin, string $nomEntreprise, ?bool $travailActuel)
public function __construct(int $id, Profil $profil, string $intitule, string $dateDebut, string $dateFin, string $nomEntreprise, bool $travailActuel)
{
$this->id = $id;
$this->profil = $profil;
@ -63,14 +63,9 @@ class Experience
return $this->id;
}
/*public function getProfil(): Profil
public function getProfil(): Profil
{
return $this->profil;
}*/
public function getProfilId(): int
{
return $this->profil->getId();
}
public function getIntitule(): string
@ -93,8 +88,8 @@ class Experience
return $this->nomEntreprise;
}
public function isTravailActuel(): ?bool
public function isTravailActuel(): bool
{
return $this->travailActuel ?? null;
return $this->travailActuel;
}
}

@ -11,7 +11,7 @@ class Formation
/**
* @var Profil profil
*/
private int $profil;
private Profil $profil;
/**
* @var string Nom
@ -36,18 +36,18 @@ class Formation
/**
* @var bool Formation Actuelle
*/
private ?bool $formationActuelle;
private bool $formationActuelle;
/**
* @param int $id
* @param int $profil
* @param Profil $profil
* @param string $nom
* @param string $ville
* @param string $dateDebut
* @param string $dateFin
* @param bool $formationActuelle
*/
public function __construct(int $id, int $profil, string $nom, string $ville, string $dateDebut, string $dateFin, bool $formationActuelle)
public function __construct(int $id, Profil $profil, string $nom, string $ville, string $dateDebut, string $dateFin, bool $formationActuelle)
{
$this->id = $id;
$this->profil = $profil;
@ -63,17 +63,10 @@ class Formation
return $this->id;
}
/*
public function getProfil(): Profil
{
return $this->profil;
}
*/
public function getProfilId(): int
{
return $this->profil->getId();
}
public function getNom(): string
{
@ -95,8 +88,8 @@ class Formation
return $this->dateFin;
}
public function isFormationActuelle(): ?bool
public function isFormationActuelle(): bool
{
return $this->formationActuelle ?? null;
return $this->formationActuelle;
}
}

@ -1,8 +1,6 @@
<?php
namespace App\metier;
use App\metier\Alumni;
class Profil
{
/**
@ -10,16 +8,18 @@ class Profil
*/
private int $id;
/**
* @var string CV
*/
private ?string $cv;
private string $cv;
/**
* @var string Nom
*/
private string $nom;
/**
* @var string Prenom
*/
@ -31,27 +31,17 @@ class Profil
*/
//image can be null
private ?string $image;
private ?string $linkedinUrl;
private string $linkedinUrl;
/**
* @var string Url github
*/
private ?string $githubUrl;
private string $githubUrl;
/**
* @var string Url du portfolio
*/
private ?string $portfolioUrl;
/**
*@var array liste des formation d'un profil
*/
// private array $listeFormation;
/**
* @var array liste des expériences d'un profil
*/
// private array $listeExperience;
private string $portfolioUrl;
/**
* @param string $cv
@ -61,9 +51,9 @@ class Profil
* @param string $githubUrl
* @param string $portfolioUrl
*/
public function __construct(int $idProfil,string $nom, string $prenom, string $email, ?string $image, ?string $cv, ?string $linkedinUrl, ?string $githubUrl, ?string $portfolioUrl)
public function __construct(int $alumni,string $nom, string $prenom, string $email, ?string $image,string $cv, string $linkedinUrl, string $githubUrl, string $portfolioUrl)
{
$this->id = $idProfil;
$this->id = $alumni;
$this->nom = $nom;
$this->prenom = $prenom;
$this->image = $image;
@ -72,8 +62,6 @@ class Profil
$this->linkedinUrl = $linkedinUrl;
$this->githubUrl = $githubUrl;
$this->portfolioUrl = $portfolioUrl;
// $this->listeFormation = null;
// $this->listeExperience = null;
}
@ -81,20 +69,13 @@ class Profil
{
return $this->id;
}
/*public function getAlmuni(): Alumni
{
return $this->alumni;
}*/
public function getImage(): ?string
{
return $this->image ?? 'logo.png';
}
public function getCv(): ?string
public function getCv(): string
{
return $this->cv ?? null;
return $this->cv;
}
public function getNom(): string
@ -107,22 +88,22 @@ class Profil
return $this->prenom;
}
public function getLinkedinUrl(): ?string
public function getLinkedinUrl(): string
{
return $this->linkedinUrl ?? null;
return $this->linkedinUrl;
}
public function getGithubUrl(): ?string
public function getGithubUrl(): string
{
return $this->githubUrl ?? null;
return $this->githubUrl;
}
public function getEmail(): string
{
return $this->email;
}
public function getPortfolioUrl(): ?string
public function getPortfolioUrl(): string
{
return $this->portfolioUrl ?? null;
return $this->portfolioUrl;
}
}

@ -5,29 +5,10 @@ namespace App\modele;
use App\gateway\ImageManager;
use App\metier\Alumni;
use App\metier\Offre;
use App\metier\Experience;
use App\metier\Formation;
use App\metier\Profil;
use App\gateway\Connection;
use App\gateway\ExperienceGateway;
use App\gateway\FormationGateway;
use App\gateway\ProfilGateway;
class MembreModele extends UtilisateurModele
{
private $con;
protected $experienceGw;
protected $formationGw;
protected $profilGw;
public function __construct()
{
$this->con = new Connection(DB_HOST,DB_USER,DB_PASS);
$this->experienceGw = new ExperienceGateway($this->con);
$this->formationGw = new FormationGateway($this->con);
$this->profilGw = new ProfilGateway($this->con);
}
/**
* @description modifier photo de profil
@ -38,170 +19,38 @@ class MembreModele extends UtilisateurModele
return false;
}
/**
* @description modifier formation
*
* @description ajouter formation
*/
public function updateFormation() : bool
public function addFormation() : bool
{
// TO DO
return false;
}
public function getProfilById($idProfil) : ?array
{
$data = $this->profilGw->getProfilById($idProfil);
$profil = array();
foreach($data as $row)
{
$profil[] = new Profil(
$row['id'],
$row['nom'],
$row['prenom'],
$row['email'],
$row['image'] ?? null,
$row['cv'] ?? null,
$row['linkedinURL'] ?? null,
$row['githubURL'] ?? null,
$row['portfolioURL'] ?? null
);
}
return $profil;
}
/**
* @description Récupérer l'expériences en fonction de l'id
*/
public function getExperienceById($idProfil) : ?array
{
$data = $this->experienceGw->getExperienceFromId($idProfil);
$experience = array();
foreach($data as $row)
{
$experience[] = new Experience(
$row['id'],
$row['profil'],
$row['intitule'],
$row['dateBegin'],
$row['dateEnd'],
$row['industryName'],
$row['currentJob']
);
}
return $experience;
}
/**
* @description Récupérer les expériences de l'utilisateurs en cours
* @description modifier formation
*/
public function getExperienceByProfil($idProfil) : ?array
public function updateFormation() : bool
{
$data = $this->experienceGw->getExperienceFromProfil($idProfil);
$experience = array();
// var_dump($data);
foreach($data as $row)
{
$experience[] = new Experience(
$row['id'],
$row['profil'],
$row['intitule'],
$row['dateDebut'],
$row['dateFin'],
$row['nomEntreprise'],
$row['currentJob']
);
}
// var_dump($experience);
return $experience;
// TO DO
return false;
}
/**
* @description ajouter Experience
*/
public function addExperience($idExperience, string $intitule, string $dateDeb, string $dateFin, string $nomEntreprise, ?string $currentJob)
public function addExperience() : bool
{
$exp = new Experience(
$this->experienceGw->getNewId(),
$idExperience,
$intitule,
$dateDeb,
$dateFin,
$nomEntreprise,
$currentJob
);
var_dump($exp);
$this->experienceGw->addExperience($exp);
}
/**
* @description supprimer une expérience
*/
public function deleteExperience($id)
{
$this->experienceGw->deleteExperience($id);
}
/**
* @description Récupérer les formations de l'utilisateurs en cours
*/
public function getFormationByProfil($idProfil) : ?array
{
$data = $this->formationGw->getFormationFromProfil($idProfil);
$formation = array();
// var_dump($data);
foreach($data as $row)
{
$formation[] = new Formation(
$row['id'],
$row['profil'],
$row['nom'],
$row['ville'],
$row['dateDeb'],
$row['dateFin'],
$row['currentFormation']
);
}
// var_dump($formation);
return $formation;
}
/**
* @description ajouter une formation
*/
public function addFormation($idExperience, string $nom, string $ville, string $dateDeb, string $dateFin, ?string $currentFormation)
{
$form = new Formation(
$this->experienceGw->getNewId(),
$idExperience,
$nom,
$ville,
$dateDeb,
$dateFin,
$currentFormation
);
$this->formationGw->addFormation($form);
}
/**
* @description supprimer une formation
*/
public function deleteFormation($id)
{
$this->formationGw->deleteFormation($id);
// TO DO
return false;
}
/**
* @description modifier experience
*/
public function updateExperience() : bool
public function updateExpereience() : bool
{
// TO DO
return false;
@ -218,8 +67,11 @@ class MembreModele extends UtilisateurModele
return false;
}
/**
* @param string $img url de l'image
* @param string $logo url du logo
* @description publier une offre
*/
public function publishOffer(string $img, string $logo)
{
$desc = $_POST["description"];
@ -267,6 +119,11 @@ class MembreModele extends UtilisateurModele
return $offre;
}
/**
* @param Offre $offre offre à supprimer
* @description supprimer une offre
* @return void
*/
public function deleteOffer(Offre $offre)
{
$this->offreGw->deleteOffer($offre->getId());

@ -192,6 +192,11 @@ class UtilisateurModele
}
/**
* @param int $id identifiant d'offre
* @return Offre|null offre trouvée
* @description récupérer une offre depuis son id
*/
public function getOfferFromId(int $id) : ?Offre
{
$res = $this->offreGw->getOfferFromId($id);
@ -203,6 +208,11 @@ class UtilisateurModele
/**
* @description créer une offre depuis un tableau de retour de Gw
* @param array $res tableau de retour de Gw
* @return array tableau d'offres
*/
public function CreateOffersFromGw($res) : array
{
$alGw = new AlumniGateway(new Connection(DB_HOST,DB_USER,DB_PASS));
@ -244,22 +254,37 @@ class UtilisateurModele
return $offers;
}
/**
* @param $start int de départ pour la reqûete sql
* @param $nbOffers nombre d'offres à récupérer
* @return array tableau d'offres
*/
public function getOfferLimit($start, $nbOffers): array
{
$res = $this->offreGw->getOfferLimit($start, $nbOffers);
return $this->CreateOffersFromGw($res);
}
/**
* @return int nombre d'offres
*/
public function getNbOffers() : int
{
return $this->offreGw->getNbOffers();
}
/**
* @param $params array filtres de la recherche
* @return array tableau d'offres
*/
public function getOffersWithFilters($params) : array
{
return $this->CreateOffersFromGw($this->offreGw->getOffersWithFilters($params));
}
/**
* @return array tableau de toutes les offres
*/
public function getOffers() : array
{
$res = $this->offreGw->getOffers();

@ -16,6 +16,9 @@
<div>
{% if role == 'Membre' or role == 'Admin' %}
<a href="{{dir}}/user/{{id}}/createOfferForm" type="button" class="btn btn-outline-success mb-4">Publier une offre</a>
{% else %}
<a type="button" class="btn btn-outline-light mb-4">Publier une offre</a>
<p><i>Connectez vous pour publier une offre</i></p>
{% endif %}
</div>
@ -79,7 +82,7 @@
</div>
<div>
<a href="{{dir}}/consultOffers" class="btn btn-info">Réinitialiser les filtres</a>
<a href="{{dir}}/resetFilters" class="btn btn-info">Réinitialiser les filtres</a>
</div>
</div>
@ -107,7 +110,7 @@
</div>
<div class="row3">
<img src="public/assets/location.png" alt="location">
<img src="{{dir}}/public/assets/location.png" alt="location">
<p>{{offre.getVille()}}</p>
</div>
<div class="d-flex justify-content-around">
@ -123,32 +126,28 @@
{% else %}
<li class="list-group-item">Aucune offre trouvée.</li>
{% endif %}
<nav style="text-align: center;">
<nav style="text-align: center;">
{% if numberPages is defined %}
{% if numberPages > 1 %}
{% if currentPage is defined %}
{% for i in 1..numberPages %}
{% if i == currentPage %}
<!--
index.php?action=consultOffers&page={{ i }}&typeContrat={{ typeContrat }}&experience={{ experience }}&niveauEtudes={{ niveauEtudes }}
-->
<a href="{{dir}}/consultOffers?page={{i}}{{valContrat}}{{valExp}}{{ValEtudes}}" class="current">{{ i }}</a>
{% else %}
<a href="{{dir}}/consultOffers?page={{i}}{{valContrat}}{{valExp}}{{ValEtudes}}">{{ i }}</a>
{% endif %}
{% endfor %}
{% endif %}
{% endif %}
{% endif %}
</nav>
<nav class="pagination justify-content-center">
{% if numberPages is defined %}
{% if numberPages > 1 %}
{% if currentPage is defined %}
{% for i in 1..numberPages %}
{% if i == currentPage %}
<a href="{{ dir }}/consultOffers?id={{ i }}" class="page-item page-link current">{{ i }}</a>
{% else %}
<a href="{{ dir }}/consultOffers?id={{ i }}" class="page-item page-link">{{ i }}</a>
{% endif %}
{% endfor %}
{% endif %}
{% endif %}
{% endif %}
</nav>
</div>
<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.11.6/dist/umd/popper.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script>

@ -14,6 +14,7 @@
<div class="container mt-5">
<h1 class="display-4">Détails de l'Offre</h1>
<a href="{{dir}}/ConsultOffers" class="btn btn-primary mb-4">Retour</a>
<ul class="list-group">
@ -23,7 +24,6 @@
{% endif %}
<img src="{{dir}}/public/uploads/{{offre.getLogo()}}" alt="Logo" class="img-thumbnail" style="max-height: 50px; max-width: 50px;"></li>
<li class="list-group-item"><img src="{{dir}}/public/uploads/{{offre.getImg()}}" alt="Offer Image" class="img-fluid"></li>
<!--<li class="list-group-item"><strong>ID:</strong> {{ offre.getId() }}</li> -->
<li class="list-group-item"><strong>Offreur:</strong> {{offre.getOffreur().Prenom()}} {{offre.getOffreur().getNom() }}</li>
<li class="list-group-item"><strong>Nom de l'offre:</strong> {{ offre.getNom() }}</li>
<li class="list-group-item"><strong>Entreprise :</strong> {{ offre.getEntreprise() }}</li>
@ -35,7 +35,7 @@
<li class="list-group-item"><strong>Date de publication:</strong> {{ offre.getDateStringFr() }}</li>
<li class="list-group-item"><strong>Descriptif Poste :</strong> {{ offre.getDescriptifPoste() }}</li>
<li class="list-group-item"><strong>Profil recherché :</strong> {{ offre.getProfilSearched() }}</li>
<li class="list-group-item"><strong>Site de L'annonce :</strong> {{ offre.getSiteUrl() }}</li>
<li class="list-group-item"><strong>Site de L'annonce :</strong><a href="{{offre.getSiteUrl()}}" target="_blank">{{ offre.getSiteUrl() }}</a></li>
<li class="list-group-item"><strong>Mail de Contact : :</strong> {{ offre.getMailContact() }}</li>
<li class="list-group-item"><strong>Numéro de Contact :</strong> {{ offre.getNumero() }}</li>
<li class="list-group-item">

@ -1,52 +0,0 @@
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Ajouter une expérience</title>
<link rel="stylesheet" href="">
</head>
<body>
<div>
<h1>Ajouter une expérience</h1>
<form action="{{dir}}/user/addExperience" method="POST" enctype="multipart/form-data">
<div>
<label for="intitule">Intitule :</label>
<input type="text" id="intitule" name="intitule" required>
</div>
<div>
<label for="dateDeb">Date de début :</label>
<input type="date" id="dateDeb" name="dateDeb" required>
</div>
<div>
<label for="dateFin">Date de fin :</label>
<input type="date" id="dateFin" name="dateFin">
</div>
<div>
<label for="nomEntreprise">Nom de l'entreprise :</label>
<input type="text" id="nomEntreprise" name="nomEntreprise" required>
</div>
<div>
<label for="currentJob">Job en cours ? :</label>
<input type="checkbox" name="currentJob" id="currentJob">
</div>
<div>
<input type="submit" value="user/addExperience">
</div>
</form>
<a href="{{dir}}/user/displayExperience">Retour</a>
</div>
<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.5.3/dist/umd/popper.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script>
</body>
</html>

@ -1,52 +0,0 @@
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Ajouter une foramtion</title>
<link rel="stylesheet" href="">
</head>
<body>
<div>
<h1>Ajouter une formation</h1>
<form action="{{dir}}/user/addFormation" method="POST" enctype="multipart/form-data">
<div>
<label for="nom">Nom :</label>
<input type="text" id="nom" name="nom" required>
</div>
<div>
<label for="ville">Ville :</label>
<input type="text" id="ville" name="ville" required>
</div>
<div>
<label for="dateDeb">Date de début :</label>
<input type="date" id="dateDeb" name="dateDeb" required>
</div>
<div>
<label for="dateFin">Date de fin :</label>
<input type="date" id="dateFin" name="dateFin">
</div>
<div>
<label for="currentFormation">Formation en cours ? :</label>
<input type="checkbox" name="currentFormation" id="currentFormation">
</div>
<div>
<input type="submit" value="addFormation">
</div>
</form>
<a href="{{dir}}/user/displayFormation">Retour</a>
</div>
<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.5.3/dist/umd/popper.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script>
</body>
</html>

@ -1,36 +0,0 @@
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title>Experience</title>
<link rel="stylesheet" href="">
</head>
<body>
<div>
{% if experience %}
{% for exp in experience %}
<h2>Détails de l'expérience : {{exp.getIntitule()}}</h2>
<div>
<p><strong>nom de l'entreprise :</strong> {{ exp.getNomEntreprise() }}</p>
<p><strong>Date de début :</strong> {{ exp.getDateDebut() }}</p>
<p><strong>Date de fin :</strong> {{ exp.getDateFin }}</p>
<p><strong>Job en cours ? :</strong> {{ exp.isTravailActuel() }}</p>
</div>
<a href="{{dir}}/user/{{exp.getId}}/deleteExperience">Supprimer cette experience</a>
{% endfor %}
{% else %}
<p>Aucune expérience n'a été ajouté</p>
{% endif %}
</div>
<div>
<a href="{{dir}}/user/experienceForm">Ajouter Experience</a>
<br>
<a href="{{dir}}/user/displayProfil">Retour</a>
</div>
<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.5.3/dist/umd/popper.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script>
</body>
</html>

@ -1,36 +0,0 @@
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title>Formation</title>
<link rel="stylesheet" href="">
</head>
<body>
<div>
{% if formation %}
{% for form in formation %}
<h2>Détails de la formation : {{form.getNom()}}</h2>
<div>
<p><strong>ville :</strong> {{ form.getVille() }}</p>
<p><strong>Date de début :</strong> {{ form.getDateDebut() }}</p>
<p><strong>Date de fin :</strong> {{ form.getDateFin }}</p>
<p><strong>Formation en cours ? :</strong> {{ form.isFormationActuelle() }}</p>
<a href="{{dir}}/user/{{form.getId}}/deleteFormation">Supprimer cette formation</a>
</div>
{% endfor %}
{% else %}
<p>Aucune formation n'a été ajouté.</p>
{% endif %}
</div>
<div>
<a href="{{dir}}/user/FormationForm">Ajouter Formation</a>
<br>
<a href="{{dir}}/user/displayProfil">Retour</a>
</div>
<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.5.3/dist/umd/popper.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script>
</body>
</html>

@ -1,51 +0,0 @@
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title>Mes Expérience(s)</title>
<link rel="stylesheet" href="">
</head>
<body>
<header>
{% include "menu.html" %}
</header>
<div>
<div>
<h1>Mes Expériences</h1>
<a href="../public/index.php?action=ajouterExperience">Ajouter une expérience</a>
</div>
<ul>
{% if experience is not empty %}
{% for experience in experiences %}
<li>
<div>
<h2>{{ experience.intitule }}</h2>
<p> <strong>nom de l'entreprise :</strong> {{ experience.getNomEntreprise() }}</p>
<p><strong>Date début :</strong> {{ experience.getDateDebut }}</p>
<p><strong>Date de fin:</strong> {{ experience.getDateFin }}</p>
<p><strong>Travail actuel :</strong> {{ experience.isTravailActuel }}</p>
</div>
<form action="../public/index.php?action=supprimerExperience&id={{ experience.id }}" method="POST">
<button type="submit" id="deleteButton">
<img src="assets/close.png" alt="Supprimer" width="20px">
</button>
</form>
</li>
{% endfor %}
{% else %}
<li>Aucun événement trouvé.</li>
{% endif %}
</ul>
</div>
<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.5.3/dist/umd/popper.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script>
</body>
</html>

@ -27,7 +27,7 @@
<!-- Afficher boutons de connexion et d'inscription -->
{% if nom and prenom %}
<!-- Afficher bouton de déconnexion -->
<a href="{{dir}}/user/displayProfil">Mon profil</a>
<a href="index.php?action=displayExperience">Mon profil</a>
<a href="{{dir}}/user/deconnexion" class="button">Déconnexion</a>
{% else %}
<div class="login-register">

@ -1,52 +0,0 @@
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title> Mon profil </title>
<link rel="stylesheet" href="">
</head>
<body>
<header>
{% include "menu.html" %}
</header>
<div>
{% if profil %}
<!-- <p>{{ dump(profil) }}</p> -->
<!-- By Thomas -->
<!-- Je ne comprends pas pourquoi le contenu du profil ne s'affiche pas -->
<h1>Profil de : {{ profil.getNom() }} {{ profil.getPrenom() }}</h1>
<div>
<p><strong>Mail :</strong> {{ profil.getEmail() }}</p>
<p><strong>Linkedin :</strong> {{ profil.getLinkedinUrl() }}</p>
<p><strong>Git :</strong> {{ profil.getGithubUrl() }}</p>
<p><strong>Portforlio :</strong> {{ profil.getPortfolioUrl() }}</p>
<!-- Modification du profil -->
</div>
{% else %}
<p>Error Profil</p>
{% endif %}
</div>
<div>
<h1> Mes expériences </h1>
<!-- Partie expérience de l'utilisateur -->
{% include "detailExperience.html" %}
</div>
<div>
<h1> Mes formations </h1>
<!-- Partie formation de l'utilisateur -->
{% include "detailFormation.html" %}
</div>
<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.5.3/dist/umd/popper.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script>
</body>
</html>
Loading…
Cancel
Save