ajout vue offres

offres2
Baptiste D 1 year ago
parent ce81b7af42
commit ec5c68db48

BIN
.DS_Store vendored

Binary file not shown.

BIN
php/.DS_Store vendored

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 515 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

@ -0,0 +1,145 @@
a {
text-decoration: none;
}
.navbar-container {
display: flex;
justify-content: space-between;
align-items: center;
padding: 0 2rem;
width: 100%;
height: 70px;
background: #fff;
color: #212121;
position: sticky;
top: 0;
left: 0;
z-index: 100;
}
.navbar-container .logo-container a {
font-size: 1.5rem;
font-weight: 500;
font-family: 'Kanit', sans-serif;
text-transform: uppercase;
cursor: pointer;
color: #212121;
max-height: 70px;
}
.navbar-container .nav-items {
display: flex;
align-items: center;
gap: 3rem;
list-style: none;
}
.navbar-container .nav-items .nav-link a {
color: #212121;
padding: 10px;
text-transform: uppercase;
transition: 0.2s;
}
.navbar-container .nav-items .nav-link:after {
content: '';
display: block;
border-top: 3px solid #00DBFF;
transform: scaleX(0);
transition: transform 250ms ease-in-out;
}
.navbar-container .nav-items .nav-link:hover:after {
transform: scaleX(0.8);
}
.navbar-container .nav-items .login-register {
display: flex;
flex-direction: row;
gap: 1rem;
}
.navbar-container .nav-items .login-register .button {
color: #00DBFF;
padding: 5px 20px;
text-transform: uppercase;
border-radius: 15px;
border: #fff 2px solid;
}
.navbar-container .nav-items .login-register .button2{
background: #00DBFF;
color: #fff;
border-radius: 15px;
}
.navbar-container .nav-items .login-register .button:hover {
border: #00DBFF 2px solid;
}
.navbar-container .nav-items .login-register .button2:hover {
border: #00A4FF 2px solid;
}
@media(max-width: 1030px) {
.navbar-container {
padding: 0 1rem;
}
.navbar-container .nav-items {
gap: 0.1rem;
}
.navbar-container .nav-items .nav-link a,
.navbar-container .nav-items .login-register .button {
font-size: 0.9rem;
}
}
@media(max-width: 915px) {
.navbar-container .nav-items {
flex-direction: column;
position: fixed;
top: 70px;
right: -100%;
width: 100vw;
height: 100vh;
padding: 1rem 0;
z-index: 99;
background: #fff;
transition: 0.2s ease-in;
}
.bars {
width: 22px;
height: auto;
cursor: pointer;
}
.bars .bar {
width: 100%;
height: 2px;
background: #212121;
margin: 5px;
}
.navbar-container .nav-items {
gap: 3rem;
}
.navbar-container .nav-items .login-register {
width: 50%;
text-align: center;
flex-direction: column;
gap: 2rem;
}
.navbar-container .nav-items .login-register .button {
padding: 1rem 0;
}
}
.navbar-container .nav-items.active {
right: 0;
}

@ -0,0 +1,32 @@
// change la possibilité d'entrer une ville pour l'offre
// cas où l'offre est à pourvoir en full remote
document.getElementById("fullRemote").addEventListener("change", function () {
var villeInput = document.getElementById("ville");
villeInput.disabled = this.checked;
//var ville = document.getElementById('')
});
document.addEventListener("DOMContentLoaded", function() {
const form = document.querySelector("form");
const submitButton = document.querySelector('input[type="submit"]');
// Fonction pour vérifier si tous les champs du formulaire sont remplis
function checkFormFields() {
const inputs = form.querySelectorAll('input, textarea, select');
let allFieldsFilled = true;
inputs.forEach(function(input) {
if (!input.value) {
allFieldsFilled = false;
}
});
submitButton.disabled = !allFieldsFilled;
}
// Écoute les événements de saisie dans les champs du formulaire
form.addEventListener("input", checkFormFields);
// Appelle la fonction initiale pour la première vérification
checkFormFields();
});

