Skip to content
Snippets Groups Projects
Commit b17396a2 authored by csauder's avatar csauder
Browse files

:sparkles: Edition de bureau via un formulaire moche

parent b592ef8f
No related branches found
No related tags found
No related merge requests found
...@@ -9,7 +9,8 @@ ...@@ -9,7 +9,8 @@
"slim/twig-view": "^3.3", "slim/twig-view": "^3.3",
"slim/flash": "^0.4.0", "slim/flash": "^0.4.0",
"illuminate/database": "^10.40", "illuminate/database": "^10.40",
"symfony/console": "^7.0" "symfony/console": "^7.0",
"ext-http": "*"
}, },
"autoload": { "autoload": {
"psr-4": { "psr-4": {
......
...@@ -12,8 +12,6 @@ $containerBuilder->addDefinitions(__DIR__ . '/container.php'); ...@@ -12,8 +12,6 @@ $containerBuilder->addDefinitions(__DIR__ . '/container.php');
$container = $containerBuilder->build(); $container = $containerBuilder->build();
$app = $container->get(App::class); $app = $container->get(App::class);
$app->addRoutingMiddleware();
$app->add(TwigMiddleware::createFromContainer($app));
(require __DIR__ . '/routes.php')($app); (require __DIR__ . '/routes.php')($app);
......
...@@ -5,6 +5,7 @@ use Slim\Factory\AppFactory; ...@@ -5,6 +5,7 @@ use Slim\Factory\AppFactory;
use Slim\Middleware\ErrorMiddleware; use Slim\Middleware\ErrorMiddleware;
use Psr\Container\ContainerInterface; use Psr\Container\ContainerInterface;
use Slim\Views\Twig; use Slim\Views\Twig;
use Slim\Views\TwigMiddleware;
return [ return [
'settings' => function () { 'settings' => function () {
...@@ -22,7 +23,10 @@ return [ ...@@ -22,7 +23,10 @@ return [
App::class => function (ContainerInterface $container) { App::class => function (ContainerInterface $container) {
$container->get('db'); $container->get('db');
AppFactory::setContainer($container); AppFactory::setContainer($container);
return AppFactory::create(); $app = AppFactory::create();
$app->addRoutingMiddleware();
$app->add(TwigMiddleware::createFromContainer($app));
return $app;
}, },
ErrorMiddleware::class => function (ContainerInterface $container) { ErrorMiddleware::class => function (ContainerInterface $container) {
$app = $container->get(App::class); $app = $container->get(App::class);
......
...@@ -3,9 +3,16 @@ ...@@ -3,9 +3,16 @@
use Slim\App; use Slim\App;
use App\Controller\CompanyController; use App\Controller\CompanyController;
use App\Controller\HomeController; use App\Controller\HomeController;
use App\Controller\OfficeController;
return function (App $app) { return function (App $app) {
// On gère la route "par défaut" de l'application // On gère la route "par défaut" de l'application
$app->get('/', HomeController::class . ':index'); $app->get('/', HomeController::class . ':index');
// CompanyController
$app->get('/company/{id}', CompanyController::class . ':index'); $app->get('/company/{id}', CompanyController::class . ':index');
// OfficeController
$app->get('/office/{id}/edit', OfficeController::class . ':editGet');
$app->post('/office/{id}/edit', OfficeController::class . ':editPost');
}; };
const modal = document.querySelector('#modal-wrapper');
const modalContent = document.querySelector('#modal-content');
const modalTitle = document.querySelector('#modal-title');
function openModal() {
modal.classList.add('active');
}
function closeModal() {
modal.classList.remove('active')
modalContent.innerHTML = ""
}
function loadModalContent(url, title) {
fetch(url)
.then(response => response.text())
.then(data => {
modalContent.innerHTML = data;
modalTitle.innerHTML = title;
openModal()
})
.catch(error => console.log(error))
}
// On gère la fermeture du modal
function init() {
document.querySelector('#close-modal').addEventListener("click", closeModal)
document.addEventListener('keydown', event => {
if (event.key == 'Escape') closeModal();
})
document.querySelector('.offices-list').addEventListener('click', event => {
if (event.target.classList.contains('office-edit')) {
loadModalContent(`/office/${event.target.dataset.officeId}/edit`, 'Édition du bureau')
}
})
}
document.addEventListener('DOMContentLoaded', init)
...@@ -79,3 +79,65 @@ html, body { ...@@ -79,3 +79,65 @@ html, body {
width: 60px; width: 60px;
color: var(--accent-color); color: var(--accent-color);
} }
.button, button, input[type="submit"] {
background: var(--main-color);
color: var(--main-bg-color);
border-radius: 2px;
border: none;
padding: 0.5em 1em;
cursor: pointer;
transition: all 0.2s ease-in-out;
}
.button:hover, button:hover, input[type="submit"]:hover {
background: var(--accent-color);
}
.button:active, button:active, input[type="submit"]:active {
transform: scale(0.95);
}
.text-center {
text-align: center;
}
.modal-wrapper {
position: fixed;
top: 0;
left: 0;
z-index: 100;
width: 100%;
height: 100%;
background-color: rgba(0,0,0,0.5);
display: none;
justify-content: center;
align-items: center;
}
#modal {
background-color: var(--main-bg-color);
padding: 1em ;
border-radius: 5px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
width: 80%;
max-width: 600px;
}
.modal-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 1em;
}
.modal-content {
margin-bottom: 1em;
}
.active {
display: flex;
}
...@@ -42,6 +42,8 @@ class CreateDatabaseCommand extends Command ...@@ -42,6 +42,8 @@ class CreateDatabaseCommand extends Command
email VARCHAR(255) , email VARCHAR(255) ,
website VARCHAR(255) , website VARCHAR(255) ,
image VARCHAR(255) , image VARCHAR(255) ,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
head_office_id INT , head_office_id INT ,
PRIMARY KEY (id) PRIMARY KEY (id)
); );
...@@ -59,6 +61,8 @@ class CreateDatabaseCommand extends Command ...@@ -59,6 +61,8 @@ class CreateDatabaseCommand extends Command
email VARCHAR(255) , email VARCHAR(255) ,
phone VARCHAR(255) , phone VARCHAR(255) ,
company_id INT NOT NULL, company_id INT NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (id), PRIMARY KEY (id),
FOREIGN KEY (company_id) REFERENCES companies (id) FOREIGN KEY (company_id) REFERENCES companies (id)
); );
...@@ -74,6 +78,8 @@ class CreateDatabaseCommand extends Command ...@@ -74,6 +78,8 @@ class CreateDatabaseCommand extends Command
email VARCHAR(255) , email VARCHAR(255) ,
phone VARCHAR(255) , phone VARCHAR(255) ,
job_title VARCHAR(255) , job_title VARCHAR(255) ,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (id), PRIMARY KEY (id),
FOREIGN KEY (office_id) REFERENCES offices (id) FOREIGN KEY (office_id) REFERENCES offices (id)
); );
......
...@@ -42,26 +42,26 @@ class PopulateDatabaseCommand extends Command ...@@ -42,26 +42,26 @@ class PopulateDatabaseCommand extends Command
$db->getConnection()->statement("INSERT INTO `companies` VALUES $db->getConnection()->statement("INSERT INTO `companies` VALUES
(1,'Stack Exchange','0601010101','stack@exchange.com','https://stackexchange.com/','https://i.stack.imgur.com/UPdHB.jpg',null), (1,'Stack Exchange','0601010101','stack@exchange.com','https://stackexchange.com/','https://i.stack.imgur.com/UPdHB.jpg', now(), now(), null),
(2,'Google','0602020202','contact@google.com','https://www.google.com','https://upload.wikimedia.org/wikipedia/commons/thumb/e/e0/Google_office_%284135991953%29.jpg/800px-Google_office_%284135991953%29.jpg?20190722090506',null) (2,'Google','0602020202','contact@google.com','https://www.google.com','https://upload.wikimedia.org/wikipedia/commons/thumb/e/e0/Google_office_%284135991953%29.jpg/800px-Google_office_%284135991953%29.jpg?20190722090506',now(), now(), null)
"); ");
$db->getConnection()->statement("INSERT INTO `offices` VALUES $db->getConnection()->statement("INSERT INTO `offices` VALUES
(1,'Bureau de Nancy','1 rue Stanistlas','Nancy','54000','France','nancy@stackexchange.com',NULL,1), (1,'Bureau de Nancy','1 rue Stanistlas','Nancy','54000','France','nancy@stackexchange.com',NULL,1, now(), now()),
(2,'Burea de Vandoeuvre','46 avenue Jeanne d\'Arc','Vandoeuvre','54500','France',NULL,NULL,1), (2,'Burea de Vandoeuvre','46 avenue Jeanne d\'Arc','Vandoeuvre','54500','France',NULL,NULL,1, now(), now()),
(3,'Siege sociale','2 rue de la primatiale','Paris','75000','France',NULL,NULL,2), (3,'Siege sociale','2 rue de la primatiale','Paris','75000','France',NULL,NULL,2, now(), now()),
(4,'Bureau Berlinois','192 avenue central','Berlin','12277','Allemagne',NULL,NULL,2) (4,'Bureau Berlinois','192 avenue central','Berlin','12277','Allemagne',NULL,NULL,2, now(), now())
"); ");
$db->getConnection()->statement("INSERT INTO `employees` VALUES $db->getConnection()->statement("INSERT INTO `employees` VALUES
(1,'Camille','La Chenille',1,'camille.la@chenille.com',NULL,'Ingénieur'), (1,'Camille','La Chenille',1,'camille.la@chenille.com',NULL,'Ingénieur', now(), now()),
(2,'Albert','Mudhat',2,'albert.mudhat@aqume.net',NULL,'Superviseur'), (2,'Albert','Mudhat',2,'albert.mudhat@aqume.net',NULL,'Superviseur', now(), now()),
(3,'Sylvie','Tesse',3,'sylive.tesse@factice.local',NULL,'PDG'), (3,'Sylvie','Tesse',3,'sylive.tesse@factice.local',NULL,'PDG', now(), now()),
(4,'John','Doe',4,'john.doe@generique.org',NULL,'Testeur'), (4,'John','Doe',4,'john.doe@generique.org',NULL,'Testeur', now(), now()),
(5,'Jean','Bon',1,'jean@test.com',NULL,'Developpeur'), (5,'Jean','Bon',1,'jean@test.com',NULL,'Developpeur', now(), now()),
(6,'Anais','Dufour',2,'anais@aqume.net',NULL,'DBA'), (6,'Anais','Dufour',2,'anais@aqume.net',NULL,'DBA', now(), now()),
(7,'Sylvain','Poirson',3,'sylvain@factice.local',NULL,'Administrateur réseau'), (7,'Sylvain','Poirson',3,'sylvain@factice.local',NULL,'Administrateur réseau', now(), now()),
(8,'Telma','Thiriet',4,'telma@generique.org',NULL,'Juriste') (8,'Telma','Thiriet',4,'telma@generique.org',NULL,'Juriste', now(), now())
"); ");
$db->getConnection()->statement("update companies set head_office_id = 1 where id = 1;"); $db->getConnection()->statement("update companies set head_office_id = 1 where id = 1;");
......
<?php
namespace App\Controller;
use App\Models\Company;
use App\Models\Office;
use http\Exception\InvalidArgumentException;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Slim\Exception\HttpNotFoundException;
class OfficeController extends DefaultController
{
public function editGet(ServerRequestInterface $request, ResponseInterface $response): ResponseInterface
{
$office = $this->findOfficeById($request);
return $this->twig->render($response, 'office/form.twig', ['office' => $office]);
}
public function editPost(ServerRequestInterface $request, ResponseInterface $response): ResponseInterface
{
$office = $this->findOfficeById($request);
$officeQuery = $request->getParsedBody();
if ($officeQuery['officeName'] !== null && $officeQuery['officeName'] !== $office->name) {
$office->name = $officeQuery['officeName'];
}
if ($officeQuery['officeAddress'] !== null && $officeQuery['officeAddress'] !== $office->address) {
$office->address = $officeQuery['officeAddress'];
}
if ($officeQuery['officeCity'] !== null && $officeQuery['officeCity'] !== $office->city) {
$office->city = $officeQuery['officeCity'];
}
if ($officeQuery['officeZipCode'] !== null && $officeQuery['officeZipCode'] !== $office->zip_code) {
$office->zip_code = $officeQuery['officeZipCode'];
}
if ($officeQuery['officeCountry'] !== null && $officeQuery['officeCountry'] !== $office->country) {
$office->country = $officeQuery['officeCountry'];
}
if ($officeQuery['officeEmail'] !== null && $officeQuery['officeEmail'] !== $office->email) {
$office->email = $officeQuery['officeEmail'];
}
if ($officeQuery['officePhone'] !== null && $officeQuery['officePhone'] !== $office->phone) {
$office->phone = $officeQuery['officePhone'];
}
$office->save();
return $response->withStatus(302)->withHeader('Location', '/company/' . $office->company->id);
}
private function findOfficeById(ServerRequestInterface $request): Office
{
$officeId = $request->getAttribute('id');
// On vérifie que l'id est bien un int
if (!is_numeric($officeId)) {
throw new InvalidArgumentException('Invalid office id format');
}
$office = Office::find($request->getAttribute('id'));
if (!$office) {
throw new HttpNotFoundException($request);
}
return $office;
}
}
...@@ -7,6 +7,9 @@ use Illuminate\Database\Eloquent\Relations\BelongsTo; ...@@ -7,6 +7,9 @@ use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\HasOne; use Illuminate\Database\Eloquent\Relations\HasOne;
/**
* @method static find($id)
*/
class Company extends Model class Company extends Model
{ {
protected $table = 'companies'; protected $table = 'companies';
......
...@@ -10,6 +10,9 @@ ...@@ -10,6 +10,9 @@
{% for office in company.offices %} {% for office in company.offices %}
<div class="office"> <div class="office">
<h2>{{ office.name }}</h2> <h2>{{ office.name }}</h2>
<div class="text-center">
<button class="office-edit" data-office-id="{{ office.id }}">✏️&nbsp;&nbsp;Éditer</button>
</div>
<p>Siège social: {{ office.headOffice ? 'Oui' : 'Non' }}</p> <p>Siège social: {{ office.headOffice ? 'Oui' : 'Non' }}</p>
<p>Adresse: {{ office.getFullAddressAttribute() }}</p> <p>Adresse: {{ office.getFullAddressAttribute() }}</p>
<div> <div>
......
...@@ -12,6 +12,19 @@ ...@@ -12,6 +12,19 @@
<body> <body>
{% block body %}{% endblock %} {% block body %}{% endblock %}
<div id="modal-wrapper" class="modal-wrapper">
<div id="modal">
<div class="modal-header">
<h2 id="modal-title">Titre</h2>
<button id="close-modal">X</button>
</div>
<div id="modal-content">
Bonjour
</div>
</div>
</div>
{% block scripts %} {% block scripts %}
<script src="/assets/script.js"></script> <script src="/assets/script.js"></script>
{% endblock %} {% endblock %}
......
<form id="officeForm" method="post" action="/office/{{ office.id }}/edit">
<div>
<label for="officeID">ID du bureau</label>
<input type="text" name="office ID" id="officeID" value="{{ office.id }}" disabled/>
</div>
<div>
<label for="officeName">Nom du bureau</label>
<input type="text" maxlength="255" name="officeName" id="officeName" value="{{ office.name }}" />
</div>
<div>
<label for="officeAddress">Adresse</label>
<input type="text" maxlength="255" name="officeAddress" id="officeAddress" value="{{ office.address }}" />
</div>
<div>
<label for="officeCity">Ville</label>
<input type="text" maxlength="255" name="officeCity" id="officeCity" value="{{ office.city }}" />
</div>
<div>
<label for="officeZipCode">Code Postal</label>
<input type="text" maxlength="255" name="officeZipCode" id="officeZipCode" value="{{ office.zip_code }}" />
</div>
<div>
<label for="officeCountry">Pays</label>
<input type="text" maxlength="255" name="officeCountry" id="officeCountry" value="{{ office.country }}" />
</div>
<div>
<label for="officeEmail">Email</label>
<input type="email" maxlength="255" name="officeEmail" id="officeEmail" value="{{ office.email }}" />
</div>
<div>
<label for="officePhone">Telephone</label>
<input type="tel" maxlength="255" name="officePhone" id="officePhone" value="{{ office.phone }}" />
</div>
<div>
<input type="submit" value="Enregistrer" />
</div>
</form>
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment