Compare commits
14 Commits
d048f55ad5
...
c640bdc4d3
Author | SHA1 | Date | |
---|---|---|---|
![]() |
c640bdc4d3 | ||
![]() |
3777067950 | ||
4fc91211f0 | |||
65093ec738 | |||
a47abaabfd | |||
b20dc2e00f | |||
28f63a5363 | |||
b35c19fa5b | |||
b80e2365ad | |||
d464aa9b2d | |||
f098f5beeb | |||
![]() |
3a4e9ce733 | ||
![]() |
8e1e5180dd | ||
0d6b65ef20 |
4
.idea/dataSources.xml
generated
4
.idea/dataSources.xml
generated
@ -1,11 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="DataSourceManagerImpl" format="xml" multifile-model="true">
|
||||
<data-source source="LOCAL" name="hegreetconfort@localhost" uuid="21423ae4-3232-4641-affb-06399f70655a">
|
||||
<data-source source="LOCAL" name="HegreEtConfort@localhost" uuid="21423ae4-3232-4641-affb-06399f70655a">
|
||||
<driver-ref>postgresql</driver-ref>
|
||||
<synchronize>true</synchronize>
|
||||
<jdbc-driver>org.postgresql.Driver</jdbc-driver>
|
||||
<jdbc-url>jdbc:postgresql://localhost:5432/hegreetconfort</jdbc-url>
|
||||
<jdbc-url>jdbc:postgresql://localhost:5433/HegreEtConfort</jdbc-url>
|
||||
<working-dir>$ProjectFileDir$</working-dir>
|
||||
</data-source>
|
||||
</component>
|
||||
|
15
.idea/php.xml
generated
15
.idea/php.xml
generated
@ -10,6 +10,11 @@
|
||||
<option name="highlightLevel" value="WARNING" />
|
||||
<option name="transferred" value="true" />
|
||||
</component>
|
||||
<component name="PhpCodeSniffer">
|
||||
<phpcs_settings>
|
||||
<phpcs_by_interpreter asDefaultInterpreter="true" interpreter_id="4bd9484f-d78e-4315-b899-c673e4a83c70" timeout="30000" />
|
||||
</phpcs_settings>
|
||||
</component>
|
||||
<component name="PhpIncludePathManager">
|
||||
<include_path>
|
||||
<path value="$PROJECT_DIR$/vendor/sebastian/exporter" />
|
||||
@ -146,6 +151,11 @@
|
||||
</include_path>
|
||||
</component>
|
||||
<component name="PhpProjectSharedConfiguration" php_language_level="8.2" />
|
||||
<component name="PhpStan">
|
||||
<PhpStan_settings>
|
||||
<phpstan_by_interpreter asDefaultInterpreter="true" interpreter_id="4bd9484f-d78e-4315-b899-c673e4a83c70" timeout="60000" />
|
||||
</PhpStan_settings>
|
||||
</component>
|
||||
<component name="PhpStanOptionsConfiguration">
|
||||
<option name="transferred" value="true" />
|
||||
</component>
|
||||
@ -154,6 +164,11 @@
|
||||
<PhpUnitSettings configuration_file_path="$PROJECT_DIR$/phpunit.xml.dist" custom_loader_path="$PROJECT_DIR$/vendor/autoload.php" use_configuration_file="true" />
|
||||
</phpunit_settings>
|
||||
</component>
|
||||
<component name="Psalm">
|
||||
<Psalm_settings>
|
||||
<psalm_fixer_by_interpreter asDefaultInterpreter="true" interpreter_id="4bd9484f-d78e-4315-b899-c673e4a83c70" timeout="60000" />
|
||||
</Psalm_settings>
|
||||
</component>
|
||||
<component name="PsalmOptionsConfiguration">
|
||||
<option name="transferred" value="true" />
|
||||
</component>
|
||||
|
59
README.md
Normal file
59
README.md
Normal file
@ -0,0 +1,59 @@
|
||||
|
||||
# 🚀 Application de Gestion Chauffagiste
|
||||
|
||||
## Description
|
||||
Cette application permet de gérer les interventions, les utilisateurs (chauffagistes, secrétaires, admin), les pièces détachées, les véhicules, et les plannings dans une entreprise de chauffagistes.
|
||||
|
||||
## Fonctionnalités principales
|
||||
- **Gestion des utilisateurs** : création de chauffagistes, secrétaires, et admins avec des rôles spécifiques.
|
||||
- **Gestion des interventions** : assignation des chauffagistes, suivi des véhicules et des pièces détachées.
|
||||
- **Gestion des stocks et des véhicules** : gestion des pièces détachées et des véhicules.
|
||||
- **Planning des interventions** : chaque rôle a accès à un planning adapté (chauffagiste, secrétaire, admin).
|
||||
- **Sécurisation par rôles** : accès aux pages limité par rôle (Admin, Secrétaire, Chauffagiste).
|
||||
|
||||
### Précisions pour les rôles :
|
||||
- **Admin** : Accès complet à toutes les fonctionnalités (gestion des utilisateurs, véhicules, stocks, plannings, etc.)
|
||||
- **Secrétaire** : Peut gérer les chauffagistes, les interventions et le planning des chauffagistes, mais **ne peut pas gérer d'autres secrétaires ni les admins**.
|
||||
- **Chauffagiste** : Accède uniquement à ses propres interventions et à son planning.
|
||||
|
||||
## Installation
|
||||
### Prérequis :
|
||||
- PHP 8.x
|
||||
- Composer
|
||||
- Symfony 7.x
|
||||
|
||||
### Étapes d'installation :
|
||||
1. Clonez le projet :
|
||||
```bash
|
||||
git clone https://gitea.btssio-poitiers.fr/sermandm/HegreEtConfort.git
|
||||
```
|
||||
2. Installez les dépendances avec Composer :
|
||||
```bash
|
||||
cd chauffagiste-app
|
||||
composer install
|
||||
```
|
||||
3. Créez la base de données :
|
||||
```bash
|
||||
php bin/console doctrine:database:create
|
||||
```
|
||||
4. Exécutez les migrations pour créer les tables :
|
||||
```bash
|
||||
php bin/console doctrine:migrations:migrate
|
||||
```
|
||||
5. Lancez le serveur Symfony :
|
||||
```bash
|
||||
symfony server:start
|
||||
```
|
||||
|
||||
Accédez ensuite à l'application sur `http://localhost:8000`.
|
||||
|
||||
## Sécurisation des accès
|
||||
Les secrétaires ont accès à toutes les pages **sauf celles concernant d'autres secrétaires et les admins**. Cela est géré par les contrôleurs via la méthode `denyAccessUnlessGranted()` pour vérifier le rôle de l'utilisateur. Par exemple, un secrétaire ne pourra pas modifier un autre secrétaire.
|
||||
|
||||
---
|
||||
|
||||
## Technologies utilisées
|
||||
- Symfony 7.x
|
||||
- Doctrine ORM
|
||||
- Twig
|
||||
- PHP 8.x
|
@ -108,19 +108,19 @@ body {
|
||||
text-align: center;
|
||||
background-color: white;
|
||||
}
|
||||
#vehicule1 {
|
||||
#oui {
|
||||
position: absolute;
|
||||
margin: 30.7% 0 0 25%;
|
||||
}
|
||||
#oui {
|
||||
#oui p {
|
||||
position: absolute;
|
||||
margin: 30.3% 0 0 27%;
|
||||
}
|
||||
#vehicule2 {
|
||||
#non {
|
||||
position: absolute;
|
||||
margin: 30.7% 0 0 32%;
|
||||
}
|
||||
#non {
|
||||
#non p {
|
||||
position: absolute;
|
||||
margin: 30.3% 0 0 34%;
|
||||
}
|
||||
|
64
migrations/Version20250425115854.php
Normal file
64
migrations/Version20250425115854.php
Normal file
@ -0,0 +1,64 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace DoctrineMigrations;
|
||||
|
||||
use Doctrine\DBAL\Schema\Schema;
|
||||
use Doctrine\Migrations\AbstractMigration;
|
||||
|
||||
/**
|
||||
* Auto-generated Migration: Please modify to your needs!
|
||||
*/
|
||||
final class Version20250425115854 extends AbstractMigration
|
||||
{
|
||||
public function getDescription(): string
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
public function up(Schema $schema): void
|
||||
{
|
||||
// this up() migration is auto-generated, please modify it to your needs
|
||||
$this->addSql('CREATE TABLE intervention_stock (intervention_id INT NOT NULL, stock_id INT NOT NULL, PRIMARY KEY(intervention_id, stock_id))');
|
||||
$this->addSql('CREATE INDEX IDX_3E534AE48EAE3863 ON intervention_stock (intervention_id)');
|
||||
$this->addSql('CREATE INDEX IDX_3E534AE4DCD6110 ON intervention_stock (stock_id)');
|
||||
$this->addSql('CREATE TABLE user_skill (utilisateur_id INT NOT NULL, skill_id INT NOT NULL, PRIMARY KEY(utilisateur_id, skill_id))');
|
||||
$this->addSql('CREATE INDEX IDX_BCFF1F2FFB88E14F ON user_skill (utilisateur_id)');
|
||||
$this->addSql('CREATE INDEX IDX_BCFF1F2F5585C142 ON user_skill (skill_id)');
|
||||
$this->addSql('ALTER TABLE intervention_stock ADD CONSTRAINT FK_3E534AE48EAE3863 FOREIGN KEY (intervention_id) REFERENCES intervention (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||
$this->addSql('ALTER TABLE intervention_stock ADD CONSTRAINT FK_3E534AE4DCD6110 FOREIGN KEY (stock_id) REFERENCES stock (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||
$this->addSql('ALTER TABLE user_skill ADD CONSTRAINT FK_BCFF1F2FFB88E14F FOREIGN KEY (utilisateur_id) REFERENCES utilisateur (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||
$this->addSql('ALTER TABLE user_skill ADD CONSTRAINT FK_BCFF1F2F5585C142 FOREIGN KEY (skill_id) REFERENCES skill (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||
$this->addSql('ALTER TABLE intervention ADD user_id INT NOT NULL');
|
||||
$this->addSql('ALTER TABLE intervention ADD fault_id INT NOT NULL');
|
||||
$this->addSql('ALTER TABLE intervention ADD vehicle_id INT DEFAULT NULL');
|
||||
$this->addSql('ALTER TABLE intervention ADD CONSTRAINT FK_D11814ABA76ED395 FOREIGN KEY (user_id) REFERENCES utilisateur (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||
$this->addSql('ALTER TABLE intervention ADD CONSTRAINT FK_D11814AB24171CD3 FOREIGN KEY (fault_id) REFERENCES fault (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||
$this->addSql('ALTER TABLE intervention ADD CONSTRAINT FK_D11814AB545317D1 FOREIGN KEY (vehicle_id) REFERENCES vehicle (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||
$this->addSql('CREATE INDEX IDX_D11814ABA76ED395 ON intervention (user_id)');
|
||||
$this->addSql('CREATE INDEX IDX_D11814AB24171CD3 ON intervention (fault_id)');
|
||||
$this->addSql('CREATE INDEX IDX_D11814AB545317D1 ON intervention (vehicle_id)');
|
||||
}
|
||||
|
||||
public function down(Schema $schema): void
|
||||
{
|
||||
// this down() migration is auto-generated, please modify it to your needs
|
||||
$this->addSql('CREATE SCHEMA public');
|
||||
$this->addSql('ALTER TABLE intervention_stock DROP CONSTRAINT FK_3E534AE48EAE3863');
|
||||
$this->addSql('ALTER TABLE intervention_stock DROP CONSTRAINT FK_3E534AE4DCD6110');
|
||||
$this->addSql('ALTER TABLE user_skill DROP CONSTRAINT FK_BCFF1F2FFB88E14F');
|
||||
$this->addSql('ALTER TABLE user_skill DROP CONSTRAINT FK_BCFF1F2F5585C142');
|
||||
$this->addSql('DROP TABLE intervention_stock');
|
||||
$this->addSql('DROP TABLE user_skill');
|
||||
$this->addSql('ALTER TABLE intervention DROP CONSTRAINT FK_D11814ABA76ED395');
|
||||
$this->addSql('ALTER TABLE intervention DROP CONSTRAINT FK_D11814AB24171CD3');
|
||||
$this->addSql('ALTER TABLE intervention DROP CONSTRAINT FK_D11814AB545317D1');
|
||||
$this->addSql('DROP INDEX IDX_D11814ABA76ED395');
|
||||
$this->addSql('DROP INDEX IDX_D11814AB24171CD3');
|
||||
$this->addSql('DROP INDEX IDX_D11814AB545317D1');
|
||||
$this->addSql('ALTER TABLE intervention DROP user_id');
|
||||
$this->addSql('ALTER TABLE intervention DROP fault_id');
|
||||
$this->addSql('ALTER TABLE intervention DROP vehicle_id');
|
||||
}
|
||||
}
|
@ -12,10 +12,10 @@ class AuthenticationController extends AbstractController
|
||||
#[Route(path: '/', name: 'app_login')]
|
||||
public function login(AuthenticationUtils $authenticationUtils): Response
|
||||
{
|
||||
// get the login error if there is one
|
||||
// Get the login error if there is one
|
||||
$error = $authenticationUtils->getLastAuthenticationError();
|
||||
|
||||
// last username entered by the user
|
||||
// Last username entered by the user
|
||||
$lastUsername = $authenticationUtils->getLastUsername();
|
||||
|
||||
return $this->render('login/index.html.twig', [
|
||||
@ -29,4 +29,4 @@ class AuthenticationController extends AbstractController
|
||||
{
|
||||
throw new \LogicException('This method can be blank - it will be intercepted by the logout key on your firewall.');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,43 +2,89 @@
|
||||
|
||||
namespace App\Controller;
|
||||
|
||||
use App\Repository\InterventionRepository;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Attribute\Route;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
|
||||
#[Route('/calendrier')]
|
||||
class CalendrierController extends AbstractController
|
||||
{
|
||||
#[Route(name: 'app_calendrier_index', methods: ['GET'])]
|
||||
public function index(): Response
|
||||
#[Route('/chauffagiste', name: 'app_calendrier_indexChauffagiste')]
|
||||
public function indexChauffagiste(InterventionRepository $interventionRepository): Response
|
||||
{
|
||||
return $this->render('calendrier/index.html.twig', [
|
||||
'controller_name' => 'CalendrierController',
|
||||
// Vérification : seul le chauffagiste connecté peut voir son propre calendrier
|
||||
$this->denyAccessUnlessGranted('ROLE_CHAUFFAGISTE');
|
||||
|
||||
// Récupérer les interventions du chauffagiste connecté
|
||||
$interventions = $interventionRepository->findByUser($this->getUser());
|
||||
|
||||
// Préparer les événements pour FullCalendar
|
||||
$events = [];
|
||||
foreach ($interventions as $intervention) {
|
||||
$events[] = [
|
||||
'title' => $intervention->getTitle(),
|
||||
'start' => $intervention->getStartDate()->format('Y-m-d H:i:s'),
|
||||
'end' => $intervention->getEndDate()->format('Y-m-d H:i:s'),
|
||||
'description' => $intervention->getDescription(),
|
||||
];
|
||||
}
|
||||
|
||||
// Passer les événements à la vue
|
||||
return $this->render('calendrier/indexChauffagiste.html.twig', [
|
||||
'events' => json_encode($events),
|
||||
]);
|
||||
}
|
||||
|
||||
#[Route('/calendrier/secretaire', name: 'calendrier_index_secretaire')]
|
||||
public function indexSecretaire(): Response
|
||||
#[Route('/secretaire', name: 'app_calendrier_indexSecretaire')]
|
||||
public function indexSecretaire(InterventionRepository $interventionRepository): Response
|
||||
{
|
||||
return $this->render('calendrier/indexSecretaire.html.twig');
|
||||
// Vérification : seul le secrétaire peut accéder à ce calendrier
|
||||
$this->denyAccessUnlessGranted('ROLE_SECRETAIRE');
|
||||
|
||||
// Récupérer toutes les interventions de tous les chauffagistes
|
||||
$interventions = $interventionRepository->findAll();
|
||||
|
||||
// Préparer les événements pour FullCalendar
|
||||
$events = [];
|
||||
foreach ($interventions as $intervention) {
|
||||
$events[] = [
|
||||
'title' => $intervention->getTitle(),
|
||||
'start' => $intervention->getStartDate()->format('Y-m-d H:i:s'),
|
||||
'end' => $intervention->getEndDate()->format('Y-m-d H:i:s'),
|
||||
'description' => $intervention->getDescription(),
|
||||
];
|
||||
}
|
||||
|
||||
// Passer les événements à la vue
|
||||
return $this->render('calendrier/indexSecretaire.html.twig', [
|
||||
'events' => json_encode($events),
|
||||
]);
|
||||
}
|
||||
|
||||
#[Route('/calendrier/chauffagiste', name: 'calendrier_index_chauffagiste')]
|
||||
public function indexChauffagiste(): Response
|
||||
#[Route('/admin', name: 'app_calendrier_index')]
|
||||
public function indexAdmin(InterventionRepository $interventionRepository): Response
|
||||
{
|
||||
return $this->render('calendrier/indexChauffagiste.html.twig');
|
||||
// Vérification : seul un admin peut accéder à ce calendrier
|
||||
$this->denyAccessUnlessGranted('ROLE_ADMIN');
|
||||
|
||||
// Récupérer toutes les interventions de tous les chauffagistes
|
||||
$interventions = $interventionRepository->findAll();
|
||||
|
||||
// Préparer les événements pour FullCalendar
|
||||
$events = [];
|
||||
foreach ($interventions as $intervention) {
|
||||
$events[] = [
|
||||
'title' => $intervention->getTitle(),
|
||||
'start' => $intervention->getStartDate()->format('Y-m-d H:i:s'),
|
||||
'end' => $intervention->getEndDate()->format('Y-m-d H:i:s'),
|
||||
'description' => $intervention->getDescription(),
|
||||
];
|
||||
}
|
||||
|
||||
// Passer les événements à la vue
|
||||
return $this->render('calendrier/index.html.twig', [
|
||||
'events' => json_encode($events),
|
||||
]);
|
||||
}
|
||||
|
||||
// créer intervention : secretaire + admin
|
||||
// créer un nouveau rdv
|
||||
// modifier un rdv
|
||||
// supprimer un rdv
|
||||
// choisir un chauffagiste
|
||||
// deconnexion
|
||||
|
||||
// créer intervention : chauffagiste
|
||||
// modifier un rdv
|
||||
// deconnexion
|
||||
|
||||
// quand on créer une rdv, alors cela nous redirige vers la page intervention
|
||||
}
|
||||
|
@ -4,26 +4,28 @@ namespace App\Controller;
|
||||
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
use Symfony\Component\Routing\Attribute\Route;
|
||||
|
||||
class DashboardController extends AbstractController
|
||||
{
|
||||
#[Route('/admin/dashboard', name: 'admin_dashboard')]
|
||||
public function admin(): Response
|
||||
{
|
||||
$this->denyAccessUnlessGranted('ROLE_ADMIN');
|
||||
return $this->render('dashboard/admin.html.twig');
|
||||
}
|
||||
|
||||
#[Route('/secretaire/dashboard', name: 'secretaire_dashboard')]
|
||||
public function secretaire(): Response
|
||||
{
|
||||
$this->denyAccessUnlessGranted('ROLE_SECRETAIRE');
|
||||
return $this->render('dashboard/secretaire.html.twig');
|
||||
}
|
||||
|
||||
#[Route('/chauffagiste/dashboard', name: 'chauffagiste_dashboard')]
|
||||
public function chauffagiste(): Response
|
||||
{
|
||||
$this->denyAccessUnlessGranted('ROLE_CHAUFFAGISTE');
|
||||
return $this->render('dashboard/chauffagiste.html.twig');
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -17,8 +17,13 @@ final class FaultController extends AbstractController
|
||||
#[Route(name: 'app_fault_index', methods: ['GET'])]
|
||||
public function index(FaultRepository $faultRepository): Response
|
||||
{
|
||||
// Filtrage des pannes : un chauffagiste ne peut voir que ses pannes
|
||||
$faults = $this->isGranted('ROLE_CHAUFFAGISTE')
|
||||
? $faultRepository->findByUser($this->getUser()) // Filtre les pannes par utilisateur
|
||||
: $faultRepository->findAll(); // Admins voient toutes les pannes
|
||||
|
||||
return $this->render('fault/index.html.twig', [
|
||||
'faults' => $faultRepository->findAll(),
|
||||
'faults' => $faults,
|
||||
]);
|
||||
}
|
||||
|
||||
@ -30,6 +35,11 @@ final class FaultController extends AbstractController
|
||||
$form->handleRequest($request);
|
||||
|
||||
if ($form->isSubmitted() && $form->isValid()) {
|
||||
// Associe la panne à un chauffagiste si c'est un chauffagiste
|
||||
if ($this->isGranted('ROLE_CHAUFFAGISTE')) {
|
||||
$fault->setUser($this->getUser());
|
||||
}
|
||||
|
||||
$entityManager->persist($fault);
|
||||
$entityManager->flush();
|
||||
|
||||
@ -45,6 +55,11 @@ final class FaultController extends AbstractController
|
||||
#[Route('/{id}', name: 'app_fault_show', methods: ['GET'])]
|
||||
public function show(Fault $fault): Response
|
||||
{
|
||||
// Un chauffagiste ne peut voir que ses pannes
|
||||
if ($this->isGranted('ROLE_CHAUFFAGISTE') && $fault->getUser() !== $this->getUser()) {
|
||||
throw $this->createAccessDeniedException('Vous ne pouvez pas voir cette panne.');
|
||||
}
|
||||
|
||||
return $this->render('fault/show.html.twig', [
|
||||
'fault' => $fault,
|
||||
]);
|
||||
@ -53,6 +68,11 @@ final class FaultController extends AbstractController
|
||||
#[Route('/{id}/edit', name: 'app_fault_edit', methods: ['GET', 'POST'])]
|
||||
public function edit(Request $request, Fault $fault, EntityManagerInterface $entityManager): Response
|
||||
{
|
||||
// Un chauffagiste ne peut modifier que ses propres pannes
|
||||
if ($this->isGranted('ROLE_CHAUFFAGISTE') && $fault->getUser() !== $this->getUser()) {
|
||||
throw $this->createAccessDeniedException('Vous ne pouvez pas modifier cette panne.');
|
||||
}
|
||||
|
||||
$form = $this->createForm(FaultType::class, $fault);
|
||||
$form->handleRequest($request);
|
||||
|
||||
@ -71,7 +91,12 @@ final class FaultController extends AbstractController
|
||||
#[Route('/{id}', name: 'app_fault_delete', methods: ['POST'])]
|
||||
public function delete(Request $request, Fault $fault, EntityManagerInterface $entityManager): Response
|
||||
{
|
||||
if ($this->isCsrfTokenValid('delete'.$fault->getId(), $request->getPayload()->getString('_token'))) {
|
||||
// Un chauffagiste ne peut supprimer que ses propres pannes
|
||||
if ($this->isGranted('ROLE_CHAUFFAGISTE') && $fault->getUser() !== $this->getUser()) {
|
||||
throw $this->createAccessDeniedException('Vous ne pouvez pas supprimer cette panne.');
|
||||
}
|
||||
|
||||
if ($this->isCsrfTokenValid('delete'.$fault->getId(), $request->get('csrf_token'))) {
|
||||
$entityManager->remove($fault);
|
||||
$entityManager->flush();
|
||||
}
|
||||
|
@ -17,8 +17,16 @@ final class InterventionController extends AbstractController
|
||||
#[Route(name: 'app_intervention_index', methods: ['GET'])]
|
||||
public function index(InterventionRepository $interventionRepository): Response
|
||||
{
|
||||
// Vérifier si l'utilisateur est un chauffagiste, pour filtrer ses interventions
|
||||
if ($this->isGranted('ROLE_CHAUFFAGISTE')) {
|
||||
$interventions = $interventionRepository->findByUser($this->getUser()); // On filtre par utilisateur connecté
|
||||
} else {
|
||||
// Les autres rôles (admin) peuvent voir toutes les interventions
|
||||
$interventions = $interventionRepository->findAll();
|
||||
}
|
||||
|
||||
return $this->render('intervention/index.html.twig', [
|
||||
'interventions' => $interventionRepository->findAll(),
|
||||
'interventions' => $interventions,
|
||||
]);
|
||||
}
|
||||
|
||||
@ -30,6 +38,11 @@ final class InterventionController extends AbstractController
|
||||
$form->handleRequest($request);
|
||||
|
||||
if ($form->isSubmitted() && $form->isValid()) {
|
||||
// Si l'utilisateur est un chauffagiste, on associe l'intervention à lui
|
||||
if ($this->isGranted('ROLE_CHAUFFAGISTE')) {
|
||||
$intervention->setUser($this->getUser());
|
||||
}
|
||||
|
||||
$entityManager->persist($intervention);
|
||||
$entityManager->flush();
|
||||
|
||||
@ -45,6 +58,11 @@ final class InterventionController extends AbstractController
|
||||
#[Route('/{id}', name: 'app_intervention_show', methods: ['GET'])]
|
||||
public function show(Intervention $intervention): Response
|
||||
{
|
||||
// Vérifier si l'utilisateur peut voir cette intervention (chauffagiste ne voit que ses interventions)
|
||||
if ($this->isGranted('ROLE_CHAUFFAGISTE') && $intervention->getUser() !== $this->getUser()) {
|
||||
throw $this->createAccessDeniedException('Vous ne pouvez pas voir cette intervention.');
|
||||
}
|
||||
|
||||
return $this->render('intervention/show.html.twig', [
|
||||
'intervention' => $intervention,
|
||||
]);
|
||||
@ -53,6 +71,11 @@ final class InterventionController extends AbstractController
|
||||
#[Route('/{id}/edit', name: 'app_intervention_edit', methods: ['GET', 'POST'])]
|
||||
public function edit(Request $request, Intervention $intervention, EntityManagerInterface $entityManager): Response
|
||||
{
|
||||
// Vérification de sécurité : un chauffagiste ne peut modifier que ses propres interventions
|
||||
if ($this->isGranted('ROLE_CHAUFFAGISTE') && $intervention->getUser() !== $this->getUser()) {
|
||||
throw $this->createAccessDeniedException('Vous ne pouvez pas modifier cette intervention.');
|
||||
}
|
||||
|
||||
$form = $this->createForm(InterventionType::class, $intervention);
|
||||
$form->handleRequest($request);
|
||||
|
||||
@ -71,7 +94,12 @@ final class InterventionController extends AbstractController
|
||||
#[Route('/{id}', name: 'app_intervention_delete', methods: ['POST'])]
|
||||
public function delete(Request $request, Intervention $intervention, EntityManagerInterface $entityManager): Response
|
||||
{
|
||||
if ($this->isCsrfTokenValid('delete'.$intervention->getId(), $request->getPayload()->getString('_token'))) {
|
||||
// Vérification de sécurité : un chauffagiste ne peut supprimer que ses propres interventions
|
||||
if ($this->isGranted('ROLE_CHAUFFAGISTE') && $intervention->getUser() !== $this->getUser()) {
|
||||
throw $this->createAccessDeniedException('Vous ne pouvez pas supprimer cette intervention.');
|
||||
}
|
||||
|
||||
if ($this->isCsrfTokenValid('delete'.$intervention->getId(), $request->get('csrf_token'))) {
|
||||
$entityManager->remove($intervention);
|
||||
$entityManager->flush();
|
||||
}
|
||||
|
@ -17,6 +17,7 @@ final class SkillController extends AbstractController
|
||||
#[Route(name: 'app_skill_index', methods: ['GET'])]
|
||||
public function index(SkillRepository $skillRepository): Response
|
||||
{
|
||||
$this->denyAccessUnlessGranted('ROLE_ADMIN');
|
||||
return $this->render('skill/admin.html.twig', [
|
||||
'skills' => $skillRepository->findAll(),
|
||||
]);
|
||||
@ -25,6 +26,7 @@ final class SkillController extends AbstractController
|
||||
#[Route('/new', name: 'app_skill_new', methods: ['GET', 'POST'])]
|
||||
public function new(Request $request, EntityManagerInterface $entityManager): Response
|
||||
{
|
||||
$this->denyAccessUnlessGranted('ROLE_ADMIN');
|
||||
$skill = new Skill();
|
||||
$form = $this->createForm(SkillType::class, $skill);
|
||||
$form->handleRequest($request);
|
||||
@ -53,6 +55,7 @@ final class SkillController extends AbstractController
|
||||
#[Route('/{id}/edit', name: 'app_skill_edit', methods: ['GET', 'POST'])]
|
||||
public function edit(Request $request, Skill $skill, EntityManagerInterface $entityManager): Response
|
||||
{
|
||||
$this->denyAccessUnlessGranted('ROLE_ADMIN');
|
||||
$form = $this->createForm(SkillType::class, $skill);
|
||||
$form->handleRequest($request);
|
||||
|
||||
@ -71,7 +74,8 @@ final class SkillController extends AbstractController
|
||||
#[Route('/{id}', name: 'app_skill_delete', methods: ['POST'])]
|
||||
public function delete(Request $request, Skill $skill, EntityManagerInterface $entityManager): Response
|
||||
{
|
||||
if ($this->isCsrfTokenValid('delete'.$skill->getId(), $request->getPayload()->getString('_token'))) {
|
||||
$this->denyAccessUnlessGranted('ROLE_ADMIN');
|
||||
if ($this->isCsrfTokenValid('delete'.$skill->getId(), $request->get('csrf_token'))) {
|
||||
$entityManager->remove($skill);
|
||||
$entityManager->flush();
|
||||
}
|
||||
|
@ -53,6 +53,11 @@ final class StockController extends AbstractController
|
||||
#[Route('/{id}/edit', name: 'app_stock_edit', methods: ['GET', 'POST'])]
|
||||
public function edit(Request $request, Stock $stock, EntityManagerInterface $entityManager): Response
|
||||
{
|
||||
// Si un chauffagiste essaie de modifier un stock d'admin
|
||||
if ($this->isGranted('ROLE_CHAUFFAGISTE')) {
|
||||
throw $this->createAccessDeniedException('Vous ne pouvez pas modifier ce stock.');
|
||||
}
|
||||
|
||||
$form = $this->createForm(StockType::class, $stock);
|
||||
$form->handleRequest($request);
|
||||
|
||||
@ -71,7 +76,7 @@ final class StockController extends AbstractController
|
||||
#[Route('/{id}', name: 'app_stock_delete', methods: ['POST'])]
|
||||
public function delete(Request $request, Stock $stock, EntityManagerInterface $entityManager): Response
|
||||
{
|
||||
if ($this->isCsrfTokenValid('delete'.$stock->getId(), $request->getPayload()->getString('_token'))) {
|
||||
if ($this->isCsrfTokenValid('delete'.$stock->getId(), $request->get('csrf_token'))) {
|
||||
$entityManager->remove($stock);
|
||||
$entityManager->flush();
|
||||
}
|
||||
|
@ -10,12 +10,12 @@ use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface;
|
||||
use Symfony\Component\Routing\Attribute\Route;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
|
||||
#[Route('/user')]
|
||||
final class UserController extends AbstractController
|
||||
{
|
||||
#[Route(name: 'app_user_index', methods: ['GET'])]
|
||||
// Route pour afficher tous les utilisateurs
|
||||
#[Route('/user', name: 'app_user_index', methods: ['GET'])]
|
||||
public function index(UserRepository $userRepository): Response
|
||||
{
|
||||
return $this->render('user/index.html.twig', [
|
||||
@ -23,7 +23,8 @@ final class UserController extends AbstractController
|
||||
]);
|
||||
}
|
||||
|
||||
#[Route('/new', name: 'app_user_new', methods: ['GET', 'POST'])]
|
||||
// Route pour créer un nouvel utilisateur
|
||||
#[Route('/user/new', name: 'app_user_new', methods: ['GET', 'POST'])]
|
||||
public function new(Request $request, EntityManagerInterface $entityManager, UserPasswordHasherInterface $passwordHasher): Response
|
||||
{
|
||||
$user = new Utilisateur();
|
||||
@ -48,7 +49,8 @@ final class UserController extends AbstractController
|
||||
]);
|
||||
}
|
||||
|
||||
#[Route('/{id}', name: 'app_user_show', methods: ['GET'])]
|
||||
// Route pour afficher un utilisateur spécifique
|
||||
#[Route('/user/{id}', name: 'app_user_show', methods: ['GET'])]
|
||||
public function show(Utilisateur $user): Response
|
||||
{
|
||||
return $this->render('user/show.html.twig', [
|
||||
@ -56,9 +58,21 @@ final class UserController extends AbstractController
|
||||
]);
|
||||
}
|
||||
|
||||
#[Route('/{id}/edit', name: 'app_user_edit', methods: ['GET', 'POST'])]
|
||||
// Route pour modifier un utilisateur spécifique
|
||||
#[Route('/user/{id}/edit', name: 'app_user_edit', methods: ['GET', 'POST'])]
|
||||
public function edit(Request $request, Utilisateur $user, EntityManagerInterface $entityManager): Response
|
||||
{
|
||||
if ($this->isGranted('ROLE_SECRETAIRE') && $user->hasRole('ROLE_SECRETAIRE')) {
|
||||
throw $this->createAccessDeniedException('Vous ne pouvez pas modifier un autre secrétaire.');
|
||||
}
|
||||
|
||||
if ($this->isGranted('ROLE_CHAUFFAGISTE') && ($user->hasRole('ROLE_CHAUFFAGISTE') || $user->hasRole('ROLE_SECRETAIRE'))) {
|
||||
throw $this->createAccessDeniedException('Vous ne pouvez pas modifier un admin.');
|
||||
}
|
||||
|
||||
// On s'assure que seul un admin peut éditer un autre admin
|
||||
$this->denyAccessUnlessGranted('ROLE_ADMIN');
|
||||
|
||||
$form = $this->createForm(UserType::class, $user);
|
||||
$form->handleRequest($request);
|
||||
|
||||
@ -74,10 +88,24 @@ final class UserController extends AbstractController
|
||||
]);
|
||||
}
|
||||
|
||||
#[Route('/{id}', name: 'app_user_delete', methods: ['POST'])]
|
||||
// Route pour supprimer un utilisateur spécifique
|
||||
#[Route('/user/{id}', name: 'app_user_delete', methods: ['POST'])]
|
||||
public function delete(Request $request, Utilisateur $user, EntityManagerInterface $entityManager): Response
|
||||
{
|
||||
if ($this->isCsrfTokenValid('delete'.$user->getId(), $request->getPayload()->getString('_token'))) {
|
||||
// Si l'utilisateur est un secrétaire et qu'il essaie de supprimer un autre secrétaire
|
||||
if ($this->isGranted('ROLE_SECRETAIRE') && $user->hasRole('ROLE_SECRETAIRE')) {
|
||||
throw $this->createAccessDeniedException('Vous ne pouvez pas supprimer un autre secrétaire ou un administrateur.');
|
||||
}
|
||||
|
||||
// Si l'utilisateur est un chauffagiste et qu'il essaie de supprimer un admin
|
||||
if ($this->isGranted('ROLE_CHAUFFAGISTE') && ($user->hasRole('ROLE_SECRETAIRE') || $user->hasRole('ROLE_CHAUFFAGISTE'))) {
|
||||
throw $this->createAccessDeniedException('Vous ne pouvez pas supprimer un utilisateur.');
|
||||
}
|
||||
|
||||
// On s'assure que seul un admin peut supprimer un autre admin
|
||||
$this->denyAccessUnlessGranted("ROLE_ADMIN");
|
||||
|
||||
if ($this->isCsrfTokenValid('delete' . $user->getId(), $request->get('csrf_token'))) {
|
||||
$entityManager->remove($user);
|
||||
$entityManager->flush();
|
||||
}
|
||||
|
@ -17,8 +17,13 @@ final class VehicleController extends AbstractController
|
||||
#[Route(name: 'app_vehicle_index', methods: ['GET'])]
|
||||
public function index(VehicleRepository $vehicleRepository): Response
|
||||
{
|
||||
// Admin peut voir tous les véhicules, chauffagiste ne peut voir que ses véhicules
|
||||
$vehicles = $this->isGranted('ROLE_CHAUFFAGISTE')
|
||||
? $vehicleRepository->findByUser($this->getUser()) // Filtre les véhicules par utilisateur
|
||||
: $vehicleRepository->findAll(); // Les admins voient tout
|
||||
|
||||
return $this->render('vehicle/index.html.twig', [
|
||||
'vehicles' => $vehicleRepository->findAll(),
|
||||
'vehicles' => $vehicles,
|
||||
]);
|
||||
}
|
||||
|
||||
@ -30,6 +35,11 @@ final class VehicleController extends AbstractController
|
||||
$form->handleRequest($request);
|
||||
|
||||
if ($form->isSubmitted() && $form->isValid()) {
|
||||
// Si l'utilisateur est un chauffagiste, on associe le véhicule à lui
|
||||
if ($this->isGranted('ROLE_CHAUFFAGISTE')) {
|
||||
$vehicle->setUser($this->getUser());
|
||||
}
|
||||
|
||||
$entityManager->persist($vehicle);
|
||||
$entityManager->flush();
|
||||
|
||||
@ -45,6 +55,11 @@ final class VehicleController extends AbstractController
|
||||
#[Route('/{id}', name: 'app_vehicle_show', methods: ['GET'])]
|
||||
public function show(Vehicle $vehicle): Response
|
||||
{
|
||||
// Si l'utilisateur est un chauffagiste et essaie de voir un véhicule d'un autre chauffagiste, on bloque
|
||||
if ($this->isGranted('ROLE_CHAUFFAGISTE') && $vehicle->getUser() !== $this->getUser()) {
|
||||
throw $this->createAccessDeniedException('Vous ne pouvez pas voir ce véhicule.');
|
||||
}
|
||||
|
||||
return $this->render('vehicle/show.html.twig', [
|
||||
'vehicle' => $vehicle,
|
||||
]);
|
||||
@ -53,6 +68,11 @@ final class VehicleController extends AbstractController
|
||||
#[Route('/{id}/edit', name: 'app_vehicle_edit', methods: ['GET', 'POST'])]
|
||||
public function edit(Request $request, Vehicle $vehicle, EntityManagerInterface $entityManager): Response
|
||||
{
|
||||
// Vérifier si un chauffagiste essaie de modifier un véhicule d'un autre chauffagiste
|
||||
if ($this->isGranted('ROLE_CHAUFFAGISTE') && $vehicle->getUser() !== $this->getUser()) {
|
||||
throw $this->createAccessDeniedException('Vous ne pouvez pas modifier ce véhicule.');
|
||||
}
|
||||
|
||||
$form = $this->createForm(VehicleType::class, $vehicle);
|
||||
$form->handleRequest($request);
|
||||
|
||||
@ -71,7 +91,12 @@ final class VehicleController extends AbstractController
|
||||
#[Route('/{id}', name: 'app_vehicle_delete', methods: ['POST'])]
|
||||
public function delete(Request $request, Vehicle $vehicle, EntityManagerInterface $entityManager): Response
|
||||
{
|
||||
if ($this->isCsrfTokenValid('delete'.$vehicle->getId(), $request->getPayload()->getString('_token'))) {
|
||||
// Vérification de sécurité : un chauffagiste ne peut supprimer un véhicule d'un autre chauffagiste
|
||||
if ($this->isGranted('ROLE_CHAUFFAGISTE') && $vehicle->getUser() !== $this->getUser()) {
|
||||
throw $this->createAccessDeniedException('Vous ne pouvez pas supprimer ce véhicule.');
|
||||
}
|
||||
|
||||
if ($this->isCsrfTokenValid('delete'.$vehicle->getId(), $request->get('csrf_token'))) {
|
||||
$entityManager->remove($vehicle);
|
||||
$entityManager->flush();
|
||||
}
|
||||
|
@ -32,7 +32,6 @@ class Fault
|
||||
public function setWording(string $Wording): static
|
||||
{
|
||||
$this->Wording = $Wording;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
@ -44,7 +43,6 @@ class Fault
|
||||
public function setDescription(string $Description): static
|
||||
{
|
||||
$this->Description = $Description;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
|
@ -5,6 +5,8 @@ namespace App\Entity;
|
||||
use App\Repository\InterventionRepository;
|
||||
use Doctrine\DBAL\Types\Types;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
|
||||
#[ORM\Entity(repositoryClass: InterventionRepository::class)]
|
||||
class Intervention
|
||||
@ -29,6 +31,32 @@ class Intervention
|
||||
#[ORM\Column(length: 255)]
|
||||
private ?string $Status = null;
|
||||
|
||||
<<<<<<< HEAD
|
||||
// #[ORM\ManyToOne(targetEntity: Vehicule::class)]
|
||||
// private ?Vehicule $vehicule = null;
|
||||
|
||||
=======
|
||||
#[ORM\ManyToOne(inversedBy: 'interventions')]
|
||||
#[ORM\JoinColumn(nullable: false)]
|
||||
private ?Utilisateur $user = null;
|
||||
|
||||
#[ORM\ManyToOne]
|
||||
#[ORM\JoinColumn(nullable: false)]
|
||||
private ?Fault $fault = null;
|
||||
|
||||
#[ORM\ManyToOne(inversedBy: 'intervention')]
|
||||
private ?Vehicle $vehicle = null;
|
||||
|
||||
#[ORM\ManyToMany(targetEntity: Stock::class)]
|
||||
#[ORM\JoinTable(name: "intervention_stock")]
|
||||
private Collection $stocks;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->stocks = new ArrayCollection();
|
||||
}
|
||||
>>>>>>> 4fc91211f0d814453d2ed97caf6a1d94d709058e
|
||||
|
||||
public function getId(): ?int
|
||||
{
|
||||
return $this->id;
|
||||
@ -42,7 +70,6 @@ class Intervention
|
||||
public function setWording(string $Wording): static
|
||||
{
|
||||
$this->Wording = $Wording;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
@ -54,7 +81,6 @@ class Intervention
|
||||
public function setTimestamp(\DateTimeInterface $Timestamp): static
|
||||
{
|
||||
$this->Timestamp = $Timestamp;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
@ -66,7 +92,6 @@ class Intervention
|
||||
public function setDescription(string $Description): static
|
||||
{
|
||||
$this->Description = $Description;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
@ -78,7 +103,6 @@ class Intervention
|
||||
public function setAddress(string $Address): static
|
||||
{
|
||||
$this->Address = $Address;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
@ -90,7 +114,58 @@ class Intervention
|
||||
public function setStatus(string $Status): static
|
||||
{
|
||||
$this->Status = $Status;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getUser(): ?Utilisateur
|
||||
{
|
||||
return $this->user;
|
||||
}
|
||||
|
||||
public function setUser(?Utilisateur $user): static
|
||||
{
|
||||
$this->user = $user;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getFault(): ?Fault
|
||||
{
|
||||
return $this->fault;
|
||||
}
|
||||
|
||||
public function setFault(?Fault $fault): static
|
||||
{
|
||||
$this->fault = $fault;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getVehicle(): ?Vehicle
|
||||
{
|
||||
return $this->vehicle;
|
||||
}
|
||||
|
||||
public function setVehicle(?Vehicle $vehicle): static
|
||||
{
|
||||
$this->vehicle = $vehicle;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getStocks(): Collection
|
||||
{
|
||||
return $this->stocks;
|
||||
}
|
||||
|
||||
public function addStock(Stock $stock): static
|
||||
{
|
||||
if (!$this->stocks->contains($stock)) {
|
||||
$this->stocks[] = $stock;
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function removeStock(Stock $stock): static
|
||||
{
|
||||
$this->stocks->removeElement($stock);
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
|
@ -4,6 +4,8 @@ namespace App\Entity;
|
||||
|
||||
use App\Repository\SkillRepository;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
|
||||
#[ORM\Entity(repositoryClass: SkillRepository::class)]
|
||||
class Skill
|
||||
@ -19,6 +21,14 @@ class Skill
|
||||
#[ORM\Column(length: 255)]
|
||||
private ?string $Description = null;
|
||||
|
||||
#[ORM\ManyToMany(mappedBy: 'skills', targetEntity: Utilisateur::class)]
|
||||
private Collection $users;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->users = new ArrayCollection();
|
||||
}
|
||||
|
||||
public function getId(): ?int
|
||||
{
|
||||
return $this->id;
|
||||
@ -32,7 +42,6 @@ class Skill
|
||||
public function setWording(string $Wording): static
|
||||
{
|
||||
$this->Wording = $Wording;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
@ -44,7 +53,28 @@ class Skill
|
||||
public function setDescription(string $Description): static
|
||||
{
|
||||
$this->Description = $Description;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getUsers(): Collection
|
||||
{
|
||||
return $this->users;
|
||||
}
|
||||
|
||||
public function addUser(Utilisateur $user): static
|
||||
{
|
||||
if (!$this->users->contains($user)) {
|
||||
$this->users[] = $user;
|
||||
$user->addSkill($this);
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function removeUser(Utilisateur $user): static
|
||||
{
|
||||
if ($this->users->removeElement($user)) {
|
||||
$user->removeSkill($this);
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
|
@ -4,6 +4,8 @@ namespace App\Entity;
|
||||
|
||||
use App\Repository\StockRepository;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
|
||||
#[ORM\Entity(repositoryClass: StockRepository::class)]
|
||||
class Stock
|
||||
@ -22,6 +24,14 @@ class Stock
|
||||
#[ORM\Column(length: 255)]
|
||||
private ?string $Quantity = null;
|
||||
|
||||
#[ORM\ManyToMany(mappedBy: 'stocks', targetEntity: Intervention::class)]
|
||||
private Collection $interventions;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->interventions = new ArrayCollection();
|
||||
}
|
||||
|
||||
public function getId(): ?int
|
||||
{
|
||||
return $this->id;
|
||||
@ -35,7 +45,6 @@ class Stock
|
||||
public function setWording(string $Wording): static
|
||||
{
|
||||
$this->Wording = $Wording;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
@ -47,7 +56,6 @@ class Stock
|
||||
public function setDescription(string $Description): static
|
||||
{
|
||||
$this->Description = $Description;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
@ -59,7 +67,28 @@ class Stock
|
||||
public function setQuantity(string $Quantity): static
|
||||
{
|
||||
$this->Quantity = $Quantity;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getInterventions(): Collection
|
||||
{
|
||||
return $this->interventions;
|
||||
}
|
||||
|
||||
public function addIntervention(Intervention $intervention): static
|
||||
{
|
||||
if (!$this->interventions->contains($intervention)) {
|
||||
$this->interventions[] = $intervention;
|
||||
$intervention->addStock($this);
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function removeIntervention(Intervention $intervention): static
|
||||
{
|
||||
if ($this->interventions->removeElement($intervention)) {
|
||||
$intervention->removeStock($this);
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
|
@ -5,6 +5,8 @@ namespace App\Entity;
|
||||
use App\Repository\UserRepository;
|
||||
use Doctrine\DBAL\Types\Types;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
use Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface;
|
||||
use Symfony\Component\Security\Core\User\UserInterface;
|
||||
|
||||
@ -32,8 +34,118 @@ class Utilisateur implements UserInterface, PasswordAuthenticatedUserInterface
|
||||
#[ORM\Column(length: 255)]
|
||||
private ?string $Phone = null;
|
||||
|
||||
#[ORM\Column]
|
||||
private array $roles = [];
|
||||
|
||||
#[ORM\Column]
|
||||
private ?string $password = null;
|
||||
|
||||
private ?string $plainPassword = null;
|
||||
|
||||
#[ORM\OneToMany(mappedBy: 'user', targetEntity: Intervention::class)]
|
||||
private Collection $interventions;
|
||||
|
||||
#[ORM\ManyToMany(targetEntity: Skill::class)]
|
||||
#[ORM\JoinTable(name: "user_skill")]
|
||||
private Collection $skills;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->interventions = new ArrayCollection();
|
||||
$this->skills = new ArrayCollection();
|
||||
}
|
||||
|
||||
public function getId(): ?int
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
public function getEmail(): ?string
|
||||
{
|
||||
return $this->email;
|
||||
}
|
||||
|
||||
public function setEmail(string $email): static
|
||||
{
|
||||
$this->email = $email;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getFirstName(): ?string
|
||||
{
|
||||
return $this->FirstName;
|
||||
}
|
||||
|
||||
public function setFirstName(?string $FirstName): void
|
||||
{
|
||||
$this->FirstName = $FirstName;
|
||||
}
|
||||
|
||||
public function getLastName(): ?string
|
||||
{
|
||||
return $this->LastName;
|
||||
}
|
||||
|
||||
public function setLastName(?string $LastName): void
|
||||
{
|
||||
$this->LastName = $LastName;
|
||||
}
|
||||
|
||||
public function getBirthDate(): ?\DateTimeInterface
|
||||
{
|
||||
return $this->BirthDate;
|
||||
}
|
||||
|
||||
public function setBirthDate(?\DateTimeInterface $BirthDate): void
|
||||
{
|
||||
$this->BirthDate = $BirthDate;
|
||||
}
|
||||
|
||||
public function getPhone(): ?string
|
||||
{
|
||||
return $this->Phone;
|
||||
}
|
||||
|
||||
public function setPhone(?string $Phone): void
|
||||
{
|
||||
$this->Phone = $Phone;
|
||||
}
|
||||
|
||||
public function getRoles(): array
|
||||
{
|
||||
$roles = $this->roles;
|
||||
$roles[] = 'ROLE_USER';
|
||||
|
||||
return array_unique($roles);
|
||||
}
|
||||
|
||||
public function setRoles(array $roles): static
|
||||
{
|
||||
$this->roles = $roles;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getPassword(): ?string
|
||||
{
|
||||
return $this->password;
|
||||
}
|
||||
|
||||
public function setPassword(string $password): static
|
||||
{
|
||||
$this->password = $password;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getUserIdentifier(): string
|
||||
{
|
||||
return (string) $this->email;
|
||||
}
|
||||
|
||||
public function eraseCredentials(): void
|
||||
{
|
||||
$this->plainPassword = null;
|
||||
}
|
||||
|
||||
public function getPlainPassword(): ?string
|
||||
{
|
||||
return $this->plainPassword;
|
||||
@ -44,154 +156,46 @@ class Utilisateur implements UserInterface, PasswordAuthenticatedUserInterface
|
||||
$this->plainPassword = $plainPassword;
|
||||
}
|
||||
|
||||
/**
|
||||
* @var list<string> The user roles
|
||||
*/
|
||||
#[ORM\Column]
|
||||
private array $roles = [];
|
||||
|
||||
/**
|
||||
* @var string The hashed password
|
||||
*/
|
||||
#[ORM\Column]
|
||||
private ?string $password = null;
|
||||
|
||||
public function getId(): ?int
|
||||
public function getInterventions(): Collection
|
||||
{
|
||||
return $this->id;
|
||||
return $this->interventions;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \DateTimeInterface|null
|
||||
*/
|
||||
public function getBirthDate(): ?\DateTimeInterface
|
||||
public function addIntervention(Intervention $intervention): static
|
||||
{
|
||||
return $this->BirthDate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \DateTimeInterface|null $BirthDate
|
||||
*/
|
||||
public function setBirthDate(?\DateTimeInterface $BirthDate): void
|
||||
{
|
||||
$this->BirthDate = $BirthDate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string|null
|
||||
*/
|
||||
public function getLastName(): ?string
|
||||
{
|
||||
return $this->LastName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string|null $LastName
|
||||
*/
|
||||
public function setLastName(?string $LastName): void
|
||||
{
|
||||
$this->LastName = $LastName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string|null
|
||||
*/
|
||||
public function getFirstName(): ?string
|
||||
{
|
||||
return $this->FirstName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string|null $FirstName
|
||||
*/
|
||||
public function setFirstName(?string $FirstName): void
|
||||
{
|
||||
$this->FirstName = $FirstName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string|null
|
||||
*/
|
||||
public function getPhone(): ?string
|
||||
{
|
||||
return $this->Phone;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string|null $Phone
|
||||
*/
|
||||
public function setPhone(?string $Phone): void
|
||||
{
|
||||
$this->Phone = $Phone;
|
||||
}
|
||||
|
||||
public function getEmail(): ?string
|
||||
{
|
||||
return $this->email;
|
||||
}
|
||||
|
||||
public function setEmail(string $email): static
|
||||
{
|
||||
$this->email = $email;
|
||||
|
||||
if (!$this->interventions->contains($intervention)) {
|
||||
$this->interventions[] = $intervention;
|
||||
$intervention->setUser($this);
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* A visual identifier that represents this user.
|
||||
*
|
||||
* @see UserInterface
|
||||
*/
|
||||
public function getUserIdentifier(): string
|
||||
public function removeIntervention(Intervention $intervention): static
|
||||
{
|
||||
return (string) $this->email;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see UserInterface
|
||||
*
|
||||
* @return list<string>
|
||||
*/
|
||||
public function getRoles(): array
|
||||
{
|
||||
$roles = $this->roles;
|
||||
// guarantee every user at least has ROLE_USER
|
||||
$roles[] = 'ROLE_USER';
|
||||
|
||||
return array_unique($roles);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param list<string> $roles
|
||||
*/
|
||||
public function setRoles(array $roles): static
|
||||
{
|
||||
$this->roles = $roles;
|
||||
|
||||
if ($this->interventions->removeElement($intervention)) {
|
||||
if ($intervention->getUser() === $this) {
|
||||
$intervention->setUser(null);
|
||||
}
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see PasswordAuthenticatedUserInterface
|
||||
*/
|
||||
public function getPassword(): ?string
|
||||
public function getSkills(): Collection
|
||||
{
|
||||
return $this->password;
|
||||
return $this->skills;
|
||||
}
|
||||
|
||||
public function setPassword(string $password): static
|
||||
public function addSkill(Skill $skill): static
|
||||
{
|
||||
$this->password = $password;
|
||||
|
||||
if (!$this->skills->contains($skill)) {
|
||||
$this->skills[] = $skill;
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see UserInterface
|
||||
*/
|
||||
public function eraseCredentials(): void
|
||||
public function removeSkill(Skill $skill): static
|
||||
{
|
||||
// If you store any temporary, sensitive data on the user, clear it here
|
||||
$this->plainPassword = null;
|
||||
$this->skills->removeElement($skill);
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
|
@ -4,6 +4,8 @@ namespace App\Entity;
|
||||
|
||||
use App\Repository\VehicleRepository;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
|
||||
#[ORM\Entity(repositoryClass: VehicleRepository::class)]
|
||||
class Vehicle
|
||||
@ -22,6 +24,14 @@ class Vehicle
|
||||
#[ORM\Column(length: 255)]
|
||||
private ?string $Model = null;
|
||||
|
||||
#[ORM\OneToMany(mappedBy: 'vehicle', targetEntity: Intervention::class)]
|
||||
private Collection $intervention;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->intervention = new ArrayCollection();
|
||||
}
|
||||
|
||||
public function getId(): ?int
|
||||
{
|
||||
return $this->id;
|
||||
@ -35,7 +45,6 @@ class Vehicle
|
||||
public function setLicensePlate(string $LicensePlate): static
|
||||
{
|
||||
$this->LicensePlate = $LicensePlate;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
@ -47,7 +56,6 @@ class Vehicle
|
||||
public function setBrand(string $Brand): static
|
||||
{
|
||||
$this->Brand = $Brand;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
@ -60,4 +68,28 @@ class Vehicle
|
||||
{
|
||||
$this->Model = $Model;
|
||||
}
|
||||
|
||||
public function getIntervention(): Collection
|
||||
{
|
||||
return $this->intervention;
|
||||
}
|
||||
|
||||
public function addIntervention(Intervention $intervention): static
|
||||
{
|
||||
if (!$this->intervention->contains($intervention)) {
|
||||
$this->intervention[] = $intervention;
|
||||
$intervention->setVehicle($this);
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function removeIntervention(Intervention $intervention): static
|
||||
{
|
||||
if ($this->intervention->removeElement($intervention)) {
|
||||
if ($intervention->getVehicle() === $this) {
|
||||
$intervention->setVehicle(null);
|
||||
}
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
|
@ -3,6 +3,7 @@
|
||||
namespace App\Form;
|
||||
|
||||
use App\Entity\Fault;
|
||||
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\TextType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
@ -14,6 +15,7 @@ class FaultType extends AbstractType
|
||||
{
|
||||
$builder
|
||||
->add('Wording', TextType::class)
|
||||
->add('Description', TextType::class)
|
||||
;
|
||||
}
|
||||
|
||||
|
@ -2,9 +2,14 @@
|
||||
|
||||
namespace App\Form;
|
||||
|
||||
use App\Entity\Fault;
|
||||
use App\Entity\Intervention;
|
||||
use App\Entity\Stock;
|
||||
use App\Entity\Utilisateur;
|
||||
use App\Entity\Vehicle;
|
||||
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\DateType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\DateTimeType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\TextType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
@ -15,13 +20,40 @@ class InterventionType extends AbstractType
|
||||
{
|
||||
$builder
|
||||
->add('Wording', TextType::class)
|
||||
->add('Timestamp', DateType::class, [
|
||||
->add('Timestamp', DateTimeType::class, [
|
||||
'widget' => 'single_text',
|
||||
])
|
||||
->add('Description', TextType::class)
|
||||
->add('Address', TextType::class)
|
||||
->add('Status', TextType::class)
|
||||
->add('user', EntityType::class, [
|
||||
'class' => Utilisateur::class,
|
||||
'choice_label' => 'FirstName', // ou autre (LastName, email)
|
||||
])
|
||||
->add('fault', EntityType::class, [
|
||||
'class' => Fault::class,
|
||||
'choice_label' => 'Wording',
|
||||
])
|
||||
->add('vehicle', EntityType::class, [
|
||||
'class' => Vehicle::class,
|
||||
'choice_label' => 'LicensePlate',
|
||||
'required' => false,
|
||||
])
|
||||
->add('stocks', EntityType::class, [
|
||||
'class' => Stock::class,
|
||||
'choice_label' => 'Wording',
|
||||
'multiple' => true,
|
||||
'expanded' => true,
|
||||
])
|
||||
;
|
||||
|
||||
// // 👉 Sélecteur de véhicule
|
||||
// ->add('vehicule', EntityType::class, [
|
||||
// 'class' => Vehicule::class,
|
||||
// 'choice_label' => 'immatriculation', // ou n'importe quel champ que tu veux afficher
|
||||
// 'placeholder' => 'Aucun véhicule sélectionné',
|
||||
// 'required' => false,
|
||||
// ]);
|
||||
}
|
||||
|
||||
public function configureOptions(OptionsResolver $resolver): void
|
||||
|
@ -13,7 +13,7 @@ class SkillType extends AbstractType
|
||||
public function buildForm(FormBuilderInterface $builder, array $options): void
|
||||
{
|
||||
$builder
|
||||
->add('Wording',TextType::class)
|
||||
->add('Wording', TextType::class)
|
||||
->add('Description', TextType::class)
|
||||
;
|
||||
}
|
||||
|
@ -2,7 +2,9 @@
|
||||
|
||||
namespace App\Form;
|
||||
|
||||
use App\Entity\Skill;
|
||||
use App\Entity\Utilisateur;
|
||||
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\DateType;
|
||||
@ -27,14 +29,24 @@ class UserType extends AbstractType
|
||||
'choices' => [
|
||||
'Secretaire' => 'ROLE_SECRETAIRE',
|
||||
'Chauffagiste' => 'ROLE_CHAUFFAGISTE',
|
||||
'Admin' => 'ROLE_ADMIN', // Ajouté si besoin de créer des admins
|
||||
],
|
||||
'multiple' => true,
|
||||
'expanded' => true, // pour avoir des cases à cocher
|
||||
])
|
||||
->add('skills', EntityType::class, [
|
||||
'class' => Skill::class,
|
||||
'choice_label' => 'Wording',
|
||||
'multiple' => true,
|
||||
'expanded' => true,
|
||||
'required' => false,
|
||||
])
|
||||
->add('plainPassword', PasswordType::class, [
|
||||
'mapped' => false,
|
||||
'required' => true,
|
||||
'label' => 'Mot de passe',
|
||||
]);
|
||||
])
|
||||
;
|
||||
}
|
||||
|
||||
public function configureOptions(OptionsResolver $resolver): void
|
||||
|
@ -3,45 +3,119 @@
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>{% block title %}Mon App Symfony{% endblock %}</title>
|
||||
<style>
|
||||
body {
|
||||
font-family: sans-serif;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
background-color: #f9f9f9;
|
||||
}
|
||||
|
||||
header {
|
||||
background-color: #222;
|
||||
color: white;
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
.user-info {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
nav {
|
||||
background-color: #eee;
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
nav ul {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 1rem;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
nav li a {
|
||||
text-decoration: none;
|
||||
color: #0077cc;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
nav li a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.content {
|
||||
padding: 2rem;
|
||||
}
|
||||
|
||||
.role-badge {
|
||||
background: #ddd;
|
||||
padding: 0.2rem 0.6rem;
|
||||
border-radius: 4px;
|
||||
margin-right: 0.3rem;
|
||||
font-size: 0.85em;
|
||||
}
|
||||
|
||||
.logout-btn {
|
||||
background: transparent;
|
||||
color: white;
|
||||
border: 1px solid white;
|
||||
padding: 0.3rem 0.8rem;
|
||||
text-decoration: none;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.logout-btn:hover {
|
||||
background-color: white;
|
||||
color: #222;
|
||||
}
|
||||
</style>
|
||||
{% block stylesheets %}{% endblock %}
|
||||
|
||||
<!-- FullCalendar pour faire un calendrier dynamique -->
|
||||
<link href="https://cdn.jsdelivr.net/npm/fullcalendar@5.10.1/main.min.css" rel="stylesheet" />
|
||||
<script src="https://cdn.jsdelivr.net/npm/fullcalendar@5.10.1/main.min.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
{% if app.user %}
|
||||
<div class="user-info">
|
||||
Connecté en tant que {{ app.user.email }} |
|
||||
Rôles :
|
||||
{% for role in app.user.roles %}
|
||||
{{ role }}{% if not loop.last %}, {% endif %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
<header>
|
||||
<div class="user-info">
|
||||
<div>
|
||||
<strong>Connecté en tant que</strong> {{ app.user.email }}<br>
|
||||
</div>
|
||||
<a href="{{ path('app_logout') }}" class="logout-btn">Déconnexion</a>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<nav>
|
||||
<ul>
|
||||
{% if is_granted('ROLE_ADMIN') %}
|
||||
<li><a href="{{ path('admin_dashboard') }}">Dashboard Admin</a></li>
|
||||
<li><a href="{{ path('app_user_index') }}">Gérer un utilisateur</a></li>
|
||||
<li><a href="{{ path('app_calendrier_index') }}">Tous les plannings</a></li>
|
||||
<li><a href="{{ path('app_stock_index') }}">Gérer les stocks</a></li>
|
||||
<li><a href="{{ path('app_user_index') }}">Gérer les utilisateurs</a></li>
|
||||
<li><a href="{{ path('app_vehicle_index') }}">Gérer les véhicules</a></li>
|
||||
<li><a href="{{ path('app_fault_index') }}">Test des fault !</a></li>
|
||||
<li><a href="{{ path('app_stock_index') }}">Gérer les stocks</a></li>
|
||||
<li><a href="{{ path('app_fault_index') }}">Gérer les pannes</a></li>
|
||||
<li><a href="{{ path('app_calendrier_index') }}">Tous les plannings</a></li>
|
||||
{% endif %}
|
||||
|
||||
{% if is_granted('ROLE_SECRETAIRE') %}
|
||||
<li><a href="{{ path('secretaire_dashboard') }}">Dashboard Secrétaire</a></li>
|
||||
<li><a href="{{ path('user_new') }}">Créer un chauffagiste</a></li>
|
||||
<li><a href="{{ path('calendrier_index_secretaire') }}">Plannings chauffagistes</a></li>
|
||||
<li><a href="{{ path('stock_index') }}">Gérer les stocks</a></li>
|
||||
<li><a href="{{ path('vehicle_index') }}">Gérer les véhicules</a></li>
|
||||
<li><a href="{{ path('app_user_index') }}">Créer un chauffagiste</a></li>
|
||||
<li><a href="{{ path('app_vehicle_index') }}">Gérer les véhicules</a></li>
|
||||
<li><a href="{{ path('app_stock_index') }}">Gérer les stocks</a></li>
|
||||
<li><a href="{{ path('app_calendrier_indexSecretaire') }}">Plannings chauffagistes</a></li>
|
||||
{% endif %}
|
||||
|
||||
{% if is_granted('ROLE_CHAUFFAGISTE') %}
|
||||
<li><a href="{{ path('chauffagiste_dashboard') }}">Dashboard Chauffagiste</a></li>
|
||||
<li><a href="{{ path('calendrier_index_chauffagiste') }}">Mon planning</a></li>
|
||||
<li><a href="{{ path('intervention_index') }}">Mes interventions</a></li>
|
||||
<li><a href="{{ path('stock_index') }}">Pièces détachées</a></li>
|
||||
<li><a href="{{ path('app_intervention_index') }}">Mes interventions</a></li>
|
||||
<li><a href="{{ path('app_stock_index') }}">Pièces détachées</a></li>
|
||||
<li><a href="{{ path('app_calendrier_indexChauffagiste') }}">Mon planning</a></li>
|
||||
{% endif %}
|
||||
|
||||
<li><a href="{{ path('app_logout') }}">Déconnexion</a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
{% endif %}
|
||||
|
@ -1,57 +1,23 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="fr">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>{% block title %}Authentification{% endblock %}</title>
|
||||
<link href="{{ asset('styles/css/calendrier.css') }}" rel="stylesheet">
|
||||
{% block stylesheets %}
|
||||
{% endblock %}
|
||||
</head>
|
||||
{% extends 'base.html.twig' %}
|
||||
|
||||
<body>
|
||||
<div class="sidebar">
|
||||
<div class="sidebar-button">
|
||||
<img class="logoEmail" src="{{ asset('styles/image/6.png') }}">
|
||||
</div>
|
||||
<div class="sidebar-button">
|
||||
<img class="logoEmail" src="{{ asset('styles/image/3.png') }}">
|
||||
</div>
|
||||
<a href="{{ path('app_intervention_new') }}">
|
||||
<button>Create Intervention</button>
|
||||
</a>
|
||||
<div class="sidebar-button">
|
||||
<img class="logoEmail" src="{{ asset('styles/image/4.png') }}">
|
||||
</div>
|
||||
<span>Choose heating engineer</span>
|
||||
<div class="sidebar-button">
|
||||
<img class="logoEmail" src="{{ asset('styles/image/5.png') }}">
|
||||
</div>
|
||||
<span>Modify Intervention</span>
|
||||
<div class="sidebar-button">
|
||||
<img class="logoEmail" src="{{ asset('styles/image/7.png') }}">
|
||||
</div>
|
||||
<span>Surname Name</span>
|
||||
{% block title %}Calendrier des interventions{% endblock %}
|
||||
|
||||
<div class="sidebar-button">
|
||||
<img class="logoEmail" src="{{ asset('styles/image/LogoHegreConfort_SansFond.png') }}">
|
||||
</div>
|
||||
{% block body %}
|
||||
<h1>📅 Calendrier des interventions</h1>
|
||||
|
||||
<div id="calendar"></div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<div class="main-content">
|
||||
<div class="calendar-header" style="gap: 50px">
|
||||
<div class="day-header">Mo</div>
|
||||
<div class="day-header">Tu</div>
|
||||
<div class="day-header">We</div>
|
||||
<div class="day-header">Th</div>
|
||||
<div class="day-header">Fr</div>
|
||||
<div class="day-header">Sa</div>
|
||||
<div class="day-header">Su</div>
|
||||
</div>
|
||||
<div class="calendar-title">Calendar</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
var calendarEl = document.getElementById('calendar');
|
||||
var calendar = new FullCalendar.Calendar(calendarEl, {
|
||||
initialView: 'dayGridMonth',
|
||||
events: {{ events | raw }},
|
||||
eventClick: function(info) {
|
||||
alert('Intervention : ' + info.event.title + '\n' + info.event.extendedProps.description);
|
||||
}
|
||||
});
|
||||
calendar.render();
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
@ -0,0 +1,23 @@
|
||||
{% extends 'base.html.twig' %}
|
||||
|
||||
{% block title %}Mon calendrier d'interventions{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<h1>📅 Mon calendrier d'interventions</h1>
|
||||
|
||||
<div id="calendar"></div>
|
||||
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
var calendarEl = document.getElementById('calendar');
|
||||
var calendar = new FullCalendar.Calendar(calendarEl, {
|
||||
initialView: 'dayGridMonth',
|
||||
events: {{ events | raw }},
|
||||
eventClick: function(info) {
|
||||
alert('Intervention : ' + info.event.title + '\n' + info.event.extendedProps.description);
|
||||
}
|
||||
});
|
||||
calendar.render();
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
@ -1,20 +1,23 @@
|
||||
{% extends 'base.html.twig' %}
|
||||
|
||||
{% block title %}Hello CalendrierController!{% endblock %}
|
||||
{% block title %}Calendrier des interventions{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<style>
|
||||
.example-wrapper { margin: 1em auto; max-width: 800px; width: 95%; font: 18px/1.5 sans-serif; }
|
||||
.example-wrapper code { background: #F5F5F5; padding: 2px 6px; }
|
||||
</style>
|
||||
<h1>📅 Calendrier des interventions</h1>
|
||||
|
||||
<div class="example-wrapper">
|
||||
<h1>Hello {{ controller_name }}! ✅</h1>
|
||||
<div id="calendar"></div>
|
||||
|
||||
This friendly message is coming from:
|
||||
<ul>
|
||||
<li>Your controller at <code>/home/allarda@stsio.lan/Test/HegreEtConfort/src/Controller/CalendrierController.php</code></li>
|
||||
<li>Your template at <code>/home/allarda@stsio.lan/Test/HegreEtConfort/templates/calendrier/index.html.twig</code></li>
|
||||
</ul>
|
||||
</div>
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
var calendarEl = document.getElementById('calendar');
|
||||
var calendar = new FullCalendar.Calendar(calendarEl, {
|
||||
initialView: 'dayGridMonth',
|
||||
events: {{ events | raw }},
|
||||
eventClick: function(info) {
|
||||
alert('Intervention : ' + info.event.title + '\n' + info.event.extendedProps.description);
|
||||
}
|
||||
});
|
||||
calendar.render();
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
@ -1,7 +1,15 @@
|
||||
{% extends 'base.html.twig' %}
|
||||
|
||||
{% block body %}
|
||||
<h1>Bienvenue Admin</h1>
|
||||
<p>Tu as tous les droits ici !</p>
|
||||
{% endblock %}
|
||||
{% block title %}Dashboard Administrateur{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<h1 class="mb-4">👑 Bienvenue {{ app.user.FirstName }} sur le Dashboard Administrateur</h1>
|
||||
|
||||
<p>Vous êtes connecté avec les rôles :
|
||||
{% for role in app.user.roles %}
|
||||
<span class="badge bg-primary">{{ role }}</span>
|
||||
{% endfor %}
|
||||
</p>
|
||||
|
||||
<p class="text-muted">Utilisez le menu en haut pour accéder aux fonctionnalités.</p>
|
||||
{% endblock %}
|
||||
|
@ -1,7 +0,0 @@
|
||||
{% extends 'base.html.twig' %}
|
||||
|
||||
{% block body %}
|
||||
<h1>Bienvenue chauffagiste</h1>
|
||||
<p>Vas travailler</p>
|
||||
{% endblock %}
|
||||
|
15
templates/dashboard/chauffagiste.html.twig
Normal file
15
templates/dashboard/chauffagiste.html.twig
Normal file
@ -0,0 +1,15 @@
|
||||
{% extends 'base.html.twig' %}
|
||||
|
||||
{% block title %}Dashboard Chauffagiste{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<h1 class="mb-4">🔧 Bonjour {{ app.user.FirstName }}, bienvenue sur ton espace</h1>
|
||||
|
||||
<p>Rôle :
|
||||
{% for role in app.user.roles %}
|
||||
<span class="badge bg-success">{{ role }}</span>
|
||||
{% endfor %}
|
||||
</p>
|
||||
|
||||
<p class="text-muted">Retrouvez votre planning, vos interventions et vos outils dans le menu ci-dessus.</p>
|
||||
{% endblock %}
|
@ -1,7 +1,15 @@
|
||||
{% extends 'base.html.twig' %}
|
||||
|
||||
{% block body %}
|
||||
<h1>Bienvenue Secretaire</h1>
|
||||
<p>Fais ce que tu veux</p>
|
||||
{% endblock %}
|
||||
{% block title %}Dashboard Secrétaire{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<h1 class="mb-4">🗂️ Bienvenue {{ app.user.FirstName }} sur le Dashboard Secrétaire</h1>
|
||||
|
||||
<p>Vous êtes connectée avec les rôles :
|
||||
{% for role in app.user.roles %}
|
||||
<span class="badge bg-secondary">{{ role }}</span>
|
||||
{% endfor %}
|
||||
</p>
|
||||
|
||||
<p class="text-muted">Utilisez le menu pour créer des interventions, gérer les chauffagistes, etc.</p>
|
||||
{% endblock %}
|
||||
|
@ -1,13 +1,14 @@
|
||||
{% extends 'base.html.twig' %}
|
||||
|
||||
{% block title %}Edit Fault{% endblock %}
|
||||
{% block title %}Modifier la panne{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<h1>Edit Fault</h1>
|
||||
<h1 class="mb-4">✏️ Modifier une panne</h1>
|
||||
|
||||
{{ include('fault/_form.html.twig', {'button_label': 'Update'}) }}
|
||||
{{ include('fault/_form.html.twig', {'button_label': 'Mettre à jour'}) }}
|
||||
|
||||
<a href="{{ path('app_fault_index') }}">back to list</a>
|
||||
|
||||
{{ include('fault/_delete_form.html.twig') }}
|
||||
<div class="mt-3">
|
||||
<a href="{{ path('app_fault_index') }}" class="btn btn-secondary">← Retour à la liste</a>
|
||||
{{ include('fault/_delete_form.html.twig') }}
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
@ -1,36 +1,37 @@
|
||||
{% extends 'base.html.twig' %}
|
||||
|
||||
{% block title %}Fault index{% endblock %}
|
||||
{% block title %}Liste des pannes{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<h1>Fault index</h1>
|
||||
<h1 class="mb-4">📋 Liste des pannes enregistrées</h1>
|
||||
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Id</th>
|
||||
<th>Wording</th>
|
||||
<th>actions</th>
|
||||
</tr>
|
||||
<table class="table table-striped table-bordered align-middle">
|
||||
<thead class="table-dark">
|
||||
<tr>
|
||||
<th>ID</th>
|
||||
<th>Nom</th>
|
||||
<th>Description</th>
|
||||
<th class="text-center">Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for fault in faults %}
|
||||
<tr>
|
||||
<td>{{ fault.id }}</td>
|
||||
<td>{{ fault.Wording }}</td>
|
||||
<td>{{ fault.actions }}</td>
|
||||
<td>
|
||||
<a href="{{ path('app_fault_show', {'id': fault.id}) }}">show</a>
|
||||
<a href="{{ path('app_fault_edit', {'id': fault.id}) }}">edit</a>
|
||||
<td>{{ fault.Description }}</td>
|
||||
<td class="text-center">
|
||||
<a href="{{ path('app_fault_show', {'id': fault.id}) }}" class="btn btn-sm btn-info">👁️ Voir</a>
|
||||
<a href="{{ path('app_fault_edit', {'id': fault.id}) }}" class="btn btn-sm btn-warning">✏️ Modifier</a>
|
||||
</td>
|
||||
</tr>
|
||||
{% else %}
|
||||
<tr>
|
||||
<td colspan="3">no records found</td>
|
||||
<td colspan="4" class="text-center text-muted">Aucune panne trouvée.</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<a href="{{ path('app_fault_new') }}">Create new</a>
|
||||
<a href="{{ path('app_fault_new') }}" class="btn btn-success mt-3">➕ Ajouter une nouvelle panne</a>
|
||||
{% endblock %}
|
||||
|
@ -1,11 +1,13 @@
|
||||
{% extends 'base.html.twig' %}
|
||||
|
||||
{% block title %}New Fault{% endblock %}
|
||||
{% block title %}Créer une panne{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<h1>Create new Fault</h1>
|
||||
<h1 class="mb-4">➕ Ajouter une nouvelle panne</h1>
|
||||
|
||||
{{ include('fault/_form.html.twig') }}
|
||||
|
||||
<a href="{{ path('app_fault_index') }}">back to list</a>
|
||||
<div class="mt-3">
|
||||
<a href="{{ path('app_fault_index') }}" class="btn btn-secondary">← Retour à la liste</a>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
@ -1,26 +1,30 @@
|
||||
{% extends 'base.html.twig' %}
|
||||
|
||||
{% block title %}Fault{% endblock %}
|
||||
{% block title %}Détail de la panne{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<h1>Fault</h1>
|
||||
<h1 class="mb-4">🔍 Détails de la panne</h1>
|
||||
|
||||
<table class="table">
|
||||
<table class="table table-bordered">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>Id</th>
|
||||
<td>{{ fault.id }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Wording</th>
|
||||
<td>{{ fault.Wording }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>ID</th>
|
||||
<td>{{ fault.id }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Nom</th>
|
||||
<td>{{ fault.Wording }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Description</th>
|
||||
<td>{{ fault.Description }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<a href="{{ path('app_fault_index') }}">back to list</a>
|
||||
|
||||
<a href="{{ path('app_fault_edit', {'id': fault.id}) }}">edit</a>
|
||||
|
||||
{{ include('fault/_delete_form.html.twig') }}
|
||||
<div class="mt-3">
|
||||
<a href="{{ path('app_fault_index') }}" class="btn btn-secondary">← Retour à la liste</a>
|
||||
<a href="{{ path('app_fault_edit', {'id': fault.id}) }}" class="btn btn-warning">✏️ Modifier</a>
|
||||
{{ include('fault/_delete_form.html.twig') }}
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
@ -1,4 +1,47 @@
|
||||
{#{{ form_start(form) }}#}
|
||||
{# {{ form_widget(form) }}#}
|
||||
{# <button class="btn">{{ button_label|default('Save') }}</button>#}
|
||||
{#{{ form_end(form) }}#}
|
||||
|
||||
|
||||
{{ form_start(form) }}
|
||||
{{ form_widget(form) }}
|
||||
<button class="btn">{{ button_label|default('Save') }}</button>
|
||||
|
||||
<div class="form-group">
|
||||
{{ form_label(form.Wording, 'Nom de l\'intervention') }}
|
||||
{{ form_widget(form.Wording, {'attr': {'class': 'form-control'}}) }}
|
||||
{{ form_errors(form.Wording) }}
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
{{ form_label(form.Timestamp, 'Date') }}
|
||||
{{ form_widget(form.Timestamp, {'attr': {'class': 'form-control'}}) }}
|
||||
{{ form_errors(form.Timestamp) }}
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
{{ form_label(form.Description, 'Description') }}
|
||||
{{ form_widget(form.Description, {'attr': {'class': 'form-control'}}) }}
|
||||
{{ form_errors(form.Description) }}
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
{{ form_label(form.Address, 'Adresse') }}
|
||||
{{ form_widget(form.Address, {'attr': {'class': 'form-control'}}) }}
|
||||
{{ form_errors(form.Address) }}
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
{{ form_label(form.Status, 'Statut') }}
|
||||
{{ form_widget(form.Status, {'attr': {'class': 'form-control'}}) }}
|
||||
{{ form_errors(form.Status) }}
|
||||
</div>
|
||||
|
||||
{#<div class="form-group">#}
|
||||
{# {{ form_label(form.vehicule, 'Véhicule associé') }}#}
|
||||
{# {{ form_widget(form.vehicule, {'attr': {'class': 'form-control'}}) }}#}
|
||||
{# {{ form_errors(form.vehicule) }}#}
|
||||
{#</div>#}
|
||||
|
||||
<button class="btn btn-primary mt-3">{{ button_label|default('Enregistrer') }}</button>
|
||||
|
||||
{{ form_end(form) }}
|
||||
|
@ -1,13 +1,14 @@
|
||||
{% extends 'base.html.twig' %}
|
||||
|
||||
{% block title %}Edit Intervention{% endblock %}
|
||||
{% block title %}Modifier une intervention{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<h1>Edit Intervention</h1>
|
||||
<h1 class="mb-4">✏️ Modifier l'intervention</h1>
|
||||
|
||||
{{ include('intervention/_form.html.twig', {'button_label': 'Update'}) }}
|
||||
{{ include('intervention/_form.html.twig', {'button_label': 'Mettre à jour'}) }}
|
||||
|
||||
<a href="{{ path('app_intervention_index') }}">back to list</a>
|
||||
|
||||
{{ include('intervention/_delete_form.html.twig') }}
|
||||
<div class="mt-3">
|
||||
<a href="{{ path('app_intervention_index') }}" class="btn btn-secondary">← Retour à la liste des interventions</a>
|
||||
{{ include('intervention/_delete_form.html.twig') }}
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
@ -1,43 +1,53 @@
|
||||
{% extends 'base.html.twig' %}
|
||||
|
||||
{% block title %}Intervention index{% endblock %}
|
||||
{% block title %}Liste des interventions{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<h1>Intervention index</h1>
|
||||
<h1>Liste des interventions</h1>
|
||||
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Id</th>
|
||||
<th>Wording</th>
|
||||
<th>Timestamp</th>
|
||||
<th>Description</th>
|
||||
<th>Address</th>
|
||||
<th>Status</th>
|
||||
<th>actions</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Id</th>
|
||||
<th>Nom</th>
|
||||
<th>Chauffagiste</th>
|
||||
<th>Véhicule</th>
|
||||
<th>Panne</th>
|
||||
<th>Date & Heure</th>
|
||||
<th>Statut</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for intervention in interventions %}
|
||||
<tr>
|
||||
<td>{{ intervention.id }}</td>
|
||||
<td>{{ intervention.Wording }}</td>
|
||||
<td>{{ intervention.Timestamp ? intervention.Timestamp|date('Y-m-d H:i:s') : '' }}</td>
|
||||
<td>{{ intervention.Description }}</td>
|
||||
<td>{{ intervention.Address }}</td>
|
||||
<td>
|
||||
{{ intervention.user ? intervention.user.FirstName ~ ' ' ~ intervention.user.LastName : 'Non assigné' }}
|
||||
</td>
|
||||
<td>
|
||||
{{ intervention.vehicle ? intervention.vehicle.LicensePlate : 'Aucun véhicule' }}
|
||||
</td>
|
||||
<td>
|
||||
{{ intervention.fault ? intervention.fault.Wording : 'Non précisé' }}
|
||||
</td>
|
||||
<td>
|
||||
{{ intervention.Timestamp ? intervention.Timestamp|date('Y-m-d H:i') : '' }}
|
||||
</td>
|
||||
<td>{{ intervention.Status }}</td>
|
||||
<td>
|
||||
<a href="{{ path('app_intervention_show', {'id': intervention.id}) }}">show</a>
|
||||
<a href="{{ path('app_intervention_edit', {'id': intervention.id}) }}">edit</a>
|
||||
<a href="{{ path('app_intervention_show', {'id': intervention.id}) }}" class="btn btn-info btn-sm">Voir</a>
|
||||
<a href="{{ path('app_intervention_edit', {'id': intervention.id}) }}" class="btn btn-secondary btn-sm">Modifier</a>
|
||||
</td>
|
||||
</tr>
|
||||
{% else %}
|
||||
<tr>
|
||||
<td colspan="7">no records found</td>
|
||||
<td colspan="8">Aucune intervention trouvée</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<a href="{{ path('app_intervention_new') }}">Create new</a>
|
||||
<a href="{{ path('app_intervention_new') }}" class="btn btn-success">Créer une nouvelle intervention</a>
|
||||
{% endblock %}
|
||||
|
@ -1,79 +1,72 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="fr, en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Créer une intervention</title>
|
||||
<link href="{{ asset('styles/css/intervention.css') }}" rel='stylesheet'>
|
||||
<link rel="icon"
|
||||
href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 128 128%22><text y=%221.2em%22 font-size=%2296%22>⚫️</text><text y=%221.3em%22 x=%220.2em%22 font-size=%2276%22 fill=%22%23fff%22>sf</text></svg>">
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet"
|
||||
integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">
|
||||
{% extends 'base.html.twig' %}
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
{% block title %}Nouvelle intervention{% endblock %}
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<div class="background"></div>
|
||||
<img class="logoCalendar" src="{{ asset('styles/image/calendar.png') }}" alt="Logo Calendrier">
|
||||
<a href="{{ path('app_intervention_index') }}" class="intervention">Voir les interventions</a>
|
||||
<img class="logoChauffagiste" src="{{ asset('styles/image/chauffagiste.png') }}" alt="Logo Chauffagiste">
|
||||
<h1 class="chauffagiste">Choisissez un chauffagiste</h1>
|
||||
<img class="logoModifier" src="{{ asset('styles/image/modifier.png') }}">
|
||||
<h1 class="modifier">Modifier l'intervention</h1>
|
||||
<img class="logoHegre" src="{{ asset('styles/image/LogoHegreConfort_SansFond.png') }}">
|
||||
{% block body %}
|
||||
<h1 class="mb-4">➕ Créer une nouvelle intervention</h1>
|
||||
|
||||
{{ include('intervention/_form.html.twig') }}
|
||||
|
||||
<<<<<<< HEAD
|
||||
<div class="background-intervention">
|
||||
<input required id="nom" placeholder="Nom de l'intervention">
|
||||
{# <input required id="nom" placeholder="Nom de l'intervention">#}
|
||||
|
||||
<select required type="select" name="pannes" id="pannes">
|
||||
<option value="pan1">pan1</option>
|
||||
<option value="pan2">pan2</option>
|
||||
<option value="pan3">pan3</option>
|
||||
<option value="pan4">pan4</option>
|
||||
<option value="pan5">pan5</option>
|
||||
<option value="pan6">pan6</option>
|
||||
</select>
|
||||
{# <select required type="select" name="pannes" id="pannes">#}
|
||||
{# <option value="pan1">pan1</option>#}
|
||||
{# <option value="pan2">pan2</option>#}
|
||||
{# <option value="pan3">pan3</option>#}
|
||||
{# <option value="pan4">pan4</option>#}
|
||||
{# <option value="pan5">pan5</option>#}
|
||||
{# <option value="pan6">pan6</option>#}
|
||||
{# </select>#}
|
||||
|
||||
<select required type="select" name="pannes" id="employesCompetences">
|
||||
<option value="emp1">employé1 - sa compétence</option>
|
||||
<option value="emp2">employé2 - sa compétence</option>
|
||||
<option value="emp3">employé3 - sa compétence</option>
|
||||
<option value="emp4">employé4 - sa compétence</option>
|
||||
<option value="emp5">employé5 - sa compétence</option>
|
||||
<option value="emp6">employé6 - sa compétence</option>
|
||||
</select>
|
||||
{# <select required type="select" name="pannes" id="employesCompetences">#}
|
||||
{# <option value="emp1">employé1 - sa compétence</option>#}
|
||||
{# <option value="emp2">employé2 - sa compétence</option>#}
|
||||
{# <option value="emp3">employé3 - sa compétence</option>#}
|
||||
{# <option value="emp4">employé4 - sa compétence</option>#}
|
||||
{# <option value="emp5">employé5 - sa compétence</option>#}
|
||||
{# <option value="emp6">employé6 - sa compétence</option>#}
|
||||
{# </select>#}
|
||||
|
||||
<!-- <input required id="employesCompetences" placeholder="Liste des employés et de leurs compétences"> -->
|
||||
<select required type="select" name="piece" id="piece">
|
||||
<option value="pièce1">Pièce affecter 1</option>
|
||||
<option value="pièce2">Pièce affecter 2</option>
|
||||
<option value="pièce3">Pièce affecter 3</option>
|
||||
<option value="pièce4">Pièce affecter 4</option>
|
||||
<option value="pièce5">Pièce affecter 5</option>
|
||||
<option value="pièce6">Pièce affecter 6</option>
|
||||
</select>
|
||||
{# <!-- <input required id="employesCompetences" placeholder="Liste des employés et de leurs compétences"> -->#}
|
||||
{# <select required type="select" name="piece" id="piece">#}
|
||||
{# <option value="pièce1">Pièce affecter 1</option>#}
|
||||
{# <option value="pièce2">Pièce affecter 2</option>#}
|
||||
{# <option value="pièce3">Pièce affecter 3</option>#}
|
||||
{# <option value="pièce4">Pièce affecter 4</option>#}
|
||||
{# <option value="pièce5">Pièce affecter 5</option>#}
|
||||
{# <option value="pièce6">Pièce affecter 6</option>#}
|
||||
{# </select>#}
|
||||
|
||||
<p id="vehicule">Véhicule nécessaire</p>
|
||||
<input type="checkbox" name="vehicule1" id="vehicule1">
|
||||
<label for=”vehicule1” id="oui"> Oui </label>
|
||||
<input type="checkbox" name="vehicule2" id="vehicule2">
|
||||
<label for=”vehicule2” id="non"> Non </label>
|
||||
{# <p id="vehicule">Véhicule nécessaire</p>#}
|
||||
{# <form>#}
|
||||
{# <label id="oui">#}
|
||||
{# <input type="radio" name="choix" value="option1">#}
|
||||
{# Oui </label>#}
|
||||
{# <label id="non">#}
|
||||
{# <input type="radio" name="choix" value="option2">#}
|
||||
{# Non </label>#}
|
||||
{# </form>#}
|
||||
|
||||
<p id="date">Jour de l'intervention</p>
|
||||
<input type="date" id="calendar">
|
||||
{# <p id="date">Jour de l'intervention</p>#}
|
||||
{# <input type="date" id="calendar">#}
|
||||
|
||||
<input type="text" id="description" placeholder="Description">
|
||||
<input type="text" id="adresse" placeholder="Adresse">
|
||||
{# <input type="text" id="description" placeholder="Description">#}
|
||||
{# <input type="text" id="adresse" placeholder="Adresse">#}
|
||||
|
||||
<button type="submit" class="applique"> Appliquée </button>
|
||||
<button type="reset" class="supprimer"> Supprimer </button>
|
||||
{# <button type="submit" class="applique"> Appliquée </button>#}
|
||||
{# <button type="reset" class="supprimer"> Supprimer </button>#}
|
||||
|
||||
|
||||
|
||||
<!-- {{ include('intervention/_form.html.twig') }} -->
|
||||
{{ include('intervention/_form.html.twig') }}
|
||||
|
||||
<a href="{{ path('app_intervention_index') }}" id="liste">Retour à la liste</a>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
=======
|
||||
<div class="mt-3">
|
||||
<a href="{{ path('app_intervention_index') }}" class="btn btn-secondary">← Retour à la liste des interventions</a>
|
||||
</div>
|
||||
{% endblock %}
|
||||
>>>>>>> 4fc91211f0d814453d2ed97caf6a1d94d709058e
|
||||
|
@ -3,40 +3,71 @@
|
||||
{% block title %}Intervention{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<h1>Intervention</h1>
|
||||
<h1>Détails de l'Intervention</h1>
|
||||
|
||||
<table class="table">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>Id</th>
|
||||
<td>{{ intervention.id }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Wording</th>
|
||||
<td>{{ intervention.Wording }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Timestamp</th>
|
||||
<td>{{ intervention.Timestamp ? intervention.Timestamp|date('Y-m-d H:i:s') : '' }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Description</th>
|
||||
<td>{{ intervention.Description }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Address</th>
|
||||
<td>{{ intervention.Address }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Status</th>
|
||||
<td>{{ intervention.Status }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Id</th>
|
||||
<td>{{ intervention.id }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Nom de l'intervention</th>
|
||||
<td>{{ intervention.Wording }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Date & Heure</th>
|
||||
<td>{{ intervention.Timestamp ? intervention.Timestamp|date('Y-m-d H:i') : '' }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Description</th>
|
||||
<td>{{ intervention.Description }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Adresse</th>
|
||||
<td>{{ intervention.Address }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Statut</th>
|
||||
<td>{{ intervention.Status }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Chauffagiste</th>
|
||||
<td>
|
||||
{{ intervention.user ? intervention.user.FirstName ~ ' ' ~ intervention.user.LastName : 'Non assigné' }}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Panne</th>
|
||||
<td>
|
||||
{{ intervention.fault ? intervention.fault.Wording : 'Non précisé' }}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Véhicule</th>
|
||||
<td>
|
||||
{{ intervention.vehicle ? intervention.vehicle.LicensePlate : 'Aucun véhicule associé' }}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Pièces détachées utilisées</th>
|
||||
<td>
|
||||
{% if intervention.stocks|length > 0 %}
|
||||
<ul>
|
||||
{% for stock in intervention.stocks %}
|
||||
<li>{{ stock.Wording }} (Quantité: {{ stock.Quantity }})</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% else %}
|
||||
Aucune pièce utilisée
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<a href="{{ path('app_intervention_index') }}">back to list</a>
|
||||
|
||||
<a href="{{ path('app_intervention_edit', {'id': intervention.id}) }}">edit</a>
|
||||
<a href="{{ path('app_intervention_index') }}" class="btn btn-primary">Retour à la liste</a>
|
||||
<a href="{{ path('app_intervention_edit', {'id': intervention.id}) }}" class="btn btn-warning">Modifier</a>
|
||||
|
||||
{{ include('intervention/_delete_form.html.twig') }}
|
||||
{% endblock %}
|
||||
|
@ -1,13 +1,14 @@
|
||||
{% extends 'base.html.twig' %}
|
||||
|
||||
{% block title %}Edit Skill{% endblock %}
|
||||
{% block title %}Modifier une compétence{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<h1>Edit Skill</h1>
|
||||
<h1 class="mb-4">✏️ Modifier une compétence</h1>
|
||||
|
||||
{{ include('skill/_form.html.twig', {'button_label': 'Update'}) }}
|
||||
{{ include('skill/_form.html.twig', {'button_label': 'Mettre à jour'}) }}
|
||||
|
||||
<a href="{{ path('app_skill_index') }}">back to list</a>
|
||||
|
||||
{{ include('skill/_delete_form.html.twig') }}
|
||||
<div class="mt-3">
|
||||
<a href="{{ path('app_skill_index') }}" class="btn btn-secondary">← Retour à la liste</a>
|
||||
{{ include('skill/_delete_form.html.twig') }}
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
@ -1,18 +1,18 @@
|
||||
{% extends 'base.html.twig' %}
|
||||
|
||||
{% block title %}Skill index{% endblock %}
|
||||
{% block title %}Compétences disponibles{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<h1>Skill index</h1>
|
||||
<h1 class="mb-4">📘 Liste des compétences</h1>
|
||||
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Id</th>
|
||||
<th>Wording</th>
|
||||
<th>Description</th>
|
||||
<th>actions</th>
|
||||
</tr>
|
||||
<table class="table table-striped table-bordered align-middle">
|
||||
<thead class="table-dark">
|
||||
<tr>
|
||||
<th>ID</th>
|
||||
<th>Nom</th>
|
||||
<th>Description</th>
|
||||
<th class="text-center">Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for skill in skills %}
|
||||
@ -20,18 +20,18 @@
|
||||
<td>{{ skill.id }}</td>
|
||||
<td>{{ skill.Wording }}</td>
|
||||
<td>{{ skill.Description }}</td>
|
||||
<td>
|
||||
<a href="{{ path('app_skill_show', {'id': skill.id}) }}">show</a>
|
||||
<a href="{{ path('app_skill_edit', {'id': skill.id}) }}">edit</a>
|
||||
<td class="text-center">
|
||||
<a href="{{ path('app_skill_show', {'id': skill.id}) }}" class="btn btn-info btn-sm">👁️ Voir</a>
|
||||
<a href="{{ path('app_skill_edit', {'id': skill.id}) }}" class="btn btn-warning btn-sm">✏️ Modifier</a>
|
||||
</td>
|
||||
</tr>
|
||||
{% else %}
|
||||
<tr>
|
||||
<td colspan="4">no records found</td>
|
||||
<td colspan="4" class="text-center text-muted">Aucune compétence enregistrée.</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<a href="{{ path('app_skill_new') }}">Create new</a>
|
||||
<a href="{{ path('app_skill_new') }}" class="btn btn-success mt-3">➕ Ajouter une compétence</a>
|
||||
{% endblock %}
|
||||
|
@ -1,11 +1,13 @@
|
||||
{% extends 'base.html.twig' %}
|
||||
|
||||
{% block title %}New Skill{% endblock %}
|
||||
{% block title %}Nouvelle compétence{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<h1>Create new Skill</h1>
|
||||
<h1 class="mb-4">➕ Ajouter une nouvelle compétence</h1>
|
||||
|
||||
{{ include('skill/_form.html.twig') }}
|
||||
|
||||
<a href="{{ path('app_skill_index') }}">back to list</a>
|
||||
<div class="mt-3">
|
||||
<a href="{{ path('app_skill_index') }}" class="btn btn-secondary">← Retour à la liste</a>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
@ -1,30 +1,30 @@
|
||||
{% extends 'base.html.twig' %}
|
||||
|
||||
{% block title %}Skill{% endblock %}
|
||||
{% block title %}Détail de la compétence{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<h1>Skill</h1>
|
||||
<h1 class="mb-4">🔍 Détail de la compétence</h1>
|
||||
|
||||
<table class="table">
|
||||
<table class="table table-bordered">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>Id</th>
|
||||
<td>{{ skill.id }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Wording</th>
|
||||
<td>{{ skill.Wording }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Description</th>
|
||||
<td>{{ skill.Description }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>ID</th>
|
||||
<td>{{ skill.id }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Nom</th>
|
||||
<td>{{ skill.Wording }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Description</th>
|
||||
<td>{{ skill.Description }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<a href="{{ path('app_skill_index') }}">back to list</a>
|
||||
|
||||
<a href="{{ path('app_skill_edit', {'id': skill.id}) }}">edit</a>
|
||||
|
||||
{{ include('skill/_delete_form.html.twig') }}
|
||||
<div class="mt-3">
|
||||
<a href="{{ path('app_skill_index') }}" class="btn btn-secondary">← Retour à la liste</a>
|
||||
<a href="{{ path('app_skill_edit', {'id': skill.id}) }}" class="btn btn-warning">✏️ Modifier</a>
|
||||
{{ include('skill/_delete_form.html.twig') }}
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
@ -1,13 +1,14 @@
|
||||
{% extends 'base.html.twig' %}
|
||||
|
||||
{% block title %}Edit Stock{% endblock %}
|
||||
{% block title %}Modifier une pièce{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<h1>Edit Stock</h1>
|
||||
<h1 class="mb-4">✏️ Modifier une pièce détachée</h1>
|
||||
|
||||
{{ include('stock/_form.html.twig', {'button_label': 'Update'}) }}
|
||||
{{ include('stock/_form.html.twig', {'button_label': 'Mettre à jour'}) }}
|
||||
|
||||
<a href="{{ path('app_stock_index') }}">back to list</a>
|
||||
|
||||
{{ include('stock/_delete_form.html.twig') }}
|
||||
<div class="mt-3">
|
||||
<a href="{{ path('app_stock_index') }}" class="btn btn-secondary">← Retour à la liste</a>
|
||||
{{ include('stock/_delete_form.html.twig') }}
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
@ -1,19 +1,19 @@
|
||||
{% extends 'base.html.twig' %}
|
||||
|
||||
{% block title %}Stock index{% endblock %}
|
||||
{% block title %}Liste des pièces détachées{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<h1>Stock index</h1>
|
||||
<h1 class="mb-4">📦 Pièces détachées disponibles</h1>
|
||||
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Id</th>
|
||||
<th>Wording</th>
|
||||
<th>Description</th>
|
||||
<th>Quantity</th>
|
||||
<th>actions</th>
|
||||
</tr>
|
||||
<table class="table table-striped table-bordered align-middle">
|
||||
<thead class="table-dark">
|
||||
<tr>
|
||||
<th>ID</th>
|
||||
<th>Nom</th>
|
||||
<th>Description</th>
|
||||
<th>Quantité</th>
|
||||
<th class="text-center">Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for stock in stocks %}
|
||||
@ -22,18 +22,18 @@
|
||||
<td>{{ stock.Wording }}</td>
|
||||
<td>{{ stock.Description }}</td>
|
||||
<td>{{ stock.Quantity }}</td>
|
||||
<td>
|
||||
<a href="{{ path('app_stock_show', {'id': stock.id}) }}">show</a>
|
||||
<a href="{{ path('app_stock_edit', {'id': stock.id}) }}">edit</a>
|
||||
<td class="text-center">
|
||||
<a href="{{ path('app_stock_show', {'id': stock.id}) }}" class="btn btn-info btn-sm">👁️ Voir</a>
|
||||
<a href="{{ path('app_stock_edit', {'id': stock.id}) }}" class="btn btn-warning btn-sm">✏️ Modifier</a>
|
||||
</td>
|
||||
</tr>
|
||||
{% else %}
|
||||
<tr>
|
||||
<td colspan="5">no records found</td>
|
||||
<td colspan="5" class="text-center text-muted">Aucune pièce en stock.</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<a href="{{ path('app_stock_new') }}">Create new</a>
|
||||
<a href="{{ path('app_stock_new') }}" class="btn btn-success mt-3">➕ Ajouter une pièce</a>
|
||||
{% endblock %}
|
||||
|
@ -1,11 +1,13 @@
|
||||
{% extends 'base.html.twig' %}
|
||||
|
||||
{% block title %}New Stock{% endblock %}
|
||||
{% block title %}Nouvelle pièce détachée{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<h1>Create new Stock</h1>
|
||||
<h1 class="mb-4">➕ Ajouter une nouvelle pièce</h1>
|
||||
|
||||
{{ include('stock/_form.html.twig') }}
|
||||
|
||||
<a href="{{ path('app_stock_index') }}">back to list</a>
|
||||
<div class="mt-3">
|
||||
<a href="{{ path('app_stock_index') }}" class="btn btn-secondary">← Retour à la liste</a>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
@ -1,34 +1,34 @@
|
||||
{% extends 'base.html.twig' %}
|
||||
|
||||
{% block title %}Stock{% endblock %}
|
||||
{% block title %}Détail de la pièce{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<h1>Stock</h1>
|
||||
<h1 class="mb-4">🔍 Détail d'une pièce détachée</h1>
|
||||
|
||||
<table class="table">
|
||||
<table class="table table-bordered">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>Id</th>
|
||||
<td>{{ stock.id }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Wording</th>
|
||||
<td>{{ stock.Wording }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Description</th>
|
||||
<td>{{ stock.Description }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Quantity</th>
|
||||
<td>{{ stock.Quantity }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>ID</th>
|
||||
<td>{{ stock.id }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Nom</th>
|
||||
<td>{{ stock.Wording }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Description</th>
|
||||
<td>{{ stock.Description }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Quantité</th>
|
||||
<td>{{ stock.Quantity }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<a href="{{ path('app_stock_index') }}">back to list</a>
|
||||
|
||||
<a href="{{ path('app_stock_edit', {'id': stock.id}) }}">edit</a>
|
||||
|
||||
{{ include('stock/_delete_form.html.twig') }}
|
||||
<div class="mt-3">
|
||||
<a href="{{ path('app_stock_index') }}" class="btn btn-secondary">← Retour à la liste</a>
|
||||
<a href="{{ path('app_stock_edit', {'id': stock.id}) }}" class="btn btn-warning">✏️ Modifier</a>
|
||||
{{ include('stock/_delete_form.html.twig') }}
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
@ -1,13 +1,14 @@
|
||||
{% extends 'base.html.twig' %}
|
||||
|
||||
{% block title %}Edit User{% endblock %}
|
||||
{% block title %}Modifier un utilisateur{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<h1>Edit User</h1>
|
||||
<h1 class="mb-4">✏️ Modifier un utilisateur</h1>
|
||||
|
||||
{{ include('user/_form.html.twig', {'button_label': 'Update'}) }}
|
||||
{{ include('user/_form.html.twig', {'button_label': 'Mettre à jour'}) }}
|
||||
|
||||
<a href="{{ path('app_user_index') }}">back to list</a>
|
||||
|
||||
{{ include('user/_delete_form.html.twig') }}
|
||||
<div class="mt-3">
|
||||
<a href="{{ path('app_user_index') }}" class="btn btn-secondary">← Retour à la liste des utilisateurs</a>
|
||||
{{ include('user/_delete_form.html.twig') }}
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
@ -1,23 +1,23 @@
|
||||
{% extends 'base.html.twig' %}
|
||||
|
||||
{% block title %}User index{% endblock %}
|
||||
{% block title %}Liste des utilisateurs{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<h1>User index</h1>
|
||||
<h1>Liste des utilisateurs</h1>
|
||||
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Id</th>
|
||||
<th>Email</th>
|
||||
<th>FirstName</th>
|
||||
<th>LastName</th>
|
||||
<th>BirthDate</th>
|
||||
<th>Phone</th>
|
||||
<th>Roles</th>
|
||||
<th>Password</th>
|
||||
<th>actions</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Id</th>
|
||||
<th>Email</th>
|
||||
<th>Prénom</th>
|
||||
<th>Nom</th>
|
||||
<th>Date de naissance</th>
|
||||
<th>Téléphone</th>
|
||||
<th>Rôles</th>
|
||||
<th>Compétences</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for user in users %}
|
||||
@ -28,20 +28,38 @@
|
||||
<td>{{ user.LastName }}</td>
|
||||
<td>{{ user.BirthDate ? user.BirthDate|date('Y-m-d') : '' }}</td>
|
||||
<td>{{ user.Phone }}</td>
|
||||
<td>{{ user.roles ? user.roles|json_encode : '' }}</td>
|
||||
<td>{{ user.password }}</td>
|
||||
<td>
|
||||
<a href="{{ path('app_user_show', {'id': user.id}) }}">show</a>
|
||||
<a href="{{ path('app_user_edit', {'id': user.id}) }}">edit</a>
|
||||
{% if user.roles %}
|
||||
<ul>
|
||||
{% for role in user.roles %}
|
||||
<li>{{ role }}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
{% if user.skills|length > 0 %}
|
||||
<ul>
|
||||
{% for skill in user.skills %}
|
||||
<li>{{ skill.Wording }}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% else %}
|
||||
Aucune compétence
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
<a href="{{ path('app_user_show', {'id': user.id}) }}" class="btn btn-info btn-sm">Voir</a>
|
||||
<a href="{{ path('app_user_edit', {'id': user.id}) }}" class="btn btn-secondary btn-sm">Modifier</a>
|
||||
</td>
|
||||
</tr>
|
||||
{% else %}
|
||||
<tr>
|
||||
<td colspan="9">no records found</td>
|
||||
<td colspan="9">Aucun utilisateur trouvé</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<a href="{{ path('app_user_new') }}">Create new</a>
|
||||
<a href="{{ path('app_user_new') }}" class="btn btn-success">Créer un nouvel utilisateur</a>
|
||||
{% endblock %}
|
||||
|
@ -1,11 +1,13 @@
|
||||
{% extends 'base.html.twig' %}
|
||||
|
||||
{% block title %}New User{% endblock %}
|
||||
{% block title %}Nouveau utilisateur{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<h1>Create new User</h1>
|
||||
<h1 class="mb-4">➕ Créer un nouvel utilisateur</h1>
|
||||
|
||||
{{ include('user/_form.html.twig') }}
|
||||
|
||||
<a href="{{ path('app_user_index') }}">back to list</a>
|
||||
<div class="mt-3">
|
||||
<a href="{{ path('app_user_index') }}" class="btn btn-secondary">← Retour à la liste des utilisateurs</a>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
@ -1,50 +1,67 @@
|
||||
{% extends 'base.html.twig' %}
|
||||
|
||||
{% block title %}User{% endblock %}
|
||||
{% block title %}Utilisateur{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<h1>User</h1>
|
||||
<h1>Détails de l'utilisateur</h1>
|
||||
|
||||
<table class="table">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>Id</th>
|
||||
<td>{{ user.id }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Email</th>
|
||||
<td>{{ user.email }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>FirstName</th>
|
||||
<td>{{ user.FirstName }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>LastName</th>
|
||||
<td>{{ user.LastName }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>BirthDate</th>
|
||||
<td>{{ user.BirthDate ? user.BirthDate|date('Y-m-d') : '' }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Phone</th>
|
||||
<td>{{ user.Phone }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Roles</th>
|
||||
<td>{{ user.roles ? user.roles|json_encode : '' }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Password</th>
|
||||
<td>{{ user.password }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Id</th>
|
||||
<td>{{ user.id }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Email</th>
|
||||
<td>{{ user.email }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Prénom</th>
|
||||
<td>{{ user.FirstName }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Nom</th>
|
||||
<td>{{ user.LastName }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Date de naissance</th>
|
||||
<td>{{ user.BirthDate ? user.BirthDate|date('Y-m-d') : '' }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Téléphone</th>
|
||||
<td>{{ user.Phone }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Rôles</th>
|
||||
<td>
|
||||
{% if user.roles %}
|
||||
<ul>
|
||||
{% for role in user.roles %}
|
||||
<li>{{ role }}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Compétences</th>
|
||||
<td>
|
||||
{% if user.skills|length > 0 %}
|
||||
<ul>
|
||||
{% for skill in user.skills %}
|
||||
<li>{{ skill.Wording }}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% else %}
|
||||
Aucune compétence
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<a href="{{ path('app_user_index') }}">back to list</a>
|
||||
|
||||
<a href="{{ path('app_user_edit', {'id': user.id}) }}">edit</a>
|
||||
<a href="{{ path('app_user_index') }}" class="btn btn-primary">Retour à la liste</a>
|
||||
<a href="{{ path('app_user_edit', {'id': user.id}) }}" class="btn btn-warning">Modifier</a>
|
||||
|
||||
{{ include('user/_delete_form.html.twig') }}
|
||||
{% endblock %}
|
||||
|
@ -1,13 +1,14 @@
|
||||
{% extends 'base.html.twig' %}
|
||||
|
||||
{% block title %}Edit Vehicle{% endblock %}
|
||||
{% block title %}Modifier un véhicule{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<h1>Edit Vehicle</h1>
|
||||
<h1 class="mb-4">✏️ Modifier un véhicule</h1>
|
||||
|
||||
{{ include('vehicle/_form.html.twig', {'button_label': 'Update'}) }}
|
||||
{{ include('vehicle/_form.html.twig', {'button_label': 'Mettre à jour'}) }}
|
||||
|
||||
<a href="{{ path('app_vehicle_index') }}">back to list</a>
|
||||
|
||||
{{ include('vehicle/_delete_form.html.twig') }}
|
||||
<div class="mt-3">
|
||||
<a href="{{ path('app_vehicle_index') }}" class="btn btn-secondary">← Retour à la liste</a>
|
||||
{{ include('vehicle/_delete_form.html.twig') }}
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
@ -1,18 +1,19 @@
|
||||
{% extends 'base.html.twig' %}
|
||||
|
||||
{% block title %}Vehicle index{% endblock %}
|
||||
{% block title %}Liste des véhicules{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<h1>Vehicle index</h1>
|
||||
<h1 class="mb-4">🚗 Liste des véhicules</h1>
|
||||
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Id</th>
|
||||
<th>LicensePlate</th>
|
||||
<th>Brand</th>
|
||||
<th>actions</th>
|
||||
</tr>
|
||||
<table class="table table-striped table-bordered align-middle">
|
||||
<thead class="table-dark">
|
||||
<tr>
|
||||
<th>ID</th>
|
||||
<th>Immatriculation</th>
|
||||
<th>Marque</th>
|
||||
<th>Modèle</th>
|
||||
<th class="text-center">Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for vehicle in vehicles %}
|
||||
@ -20,18 +21,19 @@
|
||||
<td>{{ vehicle.id }}</td>
|
||||
<td>{{ vehicle.LicensePlate }}</td>
|
||||
<td>{{ vehicle.Brand }}</td>
|
||||
<td>
|
||||
<a href="{{ path('app_vehicle_show', {'id': vehicle.id}) }}">show</a>
|
||||
<a href="{{ path('app_vehicle_edit', {'id': vehicle.id}) }}">edit</a>
|
||||
<td>{{ vehicle.Model }}</td>
|
||||
<td class="text-center">
|
||||
<a href="{{ path('app_vehicle_show', {'id': vehicle.id}) }}" class="btn btn-info btn-sm">👁️ Voir</a>
|
||||
<a href="{{ path('app_vehicle_edit', {'id': vehicle.id}) }}" class="btn btn-warning btn-sm">✏️ Modifier</a>
|
||||
</td>
|
||||
</tr>
|
||||
{% else %}
|
||||
<tr>
|
||||
<td colspan="4">no records found</td>
|
||||
<td colspan="5" class="text-center text-muted">Aucun véhicule enregistré.</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<a href="{{ path('app_vehicle_new') }}">Create new</a>
|
||||
<a href="{{ path('app_vehicle_new') }}" class="btn btn-success mt-3">➕ Ajouter un véhicule</a>
|
||||
{% endblock %}
|
||||
|
@ -1,11 +1,13 @@
|
||||
{% extends 'base.html.twig' %}
|
||||
|
||||
{% block title %}New Vehicle{% endblock %}
|
||||
{% block title %}Nouveau véhicule{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<h1>Create new Vehicle</h1>
|
||||
<h1 class="mb-4">➕ Ajouter un nouveau véhicule</h1>
|
||||
|
||||
{{ include('vehicle/_form.html.twig') }}
|
||||
|
||||
<a href="{{ path('app_vehicle_index') }}">back to list</a>
|
||||
<div class="mt-3">
|
||||
<a href="{{ path('app_vehicle_index') }}" class="btn btn-secondary">← Retour à la liste</a>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
@ -1,30 +1,34 @@
|
||||
{% extends 'base.html.twig' %}
|
||||
|
||||
{% block title %}Vehicle{% endblock %}
|
||||
{% block title %}Détail du véhicule{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<h1>Vehicle</h1>
|
||||
<h1 class="mb-4">🔍 Détail du véhicule</h1>
|
||||
|
||||
<table class="table">
|
||||
<table class="table table-bordered">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>Id</th>
|
||||
<td>{{ vehicle.id }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>LicensePlate</th>
|
||||
<td>{{ vehicle.LicensePlate }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Brand</th>
|
||||
<td>{{ vehicle.Brand }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>ID</th>
|
||||
<td>{{ vehicle.id }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Immatriculation</th>
|
||||
<td>{{ vehicle.LicensePlate }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Marque</th>
|
||||
<td>{{ vehicle.Brand }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Modèle</th>
|
||||
<td>{{ vehicle.Model }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<a href="{{ path('app_vehicle_index') }}">back to list</a>
|
||||
|
||||
<a href="{{ path('app_vehicle_edit', {'id': vehicle.id}) }}">edit</a>
|
||||
|
||||
{{ include('vehicle/_delete_form.html.twig') }}
|
||||
<div class="mt-3">
|
||||
<a href="{{ path('app_vehicle_index') }}" class="btn btn-secondary">← Retour à la liste</a>
|
||||
<a href="{{ path('app_vehicle_edit', {'id': vehicle.id}) }}" class="btn btn-warning">✏️ Modifier</a>
|
||||
{{ include('vehicle/_delete_form.html.twig') }}
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
Loading…
x
Reference in New Issue
Block a user