@ -19,7 +19,7 @@ class FrontControleur
"deconnexion","proposerOffre","consulterProfil","modifierProfil","signaler"
],
"Utilisateur" => [
"connection", "inscription", "accueil","consulterProfilLimite"
"connection", "inscription", "accueil","consulterProfilLimite","publierOffre"
]
);

@ -4,7 +4,11 @@ namespace App\controleur;
use App\gateway\Connection;
use App\gateway\ImageGateway;
use App\modele\Image;
use App\gateway\OffreGateway;
use App\metier\Image;
use App\modele\NiveauEtudes;
use App\modele\Offre;
use App\modele\TypeContrat;
class UtilisateurControleur
{
@ -13,7 +17,7 @@ class UtilisateurControleur
global $twig;
if (!isset($_REQUEST["action"])) {
//$action = NULL;
$action = "CreerOffre";
$action = "consulterOffres";
} else {
$action = \App\config\Validation::nettoyerString($_REQUEST["action"]);
}
@ -30,16 +34,22 @@ class UtilisateurControleur
case "inscription":
$this->inscription();
break;
case "consulterOffres":
$this->consulterOffres();
break;
case "consulterProfilLimite":
$this->consulterProfilLimite();
break;
case "CreerOffre":
case "creerOffre":
//echo "test";
$this->creerOffre();
break;
case "publierOffre":
$this->publierOffre();
break;
case "testAction":
$this->testAction();
break;
default:
$dVueErreur[] ="Action inconnue ou non autorisée";
echo $twig->render("erreur.html",['dVueErreur' => $dVueErreur]);
@ -72,7 +82,7 @@ class UtilisateurControleur
// Si l'inscription a réussi, redirigez l'utilisateur vers une page de confirmation
// Vous pouvez également gérer les erreurs ici en cas d'échec de l'inscription
if ($nouvelUtilisateur instanceof \App\modele\Alumni) {
if ($nouvelUtilisateur instanceof \App\metier\Alumni) {
// L'inscription a réussi, redirigez l'utilisateur vers une page de confirmation
// par exemple :
header('Location: index.php?action=inscription_success');
@ -98,14 +108,18 @@ class UtilisateurControleur
//TODO
}
protected function consulterOffres()
{
global $twig;
echo $twig->render('offres.html', []);
}
protected function creerOffre()
{
/*
global $twig;
echo $twig->render('testImage.html', []);
/*
* */
$con = new Connection("mysql:host=localhost;dbname=dbAlica",'test','test');
echo $twig->render('CreerOffre.html', []);
/* $con = new Connection("mysql:host=localhost;dbname=dbAlica",'test','test');
$imgGw = new ImageGateway($con);
@ -114,33 +128,93 @@ class UtilisateurControleur
//echo $imglist[0]->getBlob();
// echo $imglist[0]->toString();
echo '<img src="data:image/jpg;base64,' . base64_encode($imglist[0]->getBlob() ). '" height="100" width="100" alt="mon image" title="image"/>';
echo '<img src="data:image/jpg;base64,' . base64_encode($imglist[0]->getBlob() ). '" height="100" width="100" alt="mon image" title="image"/>';*/
}
protected function publierOffre()
{
global $twig;
try{
if(isset($_POST["submit"]))
{
// echo "numero : ",$_POST["num"];
$con = new Connection("mysql:host=localhost;dbname=dbAlica",'test','test');
$imgGw = new ImageGateway($con);
$img = new Image($imgGw->getNewId(),$_FILES["image"]["name"],
$_FILES["image"]["size"],$_FILES["image"]["type"],file_get_contents($_FILES["image"]["tmp_name"]));
$imgid = $imgGw->findByNom($img->getName())->getId();
$desc = $_POST["description"];
$descposte = $_POST["descriptPoste"];
$nom = $_POST["name"];
$ville = $_POST["ville"];
$entreprise = $_POST["entreprise"];
$profilRecherche = $_POST["profilRecherche"];
$mail = $_POST["mail"];
$num = $_POST["num"];
$site = $_POST["site"];
$type = match ($_POST["type"]) {
"Stage" => TypeContrat::Stage,
"CDI" => TypeContrat::CDI,
"CDD" => TypeContrat::CDD,
"Alternance" => TypeContrat::Alternance,
default => TypeContrat::CDD,
};
$niveauEtudes = match ($_POST["education"]) {
"Bac+2" => NiveauEtudes::Bac2,
"Bac+3" => NiveauEtudes::Bac3,
"Bac+5" => NiveauEtudes::Bac5,
default => NiveauEtudes::Indifferent,
};
$offre = new Offre(NULL,$nom,$desc,$imgid,$type,$ville,$entreprise,$profilRecherche,$mail,$num,$site,$type,$niveauEtudes);
}
}
catch(\Exception )
{
$twig->render("erreur.html",['dVueErreur' => "erreur "]);
}
if(isset($_POST["submit"]))
$img = new Image($_FILES["image"]["name"],
$_FILES["image"]["size"],$_FILES["image"]["type"],file_get_contents($_FILES["image"]["tmp_name"]));
else {
echo "<h1>Image non inserée<h1>";
echo $twig->render("erreur.html", ['dVueErreur' => "Erreur lors de l'upload de l'image"]);
return;
}
$con = new Connection("mysql:host=localhost;dbname=dbAlica",'test','test');
$imgGw = new ImageGateway($con);
$imgGw->insertImage($img);
//echo $img->getBlob();
// echo '<img src="data:image/jpg;base64,' . base64_encode($img->getBlob() ). '" height="100" width="100" alt="mon image" title="image"/>';
echo "<h1>Image inserée<h1>";
}
protected function testAction()
{
echo "test action ";
$con = new Connection("mysql:host=localhost;dbname=dbAlica",'test','test');
$offreGw = new OffreGateway($con);
if($offreGw->getMaxid() == NULL)
echo "max id == NULL";
else echo "max id != NULL";
}
}

@ -2,8 +2,9 @@
namespace App\gateway;
use App\modele\Image;
use App\metier\Image;
use PDO;
class ImageGateway
{
private Connection $con;
@ -31,7 +32,7 @@ class ImageGateway
public function insert(int $id,string $name, string $desc, string $taille, string $type, string $blob)
{
$query = 'INSERT INTO Image (nom, taille, type, desc, blob) VALUES (:i, :n, :t, :ty, :d, :b)';
$query = 'INSERT INTO Image VALUES (:i, :n, :t, :ty, :d, :b)';
$this->con->executeQuery($query, array(
':i' => array($id,PDO::PARAM_INT),
':n' => array($name, PDO::PARAM_STR),
@ -43,6 +44,8 @@ class ImageGateway
}
public function delete(int $id)
{
$query = 'DELETE FROM Image WHERE id=:i';
@ -61,6 +64,25 @@ class ImageGateway
return new Image($res[0]['nom'], $res[0]['desc'], $res[0]['taille'], $res[0]['type'], $res[0]['blob']);
}
public function findByNom(string $nom)
{
$query = 'SELECT * FROM Image WHERE nom=:n';
$this->con->executeQuery($query, array(
':n' => array($nom, PDO::PARAM_STR)
));
$res = $this->con->getResults();
return new Image($res[0]['nom'], $res[0]['taille'], $res[0]['type'], $res[0]['blob']);
}
public function getNewId()
{
$query = 'SELECT MAX(id) FROM Image';
$this->con->executeQuery($query);
$res = $this->con->getResults();
return $res[0]['MAX(id)'] + 1;
}
public function getAll()
{
$query = 'SELECT * FROM Image';

@ -15,4 +15,12 @@ class OffreGateway
$query='INSERT INTO Offre VALUES ()';
$this->con->executeQuery($query, array());
}
public function getMaxid()
{
$query = 'SELECT MAX(id) FROM Offre';
$this->con->executeQuery($query, array());
$res = $this->con->getResults();
return $res[0]['MAX(id)'];
}
}

@ -1,6 +1,6 @@
<?php
namespace App\modele;
namespace App\metier;
class Alumni{
/**

@ -1,5 +1,5 @@
<?php
namespace App\modele;
namespace App\metier;
class Article
{

@ -1,5 +1,5 @@
<?php
namespace App\modele;
namespace App\metier;
class Evenement
{

@ -1,5 +1,5 @@
<?php
namespace App\modele;
namespace App\metier;
class Experience
{

@ -1,5 +1,5 @@
<?php
namespace App\modele;
namespace App\metier;
class Formation
{

@ -1,10 +1,10 @@
<?php
namespace App\modele;
namespace App\metier;
class Image
{
//private int $id;
private int $id;
private string $name;
private string $taille;
@ -14,14 +14,15 @@ class Image
private string $blob;
/**
* @param int $id
* @param string $name
* @param string $taille
* @param string $type
* @param string $blob
*/
public function __construct( string $name, string $taille, string $type, string $blob)
public function __construct(int $id, string $name, string $taille, string $type, string $blob)
{
//$this->id = $id;
$this->id = $id;
$this->name = $name;
$this->taille = $taille;
$this->type = $type;
@ -49,6 +50,11 @@ class Image
return $this->blob;
}
public function getId() : string
{
return $this->id;
}
public function toString() : string {
return "Image : " . $this->name . " " . $this->taille . " " . $this->type . " blob " . $this->blob;
}

@ -1,6 +1,9 @@
<?php
namespace App\modele;
use App\metier\Alumni;
use App\metier\Profil;
enum TypeContrat
{
case CDI;
@ -49,7 +52,6 @@ class Offre
/**
* @var string Url de l'image
*/
private string $imageUrl;
/**
* @var \App\metier\TypeContrat Type de contrat
@ -86,6 +88,8 @@ class Offre
*/
private \App\metier\NiveauEtudes $niveauEtudes;
private int $imgId;
/**
* @var string Email de contact
*/
@ -118,13 +122,13 @@ class Offre
* @param string $numero
* @param string $siteUrl
*/
public function __construct(int $id, Alumni $offreur, string $nom, string $description, string $imageUrl, \App\metier\TypeContrat $typeContrat, string $ville, string $entreprise, string $descriptifPoste, Profil $profil, string $experience, \App\metier\NiveauEtudes $niveauEtudes, string $mailContact, string $numero, string $siteUrl)
public function __construct(int $id, Alumni $offreur, string $nom, string $description,int $imgId, \App\metier\TypeContrat $typeContrat, string $ville, string $entreprise, string $descriptifPoste, Profil $profil, string $experience, \App\metier\NiveauEtudes $niveauEtudes, string $mailContact, string $numero, string $siteUrl)
{
$this->id = $id;
$this->offreur = $offreur;
$this->nom = $nom;
$this->description = $description;
$this->imageUrl = $imageUrl;
$this->imgId = $imgId;
$this->typeContrat = $typeContrat;
$this->ville = $ville;
$this->entreprise = $entreprise;
@ -211,4 +215,15 @@ class Offre
{
return $this->siteUrl;
}
public function getImgId(): int
{
return $this->imgId;
}
public function setImgId(int $imgId): void
{
$this->imgId = $imgId;
}
}

@ -1,5 +1,5 @@
<?php
namespace App\modele;
namespace App\metier;
class Profil
{

@ -1,5 +1,5 @@
<?php
namespace App\modele;
namespace App\metier;
enum Role
{
case Admin;

@ -2,13 +2,15 @@
namespace App\modele;
use App\metier\Alumni;
class AdminModele extends MembreModele
{
/**
* @description supprimer un compte
* @param Alumni $account compte à supprimer
*/
public function deleteAccount(\App\modele\Alumni $account)
public function deleteAccount(\App\metier\Alumni $account)
{
// TO DO
}

@ -16,12 +16,12 @@ class UtilisateurModele
* @description se connecter
* @param string email
* @param string hash
* @return \App\modele\Alumni
* @return \App\metier\Alumni
*/
public function Login(string $email,string $hash) : \App\modele\Alumni
public function Login(string $email,string $hash) : \App\metier\Alumni
{
// TO DO
return new \App\modele\Alumni(null,null,null);
return new \App\metier\Alumni(null,null,null);
}
/**
@ -31,7 +31,7 @@ class UtilisateurModele
* @param string $pseudo
* @return \Alumni chargé
*/
public function inscription(string $email, string $hashpassword): \App\modele\Alumni
public function inscription(string $email, string $hashpassword): \App\metier\Alumni
{
$dsn = "mysql:host=localhost;dbname=dbAlica";
$username = "test";
@ -43,11 +43,11 @@ class UtilisateurModele
// Insérez le nouvel utilisateur dans la base de données en utilisant AlumniGateway
if ($gate->insert($email, $hashpassword, $role)) {
// L'insertion a réussi, retournez le nouvel utilisateur
$nouvelUtilisateur = new \App\modele\Alumni($email, $hashpassword, $role);
$nouvelUtilisateur = new \App\metier\Alumni($email, $hashpassword, $role);
return $nouvelUtilisateur;
} else {
// L'insertion a échoué, renvoyez un utilisateur vide pour indiquer l'échec
return new \App\modele\Alumni(null, null, null);
return new \App\metier\Alumni(null, null, null);
}
}
}

@ -9,44 +9,27 @@
<body>
<header>
<nav class="navbar navbar-expand-lg navbar-light bg-light">
<a class="navbar-brand" href="accueil.html">Reseau Alica Info</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav">
<li class="nav-item">
<a class="nav-link" href="#">A propos</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Evenements</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Offres</a>
</li>
</ul>
</div>
</nav>
{% include "menu.html" %}
</header>
<main class="container mt-4">
<h1>Publier Une Offre</h1>
<form style="background-color: #00DBFF" class="p-4" enctype="multipart/form-data" action="../php/modeles/OffreModele.php" method="post">
<form style="background-color: #00DBFF" class="p-4" enctype="multipart/form-data" action="index.php?action=publierOffre" method="post">
<p>Les champs contenant des astrérisques * sont obligatoires.</p>
<div class="form-group">
<label for="name">Intitulé de l'offre</label>
<label for="name">Intitulé de l'offre*</label>
<input type="text" class="form-control" id="name" name="name" placeholder="Intitulé">
</div>
<div class="form-group">
<label for="entreprise">Nom de l'entreprise :</label>
<label for="entreprise">Nom de l'entreprise :*</label>
<input type="text" class="form-control" id="entreprise" name="entreprise" placeholder="Entreprise">
</div>
<div class="form-group">
<label for="description">Description</label>
<label for="description">Description*</label>
<textarea class="form-control" id="description" name="description" placeholder="Description rapide"></textarea>
</div>
@ -61,7 +44,7 @@
</div>
<div class="form-group">
<label for="choixContrat">Choisissez un type de contrat :</label>
<label for="choixContrat">Choisissez un type de contrat :*</label>
<select class="form-control" id="choixContrat" name="typeContrat">
<option value="CDI">CDI</option>
<option value="CDD">CDD</option>
@ -71,17 +54,17 @@
</div>
<div class="form-group">
<label for="descriptPoste">Descriptif du Poste :</label>
<label for="descriptPoste">Descriptif du Poste :*</label>
<textarea class="form-control" id="descriptPoste" name="descriptPoste" placeholder="Description du Poste"></textarea>
</div>
<div class="form-group">
<label for="profilRecherche">Profil Recherché :</label>
<label for="profilRecherche">Profil Recherché :*</label>
<textarea class="form-control" id="profilRecherche" name="profilRecherche" placeholder="Profil recherché"></textarea>
</div>
<div class="form-group">
<label for="choixExp">Experience Recherchée :</label>
<label for="choixExp">Experience Recherchée :*</label>
<select class="form-control" id="choixExp" name="choixExp">
<option value="Junior">Junior</option>
<option value="Senior">Senior</option>
@ -89,34 +72,35 @@
</select>
</div>
<label>Niveau d'études :</label>
<label>Niveau d'études :*</label>
<div class="form-check-inline">
<input type="checkbox" class="form-check-input" id="indifferent" name="education" value="indifferent" checked>
<input type="radio" class="form-check-input" id="indifferent" name="education" checked>
<label class="form-check-label" for="indifferent">Indifférent</label>
</div>
<div class="form-check-inline">
<input type="checkbox" class="form-check-input" id="bac2" name="education" value="bac2">
<input type="radio" class="form-check-input" id="bac2" name="education">
<label class="form-check-label" for="bac2">Bac +2</label>
</div>
<div class="form-check-inline">
<input type="checkbox" class="form-check-input" id="bac5" name="education" value="bac5">
<label class="form-check-label" for="bac5">Bac +5</label>
<input type="radio" class="form-check-input" id="bac5" name="education">
<label class="form-check-label" for="bac5">Bac +3</label>
</div>
<div class="form-check-inline">
<input type="checkbox" class="form-check-input" id="bac8" name="education" value="bac8">
<label class="form-check-label" for="bac8">Bac +8</label>
<input type="radio" class="form-check-input" id="bac8" name="education">
<label class="form-check-label" for="bac8">Bac +5</label>
</div>
<div class="form-group">
<label for="mail">Email de contact :</label>
<label for="mail">Email de contact :*</label>
<input type="text" class="form-control" id="mail" name="mail" placeholder="Adresse de contact">
</div>
<div class="form-group">
<label for="num">Numero de contact :</label>
<label for="num">Numero de contact :*</label>
<input type="text" class="form-control" id="num" name="num" placeholder="Numéro de contact">
</div>
@ -126,7 +110,7 @@
</div>
<input type="file" name="fileToUpload" id="fileToUpload">
<input type="submit" value="Publier L'annonce" name="submit">
<input type="submit" value="Publier L'annonce" name="submit" id="submit">
</form>

@ -0,0 +1,30 @@
<!DOCTYPE html>
<html lang="fr">
<head>
<link rel="stylesheet" type="text/css" href="css/menu.css">
</head>
<nav class="navbar-container">
<div class="logo-container">
<a href="index.php">
<img src="assets/logo.png" alt="Logo" height="70px">
</a>
</div>
<div class="bars">
<div class="bar"></div>
<div class="bar"></div>
<div class="bar"></div>
</div>
<ul class="nav-items">
<li class="nav-link"><a href="#">A propos</a></li>
<li class="nav-link"><a href="#">Evenements</a></li>
<li class="nav-link"><a href="#">Offres</a></li>
<li class="nav-link"><a href="#">Nous contacter</a></li>
</ul>
<ul class="nav-items">
<div class="login-register">
<a href="index.php?action=connection" class="button">Connexion</a>
<a href="index.php?action=inscription" class="button button2">Inscription</a>
</div>
</ul>
</nav>
</html>

@ -0,0 +1,67 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Alica - Offres</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
</head>
<header>
{% include "menu.html" %}
</header>
<div class="container mt-4">
<h1 id="titrePrincipal">Offres d'emploi</h1>
<article class="mb-4">
<div class="row">
<div class="col-sm-3">
<img src="assets/michelin.png" alt="Michelin" class="img-fluid">
</div>
<div class="col-sm-9">
<h3>Administrateur de bases de données (CDI)</h3>
<p>Julien Martin - 15 Janvier 2022</p>
<p>Nous recherchons un administrateur en base de données pour contribuer au développement de nos infrastructures</p>
<img src="assets/location.png" alt="Localisation">
<p>Clermont-Ferrand (63)</p>
</div>
</div>
</article>
<article class="mb-4">
<div class="row">
<div class="col-sm-3">
<img src="assets/michelin.png" alt="Michelin" class="img-fluid">
</div>
<div class="col-sm-9">
<h3>Administrateur de bases de données (CDI)</h3>
<p>Julien Martin - 15 Janvier 2022</p>
<p>Nous recherchons un administrateur en base de données pour contribuer au développement de nos infrastructures</p>
<img src="assets/location.png" alt="Localisation">
<p>Clermont-Ferrand (63)</p>
</div>
</div>
</article>
<article class="mb-4">
<div class="row">
<div class="col-sm-3">
<img src="assets/michelin.png" alt="Michelin" class="img-fluid">
</div>
<div class="col-sm-9">
<h3>Administrateur de bases de données (CDI)</h3>
<p>Julien Martin - 15 Janvier 2022</p>
<p>Nous recherchons un administrateur en base de données pour contribuer au développement de nos infrastructures</p>
<img src="assets/location.png" alt="Localisation">
<p>Clermont-Ferrand (63)</p>
</div>
</div>
</article>
</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>
</body>
</html>
Loading…
Cancel
Save