diff --git a/.idea/.gitignore b/.idea/.gitignore deleted file mode 100644 index 13566b8..0000000 --- a/.idea/.gitignore +++ /dev/null @@ -1,8 +0,0 @@ -# Default ignored files -/shelf/ -/workspace.xml -# Editor-based HTTP Client requests -/httpRequests/ -# Datasource local storage ignored files -/dataSources/ -/dataSources.local.xml diff --git a/compose.override.yaml b/compose.override.yaml index 8dc54de..fc37713 100644 --- a/compose.override.yaml +++ b/compose.override.yaml @@ -1,4 +1,3 @@ - services: ###> doctrine/doctrine-bundle ### database: @@ -16,3 +15,4 @@ services: MP_SMTP_AUTH_ACCEPT_ANY: 1 MP_SMTP_AUTH_ALLOW_INSECURE: 1 ###< symfony/mailer ### + diff --git a/compose.yaml b/compose.yaml index 89c74d1..3bc2b6e 100644 --- a/compose.yaml +++ b/compose.yaml @@ -1,13 +1,12 @@ - services: ###> doctrine/doctrine-bundle ### database: image: postgres:${POSTGRES_VERSION:-16}-alpine environment: - POSTGRES_DB: ${POSTGRES_DB:-app} + POSTGRES_DB: ${POSTGRES_DB:-hegresphere} # You should definitely change the password in production - POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-!ChangeMe!} - POSTGRES_USER: ${POSTGRES_USER:-app} + POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-Btssio2024} + POSTGRES_USER: ${POSTGRES_USER:-bourgoino} healthcheck: test: ["CMD", "pg_isready", "-d", "${POSTGRES_DB:-app}", "-U", "${POSTGRES_USER:-app}"] timeout: 5s @@ -23,3 +22,4 @@ volumes: ###> doctrine/doctrine-bundle ### database_data: ###< doctrine/doctrine-bundle ### + diff --git a/composer.json b/composer.json index 6cda857..eaf6016 100644 --- a/composer.json +++ b/composer.json @@ -42,8 +42,10 @@ "symfony/validator": "7.1.*", "symfony/web-link": "7.1.*", "symfony/yaml": "7.1.*", + "symfonycasts/sass-bundle": "^0.7.0", "twig/extra-bundle": "^2.12|^3.0", - "twig/twig": "^2.12|^3.0" + "twig/twig": "^2.12|^3.0", + "ext-http": "*" }, "config": { "allow-plugins": { @@ -100,7 +102,7 @@ "symfony/browser-kit": "7.1.*", "symfony/css-selector": "7.1.*", "symfony/debug-bundle": "7.1.*", - "symfony/maker-bundle": "^1.0", + "symfony/maker-bundle": "^1.61", "symfony/phpunit-bridge": "^7.1", "symfony/stopwatch": "7.1.*", "symfony/web-profiler-bundle": "7.1.*" diff --git a/composer.lock b/composer.lock index 78aceec..466f205 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "1bc99d81c026aaf4e662ffffde457d04", + "content-hash": "39f4377209acc13ab9e977a5301faef0", "packages": [ { "name": "composer/semver", @@ -7423,6 +7423,61 @@ ], "time": "2025-01-07T12:50:05+00:00" }, + { + "name": "symfonycasts/sass-bundle", + "version": "v0.7.0", + "source": { + "type": "git", + "url": "https://github.com/SymfonyCasts/sass-bundle.git", + "reference": "d88601c50eff716d9273dffbd736adefdc19e2fc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/SymfonyCasts/sass-bundle/zipball/d88601c50eff716d9273dffbd736adefdc19e2fc", + "reference": "d88601c50eff716d9273dffbd736adefdc19e2fc", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "symfony/asset-mapper": "^6.3|^7.0", + "symfony/console": "^5.4|^6.3|^7.0", + "symfony/filesystem": "^5.4|^6.3|^7.0", + "symfony/http-client": "^5.4|^6.3|^7.0", + "symfony/process": "^5.4|^6.3|^7.0" + }, + "require-dev": { + "matthiasnoback/symfony-config-test": "^5.0", + "phpstan/phpstan-symfony": "^1.4", + "symfony/framework-bundle": "^6.3|^7.0", + "symfony/phpunit-bridge": "^6.3|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfonycasts\\SassBundle\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mathéo Daninos", + "homepage": "https://github.com/WebMamba" + } + ], + "description": "Delightful Sass Support for Symfony + AssetMapper", + "keywords": [ + "asset-mapper", + "sass" + ], + "support": { + "issues": "https://github.com/SymfonyCasts/sass-bundle/issues", + "source": "https://github.com/SymfonyCasts/sass-bundle/tree/v0.7.0" + }, + "time": "2024-05-22T14:59:07+00:00" + }, { "name": "twig/extra-bundle", "version": "v3.21.0", @@ -9914,7 +9969,7 @@ ], "aliases": [], "minimum-stability": "stable", - "stability-flags": {}, + "stability-flags": [], "prefer-stable": true, "prefer-lowest": false, "platform": { @@ -9922,6 +9977,6 @@ "ext-ctype": "*", "ext-iconv": "*" }, - "platform-dev": {}, - "plugin-api-version": "2.6.0" + "platform-dev": [], + "plugin-api-version": "2.3.0" } diff --git a/config/bundles.php b/config/bundles.php index 4e3a560..1ebcba9 100644 --- a/config/bundles.php +++ b/config/bundles.php @@ -13,4 +13,5 @@ return [ Symfony\Bundle\SecurityBundle\SecurityBundle::class => ['all' => true], Symfony\Bundle\MonologBundle\MonologBundle::class => ['all' => true], Symfony\Bundle\MakerBundle\MakerBundle::class => ['dev' => true], + Symfonycasts\SassBundle\SymfonycastsSassBundle::class => ['all' => true], ]; diff --git a/config/packages/security.yaml b/config/packages/security.yaml index 2f23ef7..9a7f3a1 100644 --- a/config/packages/security.yaml +++ b/config/packages/security.yaml @@ -1,7 +1,7 @@ security: # https://symfony.com/doc/current/security.html#registering-the-user-hashing-passwords password_hashers: - Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface: 'plaintext' # à mettre en auto pour sécuriser les mdp + Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface: 'auto' # à mettre en auto pour sécuriser les mdp # https://symfony.com/doc/current/security.html#loading-the-user-the-user-provider providers: # used to reload user from session & other features (e.g. switch_user) diff --git a/config/services.yaml b/config/services.yaml index 2d6a76f..f77bd4b 100644 --- a/config/services.yaml +++ b/config/services.yaml @@ -4,7 +4,8 @@ # Put parameters here that don't need to change on each machine where the app is deployed # https://symfony.com/doc/current/best_practices.html#use-parameters-for-application-configuration parameters: - + app.jwtsecret : '%env(JWT_SECRET)%' + cv_directory: '%kernel.project_dir%/public/cv' services: # default configuration for services in *this* file _defaults: diff --git a/public/js/map.js b/public/js/map.js new file mode 100644 index 0000000..ae168ad --- /dev/null +++ b/public/js/map.js @@ -0,0 +1,7 @@ + + +// initialize the map on the "map" div with a given center and zoom +var map = L.map('map', { + center: [51.505, -0.09], + zoom: 13 +}); diff --git a/src/Controller/AnnouncementController.php b/src/Controller/AnnouncementController.php index 699d90b..31c6513 100644 --- a/src/Controller/AnnouncementController.php +++ b/src/Controller/AnnouncementController.php @@ -5,6 +5,7 @@ namespace App\Controller; use App\Entity\Announcement; use App\Form\AnnouncementType; use App\Repository\AnnouncementRepository; +use App\Repository\InternApplicationRepository; use Doctrine\ORM\EntityManagerInterface; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Request; @@ -14,13 +15,17 @@ use Symfony\Component\Routing\Attribute\Route; #[Route('/announcement')] final class AnnouncementController extends AbstractController { + + public function __construct( + private readonly EntityManagerInterface $entityManager, + private readonly AnnouncementRepository $announcementRepository, + ){} #[Route('/', name: 'app_announcement_index')] - public function list(Request $request, AnnouncementRepository $announcementRepository): Response + public function list(Request $request,): Response { $user = $this->getUser(); $announcements = []; - // Récupérer les paramètres de recherche $companyName = $request->query->get('company_name'); $location = $request->query->get('location'); $category = $request->query->get('category'); @@ -29,9 +34,9 @@ final class AnnouncementController extends AbstractController $showNonValidated = $request->query->get('show_non_validated'); if ($showNonValidated) { - $announcements = $announcementRepository->findBy(['status' => 'notVerified']); + $announcements = $this->announcementRepository->findBy(['status' => 'notVerified']); } else { - $announcements = $announcementRepository->findAll(); + $announcements = $this->announcementRepository->findAll(); } } @@ -39,28 +44,37 @@ final class AnnouncementController extends AbstractController $company = $user->getCompany(); if ($company) { - $announcements = $announcementRepository->findBy(['company' => $company]); + $announcements = $this->announcementRepository->findBy(['company' => $company]); } } if (in_array('ROLE_INTERN', $user->getRoles())) { - $announcements = $announcementRepository->findBy(['status' => 'Verified']); + $announcements = $this->announcementRepository->findBy(['status' => 'Verified']); } - // Filtrer les annonces en fonction des critères de recherche if ($companyName || $location || $category) { - $announcements = $announcementRepository->searchAnnouncements($companyName, $location, $category); + $announcements = $this->announcementRepository->searchAnnouncements($companyName, $location, $category); + } + + $favorites = []; + if (in_array('ROLE_INTERN', $user->getRoles())) { + $favorites = array_map( + fn($f) => $f->getAnnouncement()->getId(), + $user->getFavorites()->toArray() + ); } return $this->render('announcement/index.html.twig', [ 'announcements' => $announcements, + 'favorites' => $favorites, 'showNonValidated' => $request->query->get('show_non_validated', false), ]); } + #[Route('/new', name: 'app_announcement_new', methods: ['GET', 'POST'])] - public function new(Request $request, EntityManagerInterface $entityManager): Response + public function new(Request $request,): Response { /*$user = $this->getUser(); @@ -81,8 +95,8 @@ final class AnnouncementController extends AbstractController if ($form->isSubmitted() && $form->isValid()) { $announcement->setCreationDate(new \DateTime()); $announcement->setStatus('notVerified'); - $entityManager->persist($announcement); - $entityManager->flush(); + $this->entityManager->persist($announcement); + $this->entityManager->flush(); return $this->redirectToRoute('app_announcement_index', [], Response::HTTP_SEE_OTHER); } @@ -102,13 +116,13 @@ final class AnnouncementController extends AbstractController } #[Route('/{id}/edit', name: 'app_announcement_edit', methods: ['GET', 'POST'])] - public function edit(Request $request, Announcement $announcement, EntityManagerInterface $entityManager): Response + public function edit(Request $request, Announcement $announcement,): Response { $form = $this->createForm(AnnouncementType::class, $announcement); $form->handleRequest($request); if ($form->isSubmitted() && $form->isValid()) { - $entityManager->flush(); + $this->entityManager->flush(); return $this->redirectToRoute('app_announcement_index', [], Response::HTTP_SEE_OTHER); } @@ -120,23 +134,23 @@ final class AnnouncementController extends AbstractController } #[Route('/{id}', name: 'app_announcement_delete', methods: ['POST'])] - public function delete(Request $request, Announcement $announcement, EntityManagerInterface $entityManager): Response + public function delete(Request $request, Announcement $announcement,): Response { if ($this->isCsrfTokenValid('delete'.$announcement->getId(), $request->getPayload()->getString('_token'))) { - $entityManager->remove($announcement); - $entityManager->flush(); + $this->entityManager->remove($announcement); + $this->entityManager->flush(); } return $this->redirectToRoute('app_announcement_index', [], Response::HTTP_SEE_OTHER); } #[Route('/{id}/validate', name: 'app_announcement_validate', methods: ['POST'])] - public function validate(Request $request, Announcement $announcement, EntityManagerInterface $entityManager): Response + public function validate(Request $request, Announcement $announcement,): Response { if ($announcement->getStatus() !== 'Verified') { $announcement->setStatus('Verified'); - $entityManager->flush(); + $this->entityManager->flush(); } return $this->redirectToRoute('app_announcement_show', ['id' => $announcement->getId()], Response::HTTP_SEE_OTHER); diff --git a/src/Controller/CompanyController.php b/src/Controller/CompanyController.php index 55cfd87..b729d8a 100644 --- a/src/Controller/CompanyController.php +++ b/src/Controller/CompanyController.php @@ -4,7 +4,9 @@ namespace App\Controller; use App\Entity\Company; use App\Form\CompanyType; +use App\Repository\AnnouncementRepository; use App\Repository\CompanyRepository; +use App\Repository\InternApplicationRepository; use Doctrine\ORM\EntityManagerInterface; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Request; @@ -15,25 +17,29 @@ use Symfony\Component\Security\Http\Attribute\IsGranted; #[Route('/company')] final class CompanyController extends AbstractController { + public function __construct( + private readonly EntityManagerInterface $entityManager, + private readonly CompanyRepository $companyRepository, + ){} #[Route(name: 'app_company_index', methods: ['GET'])] - public function index(CompanyRepository $companyRepository): Response + public function index(): Response { return $this->render('company/index.html.twig', [ - 'companies' => $companyRepository->findAll(), + 'companies' => $this->companyRepository->findAll(), ]); } #[Route('/new', name: 'app_company_new', methods: ['GET', 'POST'])] #[IsGranted('ROLE_ADMIN')] - public function new(Request $request, EntityManagerInterface $entityManager): Response + public function new(Request $request,): Response { $company = new Company(); $form = $this->createForm(CompanyType::class, $company); $form->handleRequest($request); if ($form->isSubmitted() && $form->isValid()) { - $entityManager->persist($company); - $entityManager->flush(); + $this->entityManager->persist($company); + $this->entityManager->flush(); return $this->redirectToRoute('app_company_index', [], Response::HTTP_SEE_OTHER); } @@ -54,13 +60,13 @@ final class CompanyController extends AbstractController #[Route('/{id}/edit', name: 'app_company_edit', methods: ['GET', 'POST'])] #[IsGranted('ROLE_ADMIN')] - public function edit(Request $request, Company $company, EntityManagerInterface $entityManager): Response + public function edit(Request $request, Company $company,): Response { $form = $this->createForm(CompanyType::class, $company); $form->handleRequest($request); if ($form->isSubmitted() && $form->isValid()) { - $entityManager->flush(); + $this->entityManager->flush(); return $this->redirectToRoute('app_company_index', [], Response::HTTP_SEE_OTHER); } @@ -72,11 +78,11 @@ final class CompanyController extends AbstractController } #[Route('/{id}', name: 'app_company_delete', methods: ['POST'])] - public function delete(Request $request, Company $company, EntityManagerInterface $entityManager): Response + public function delete(Request $request, Company $company,): Response { if ($this->isCsrfTokenValid('delete'.$company->getId(), $request->getPayload()->getString('_token'))) { - $entityManager->remove($company); - $entityManager->flush(); + $this->entityManager->remove($company); + $this->entityManager->flush(); } return $this->redirectToRoute('app_company_index', [], Response::HTTP_SEE_OTHER); diff --git a/src/Controller/DegreeController.php b/src/Controller/DegreeController.php index d4e2469..8b855b0 100644 --- a/src/Controller/DegreeController.php +++ b/src/Controller/DegreeController.php @@ -5,7 +5,9 @@ namespace App\Controller; use App\Entity\Degree; use App\Entity\InternDegree; use App\Form\DegreeType; +use App\Repository\AnnouncementRepository; use App\Repository\DegreeRepository; +use App\Repository\InternApplicationRepository; use Doctrine\ORM\EntityManagerInterface; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Request; @@ -15,24 +17,28 @@ use Symfony\Component\Routing\Attribute\Route; #[Route('/degree')] final class DegreeController extends AbstractController { + public function __construct( + private readonly EntityManagerInterface $entityManager, + private readonly DegreeRepository $degreeRepository, + ){} #[Route(name: 'app_degree_index', methods: ['GET'])] - public function index(DegreeRepository $degreeRepository): Response + public function index(): Response { return $this->render('degree/index.html.twig', [ - 'degrees' => $degreeRepository->findAll(), + 'degrees' => $this->degreeRepository->findAll(), ]); } #[Route('/new', name: 'app_degree_new', methods: ['GET', 'POST'])] - public function new(Request $request, EntityManagerInterface $entityManager): Response + public function new(Request $request,): Response { $degree = new Degree(); $form = $this->createForm(DegreeType::class, $degree); $form->handleRequest($request); if ($form->isSubmitted() && $form->isValid()) { - $entityManager->persist($degree); - $entityManager->flush(); + $this->entityManager->persist($degree); + $this->entityManager->flush(); return $this->redirectToRoute('app_degree_index', [], Response::HTTP_SEE_OTHER); } @@ -52,13 +58,13 @@ final class DegreeController extends AbstractController } #[Route('/{id}/edit', name: 'app_degree_edit', methods: ['GET', 'POST'])] - public function edit(Request $request, Degree $degree, EntityManagerInterface $entityManager): Response + public function edit(Request $request, Degree $degree,): Response { $form = $this->createForm(DegreeType::class, $degree); $form->handleRequest($request); if ($form->isSubmitted() && $form->isValid()) { - $entityManager->flush(); + $this->entityManager->flush(); return $this->redirectToRoute('app_degree_index', [], Response::HTTP_SEE_OTHER); } @@ -70,11 +76,11 @@ final class DegreeController extends AbstractController } #[Route('/{id}', name: 'app_degree_delete', methods: ['POST'])] - public function delete(Request $request, Degree $degree, EntityManagerInterface $entityManager): Response + public function delete(Request $request, Degree $degree,): Response { if ($this->isCsrfTokenValid('delete'.$degree->getId(), $request->getPayload()->getString('_token'))) { - $entityManager->remove($degree); - $entityManager->flush(); + $this->entityManager->remove($degree); + $this->entityManager->flush(); } return $this->redirectToRoute('app_degree_index', [], Response::HTTP_SEE_OTHER); diff --git a/src/Controller/EmployeeController.php b/src/Controller/EmployeeController.php index 0498378..6d7cd17 100644 --- a/src/Controller/EmployeeController.php +++ b/src/Controller/EmployeeController.php @@ -33,7 +33,7 @@ final class EmployeeController extends AbstractController ]); } - #[Route('/{id}', name: 'app_employee_show', methods: ['GET'])] + #[Route('/{id}', name: 'app_employee_show', requirements: ['id' => '\d+'], methods: ['GET'])] public function show(Employee $employee): Response { return $this->render('employee/show.html.twig', [ @@ -41,7 +41,7 @@ final class EmployeeController extends AbstractController ]); } - #[Route('/{id}/edit', name: 'app_employee_edit', methods: ['GET', 'POST'])] + #[Route('/{id}/edit', name: 'app_employee_edit', requirements: ['id' => '\d+'], methods: ['GET', 'POST'])] public function edit(Request $request, Employee $employee): Response { $form = $this->createForm(EmployeeType::class, $employee); @@ -59,7 +59,7 @@ final class EmployeeController extends AbstractController ]); } - #[Route('/{id}', name: 'app_employee_delete', methods: ['POST'])] + #[Route('/{id}', name: 'app_employee_delete', requirements: ['id' => '\d+'], methods: ['POST'])] public function delete(Request $request, Employee $employee): Response { if ($this->isCsrfTokenValid('delete'.$employee->getId(), $request->getPayload()->getString('_token'))) { @@ -70,7 +70,7 @@ final class EmployeeController extends AbstractController return $this->redirectToRoute('app_employee_index', [], Response::HTTP_SEE_OTHER); } - #[Route('/seeApplications', name: 'app_employee_applications')] + #[Route('/seeApplications', name: 'app_employee_seeApplications')] public function seeApplications(): Response { $employee = $this->getUser(); @@ -85,12 +85,38 @@ final class EmployeeController extends AbstractController ->findBy(['company' => $company]); $applications = $this->internApplicationRepository - ->findBy(['announcement' => $announcements]); + ->findBy(['application' => $announcements]); return $this->render('employee/applications.html.twig', [ 'applications' => $applications, ]); } + #[Route('/application/{id}/update-status/{status}', name: 'app_employee_update_application_status', methods: ['POST'])] + public function updateApplicationStatus(int $id, string $status): Response + { + $employee = $this->getUser(); + if (!$employee instanceof Employee) { + throw $this->createAccessDeniedException('Seuls les employés peuvent accéder à cette action.'); + } + + $application = $this->internApplicationRepository->find($id); + + if (!$application) { + throw $this->createNotFoundException('Candidature introuvable.'); + } + + $company = $employee->getCompany(); + if ($application->getApplication()->getCompany() !== $company) { + throw $this->createAccessDeniedException('Cette candidature ne vous appartient pas.'); + } + + $application->setStatus($status); + $this->entityManager->flush(); + + $this->addFlash('success', 'Le statut de la candidature a bien été mis à jour.'); + + return $this->redirectToRoute('app_employee_seeApplications'); + } } diff --git a/src/Controller/FAQController.php b/src/Controller/FAQController.php index d8db205..15ba076 100644 --- a/src/Controller/FAQController.php +++ b/src/Controller/FAQController.php @@ -4,7 +4,9 @@ namespace App\Controller; use App\Entity\FAQ; use App\Form\FAQType; +use App\Repository\AnnouncementRepository; use App\Repository\FAQRepository; +use App\Repository\InternApplicationRepository; use Doctrine\ORM\EntityManagerInterface; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Request; @@ -15,17 +17,21 @@ use Symfony\Component\Security\Http\Attribute\IsGranted; #[Route('/faq')] final class FAQController extends AbstractController { + public function __construct( + private readonly EntityManagerInterface $entityManager, + private readonly FaqRepository $faqRepository, + ){} #[Route(name: 'app_faq_index', methods: ['GET'])] - public function index(FAQRepository $fAQRepository): Response + public function index(): Response { return $this->render('faq/index.html.twig', [ - 'faqs' => $fAQRepository->findAll(), + 'faqs' => $this->faqRepository->findAll(), ]); } #[Route('/new', name: 'app_faq_new', methods: ['GET', 'POST'])] #[IsGranted('ROLE_ADMIN')] - public function new(Request $request, EntityManagerInterface $entityManager): Response + public function new(Request $request,): Response { $fAQ = new FAQ(); $form = $this->createForm(FAQType::class, $fAQ); @@ -33,8 +39,8 @@ final class FAQController extends AbstractController if ($form->isSubmitted() && $form->isValid()) { $fAQ->setUpdateDate(new \DateTime()); - $entityManager->persist($fAQ); - $entityManager->flush(); + $this->entityManager->persist($fAQ); + $this->entityManager->flush(); return $this->redirectToRoute('app_faq_index', [], Response::HTTP_SEE_OTHER); } @@ -55,14 +61,14 @@ final class FAQController extends AbstractController #[Route('/{id}/edit', name: 'app_faq_edit', methods: ['GET', 'POST'])] #[IsGranted('ROLE_ADMIN')] - public function edit(Request $request, FAQ $fAQ, EntityManagerInterface $entityManager): Response + public function edit(Request $request, FAQ $fAQ,): Response { $form = $this->createForm(FAQType::class, $fAQ); $form->handleRequest($request); if ($form->isSubmitted() && $form->isValid()) { $fAQ->setUpdateDate(new \DateTime()); - $entityManager->flush(); + $this->entityManager->flush(); return $this->redirectToRoute('app_faq_index', [], Response::HTTP_SEE_OTHER); } @@ -75,11 +81,11 @@ final class FAQController extends AbstractController #[Route('/{id}', name: 'app_faq_delete', methods: ['POST'])] #[IsGranted('ROLE_ADMIN')] - public function delete(Request $request, FAQ $fAQ, EntityManagerInterface $entityManager): Response + public function delete(Request $request, FAQ $fAQ,): Response { if ($this->isCsrfTokenValid('delete'.$fAQ->getId(), $request->getPayload()->getString('_token'))) { - $entityManager->remove($fAQ); - $entityManager->flush(); + $this->entityManager->remove($fAQ); + $this->entityManager->flush(); } return $this->redirectToRoute('app_faq_index', [], Response::HTTP_SEE_OTHER); diff --git a/src/Controller/IndexController.php b/src/Controller/IndexController.php index 5cce937..4e6491e 100644 --- a/src/Controller/IndexController.php +++ b/src/Controller/IndexController.php @@ -3,7 +3,9 @@ namespace App\Controller; use App\Entity\UserApp; +use App\Repository\AnnouncementRepository; use App\Repository\CompanyRepository; +use App\Repository\InternApplicationRepository; use Doctrine\ORM\EntityManagerInterface; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Response; diff --git a/src/Controller/InternController.php b/src/Controller/InternController.php index ff4b627..52d4de7 100644 --- a/src/Controller/InternController.php +++ b/src/Controller/InternController.php @@ -7,22 +7,43 @@ use App\Entity\Degree; use App\Entity\Intern; use App\Entity\InternApplication; use App\Entity\InternDegree; +use App\Entity\InternSkill; +use App\Entity\Skill; use App\Form\InternType; +use App\Repository\AnnouncementRepository; +use App\Repository\DegreeRepository; +use App\Repository\InternApplicationRepository; +use App\Repository\InternDegreeRepository; use App\Repository\InternRepository; +use App\Repository\InternSkillRepository; +use App\Repository\SkillRepository; use Doctrine\ORM\EntityManagerInterface; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; +use Symfony\Component\DependencyInjection\Attribute\Autowire; +use Symfony\Component\Form\Extension\Core\Type\FileType; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Routing\Attribute\Route; +use Symfony\Component\Validator\Constraints\File; #[Route('/intern')] final class InternController extends AbstractController { + public function __construct( + private readonly EntityManagerInterface $entityManager, + private readonly AnnouncementRepository $announcementRepository, + private readonly InternRepository $internRepository, + private readonly InternApplicationRepository $internApplicationRepository, + private readonly InternDegreeRepository $internDegreeRepository, + private readonly InternSkillRepository $internSkillRepository, + private readonly DegreeRepository $degreeRepository, + private readonly SkillRepository $skillRepository, + ){} #[Route(name: 'app_intern_index', methods: ['GET'])] - public function index(InternRepository $internRepository): Response + public function index(): Response { return $this->render('intern/index.html.twig', [ - 'interns' => $internRepository->findAll(), + 'interns' => $this->internRepository->findAll(), ]); } @@ -35,13 +56,13 @@ final class InternController extends AbstractController } #[Route('/{id}/edit', name: 'app_intern_edit', methods: ['GET', 'POST'])] - public function edit(Request $request, Intern $intern, EntityManagerInterface $entityManager): Response + public function edit(Request $request, Intern $intern,): Response { $form = $this->createForm(InternType::class, $intern); $form->handleRequest($request); if ($form->isSubmitted() && $form->isValid()) { - $entityManager->flush(); + $this->entityManager->flush(); return $this->redirectToRoute('app_intern_index', [], Response::HTTP_SEE_OTHER); } @@ -52,19 +73,76 @@ final class InternController extends AbstractController ]); } + #[Route('/{id}/resume', name: 'app_intern_resume', methods: ['GET', 'POST'])] + public function addResume(Request $request, Intern $intern, EntityManagerInterface $entityManager, #[Autowire('%cv_directory%')] string $cvDirectory): Response + { + // Création d'un formulaire spécifique pour le CV plutôt que d'utiliser InternType entier + $form = $this->createFormBuilder($intern) + ->add('resume', FileType::class, [ + 'label' => 'CV : ', + 'mapped' => false, // Ne pas lier directement à l'entité + 'constraints' => [ + new File([ + 'maxSize' => '1024k', + 'mimeTypes' => [ + 'application/pdf', + 'application/x-pdf', + ], + 'mimeTypesMessage' => 'Merci de bien vouloir envoyer un fichier PDF valide.', + ]) + ], + ]) + ->getForm(); + + $form->handleRequest($request); + + if ($form->isSubmitted() && $form->isValid()) { + $cvFile = $form->get('resume')->getData(); + + if ($cvFile) { + // Génération d'un nom de fichier unique + $newFilename = $intern->getId().'_'.date("d-m-Y").'_'.random_int(0,99999999).'.pdf'; + + // Déplacement vers le répertoire de stockage + $cvFile->move( + $cvDirectory, + $newFilename + ); + + if($intern->getResume() !== null){ + unlink($cvDirectory.'/'.$intern->getResume()); + } + + // Mise à jour de l'entité avec le nom du fichier + $intern->setResume($newFilename); + $intern->setResumeName($cvFile->getClientOriginalName()); // Conserver le nom original du fichier + } + + $entityManager->flush(); + + return $this->redirectToRoute('app_profile', [], Response::HTTP_SEE_OTHER); + } + + return $this->render('intern/resume.html.twig', [ + 'intern' => $intern, + 'form' => $form->createView(), + ]); + } + + #[Route('/{id}', name: 'app_intern_delete', methods: ['POST'])] - public function delete(Request $request, Intern $intern, EntityManagerInterface $entityManager): Response + public function delete(Request $request, Intern $intern,): Response { if ($this->isCsrfTokenValid('delete'.$intern->getId(), $request->getPayload()->getString('_token'))) { - $entityManager->remove($intern); - $entityManager->flush(); + $this->entityManager->remove($intern); + $this->entityManager->flush(); } return $this->redirectToRoute('app_intern_index', [], Response::HTTP_SEE_OTHER); } #[Route('/degrees/add', name:'app_intern_add_degrees', methods:['POST'])] - public function addDegrees(Request $request, EntityManagerInterface $entityManager): Response + public function addDegrees(Request $request): Response { $intern = $this->getUser(); @@ -79,17 +157,14 @@ final class InternController extends AbstractController return $this->redirectToRoute('app_degree_index'); } - $degreeRepository = $entityManager->getRepository(Degree::class); - $internDegreeRepository = $entityManager->getRepository(InternDegree::class); - foreach ($selectedDegreeIds as $degreeId) { - $degree = $degreeRepository->find($degreeId); + $degree = $this->degreeRepository->find($degreeId); if (!$degree) { continue; } - $existingInternDegree = $internDegreeRepository->findOneBy([ + $existingInternDegree = $this->internDegreeRepository->findOneBy([ 'intern' => $intern, 'degree' => $degree ]); @@ -100,11 +175,11 @@ final class InternController extends AbstractController $internDegree->setDegree($degree); $internDegree->setGraduationDate(new \DateTime()); - $entityManager->persist($internDegree); + $this->entityManager->persist($internDegree); } } - $entityManager->flush(); + $this->entityManager->flush(); $this->addFlash('success', 'Les diplômes ont été ajoutés avec succès.'); @@ -112,20 +187,17 @@ final class InternController extends AbstractController } #[Route('/application/send', name:'app_intern_send_application', methods:['POST'])] - public function sendApplication(Request $request, EntityManagerInterface $entityManager): Response + public function sendApplication(Request $request,): Response { $intern = $this->getUser(); if (!$intern instanceof Intern) { throw $this->createAccessDeniedException("Seuls les stagiaires peuvent envoyer des candidatures."); } - $announcementRepository = $entityManager->getRepository(Announcement::class); - $internApplicationRepository = $entityManager->getRepository(InternApplication::class); - $announcementId = $request->request->get('announcement_id'); - $announcement = $announcementRepository->find($announcementId); + $announcement = $this->announcementRepository->find($announcementId); - $existingInternApplication = $internApplicationRepository->findOneBy([ + $existingInternApplication = $this->internApplicationRepository->findOneBy([ 'intern' => $intern, 'application' => $announcement ]); @@ -137,13 +209,56 @@ final class InternController extends AbstractController $internApplication->setApplicationDate(new \DateTime()); $internApplication->setStatus("En Attente"); - $entityManager->persist($internApplication); + $this->entityManager->persist($internApplication); } - $entityManager->flush(); + $this->entityManager->flush(); $this->addFlash('success', 'La candidature à bien été envoyée.'); return $this->redirectToRoute('app_profile'); } + + #[Route('/skills/add', name:'app_intern_add_skills', methods:['POST'])] + public function addSkills(Request $request,): Response + { + $intern = $this->getUser(); + + if (!$intern instanceof Intern) { + throw $this->createAccessDeniedException("Seuls les stagiaires peuvent sélectionner des compétences."); + } + + $selectedSkillIds = $request->request->all('selected_skills'); + + if ($selectedSkillIds == []) { + $this->addFlash('error', "Aucune sélection valide n'a été effectuée."); + return $this->redirectToRoute('app_skill_index'); + } + + foreach ($selectedSkillIds as $skillId) { + $skill = $this->skillRepository->find($skillId); + + if (!$skill) continue; + + $existingInternSkill = $this->internSkillRepository->findOneBy([ + 'intern' => $intern, + 'skill' => $skill + ]); + + if (!$existingInternSkill) { + $internSkill = new InternSkill(); + $internSkill->setIntern($intern); + $internSkill->setSkill($skill); + + $this->entityManager->persist($internSkill); + } + } + + $this->entityManager->flush(); + + $this->addFlash('success', 'Les compétences ont été ajoutées avec succès.'); + + return $this->redirectToRoute('app_profile'); + } + } diff --git a/src/Controller/InternFavoriteController.php b/src/Controller/InternFavoriteController.php new file mode 100644 index 0000000..c4d95f1 --- /dev/null +++ b/src/Controller/InternFavoriteController.php @@ -0,0 +1,138 @@ +getUser(); + + $existing = $this->internFavoriteRepository->findOneBy([ + 'intern' => $intern, + 'announcement' => $announcement + ]); + + if ($existing) { + $this->entityManager->remove($existing); + } else { + $favorite = new InternFavorite(); + $favorite->setIntern($intern); + $favorite->setAnnouncement($announcement); + $this->entityManager->persist($favorite); + } + + $this->entityManager->flush(); + + return $this->redirectToRoute('app_announcement_index'); + } + + #[Route('/announcement/{id}/favorite/toggle', name: 'app_favorite_toggle', methods: ['POST'])] + public function toggle(Announcement $announcement,Security $security): RedirectResponse + { + $user = $this->getUser(); + + if (!$user instanceof Intern) { + throw new AccessDeniedHttpException('Seuls les stagiaires peuvent ajouter aux favoris.'); + } + + $favorite = $this->entityManager->getRepository(InternFavorite::class)->findOneBy([ + 'intern' => $user, + 'announcement' => $announcement + ]); + + if ($favorite) { + $this->entityManager->remove($favorite); + } else { + $favorite = new InternFavorite(); + $favorite->setIntern($user); + $favorite->setAnnouncement($announcement); + $this->entityManager->persist($favorite); + } + + $this->entityManager->flush(); + + return new RedirectResponse($_SERVER['HTTP_REFERER'] ?? '/'); + } + + #[Route('/announcement/{id}', name: 'app_announcement_show')] + public function show(Announcement $announcement,): Response + { + $user = $this->getUser(); + $isFavorite = false; + + if (in_array('ROLE_INTERN', $user->getRoles())) { + $favorite = $this->internFavoriteRepository->findOneBy([ + 'announcement' => $announcement, + 'intern' => $user, + ]); + + $isFavorite = $favorite ? true : false; + } + + return $this->render('announcement/show.html.twig', [ + 'announcement' => $announcement, + 'isFavorite' => $isFavorite, + ]); + } + + #[Route('/favorite/add/{id}', name: 'app_favorite_add')] + public function addFavorite(Announcement $announcement,): Response + { + $user = $this->getUser(); + + // Vérifier si l'intern a déjà ce favori + $existingFavorite = $this->entityManager->getRepository(InternFavorite::class)->findOneBy([ + 'announcement' => $announcement, + 'intern' => $user, + ]); + + if (!$existingFavorite) { + $favorite = new InternFavorite(); + $favorite->setAnnouncement($announcement); + $favorite->setIntern($user); + + $this->entityManager->persist($favorite); + $this->entityManager->flush(); + } + + return $this->redirectToRoute('app_announcement_show', ['id' => $announcement->getId()]); + } + + #[Route('/favorite/remove/{id}', name: 'app_favorite_remove')] + public function removeFavorite(Announcement $announcement,): Response + { + $user = $this->getUser(); + + $favorite = $this->entityManager->getRepository(InternFavorite::class)->findOneBy([ + 'announcement' => $announcement, + 'intern' => $user, + ]); + + if ($favorite) { + $this->entityManager->remove($favorite); + $this->entityManager->flush(); + } + + return $this->redirectToRoute('app_announcement_show', ['id' => $announcement->getId()]); + } +} diff --git a/src/Controller/MessageController.php b/src/Controller/MessageController.php index cca62c2..13db7b5 100644 --- a/src/Controller/MessageController.php +++ b/src/Controller/MessageController.php @@ -5,22 +5,33 @@ namespace App\Controller; use App\Entity\Message; use App\Entity\UserApp; use App\Form\MessageType; +use App\Repository\AnnouncementRepository; +use App\Repository\InternSkillRepository; use App\Repository\MessageRepository; use App\Repository\UserRepository; use Doctrine\ORM\EntityManagerInterface; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException; use Symfony\Component\Routing\Attribute\Route; #[Route('/message')] final class MessageController extends AbstractController { + public function __construct( + private readonly EntityManagerInterface $entityManager, + private readonly MessageRepository $messageRepository, + private readonly UserRepository $userRepository, + ){} #[Route(name: 'app_message_index', methods: ['GET'])] - public function index(MessageRepository $messageRepository): Response + public function index(): Response { $user = $this->getUser(); - $messages = $messageRepository->findLatestMessagesByUser($user); + if (!$user instanceof UserApp) { + throw new AccessDeniedHttpException("erreur"); + } + $messages = $this->messageRepository->findLatestMessagesByUser($user); return $this->render('message/index.html.twig', [ 'messages' => $messages, @@ -28,12 +39,12 @@ final class MessageController extends AbstractController } #[Route('/conversation/{id}', name: 'app_message_conversation', methods: ['GET'])] - public function conversation(Message $message, MessageRepository $messageRepository): Response + public function conversation(Message $message,): Response { $user = $this->getUser(); $otherUser = $message->getSender() === $user ? $message->getReceiver() : $message->getSender(); - $conversation = $messageRepository->findByConversation($user, $otherUser); + $conversation = $this->messageRepository->findByConversation($user, $otherUser); return $this->render('message/conversation.html.twig', [ 'conversation' => $conversation, @@ -44,12 +55,12 @@ final class MessageController extends AbstractController #[Route('/new/{receiverId}', name: 'app_message_new', methods: ['GET', 'POST'])] - public function new(Request $request, EntityManagerInterface $entityManager, ?int $receiverId = null, UserRepository $userRepository): Response + public function new(Request $request, ?int $receiverId = null,): Response { $message = new Message(); if ($receiverId) { - $receiver = $userRepository->find($receiverId); + $receiver = $this->userRepository->find($receiverId); if ($receiver) { $message->setReceiver($receiver); } @@ -62,8 +73,8 @@ final class MessageController extends AbstractController $message->setSendingDate(new \DateTime()); $message->setSender($this->getUser()); - $entityManager->persist($message); - $entityManager->flush(); + $this->entityManager->persist($message); + $this->entityManager->flush(); return $this->redirectToRoute('app_message_index'); } @@ -82,14 +93,14 @@ final class MessageController extends AbstractController } #[Route('/{id}/edit', name: 'app_message_edit', methods: ['GET', 'POST'])] - public function edit(Request $request, Message $message, EntityManagerInterface $entityManager): Response + public function edit(Request $request, Message $message,): Response { $form = $this->createForm(MessageType::class, $message); $form->handleRequest($request); if ($form->isSubmitted() && $form->isValid()) { $message->setSendingDate(new \DateTime()); - $entityManager->flush(); + $this->entityManager->flush(); return $this->redirectToRoute('app_message_index', [], Response::HTTP_SEE_OTHER); } @@ -101,11 +112,11 @@ final class MessageController extends AbstractController } #[Route('/{id}', name: 'app_message_delete', methods: ['POST'])] - public function delete(Request $request, Message $message, EntityManagerInterface $entityManager): Response + public function delete(Request $request, Message $message,): Response { if ($this->isCsrfTokenValid('delete'.$message->getId(), $request->getPayload()->getString('_token'))) { - $entityManager->remove($message); - $entityManager->flush(); + $this->entityManager->remove($message); + $this->entityManager->flush(); } return $this->redirectToRoute('app_message_index', [], Response::HTTP_SEE_OTHER); diff --git a/src/Controller/ProfileController.php b/src/Controller/ProfileController.php index 4277747..b3211e1 100644 --- a/src/Controller/ProfileController.php +++ b/src/Controller/ProfileController.php @@ -7,6 +7,8 @@ use App\Entity\Intern; use App\Entity\InternApplication; use App\Entity\UserApp; use App\Form\UserAppType; +use App\Repository\InternApplicationRepository; +use App\Repository\SkillRepository; use Doctrine\ORM\EntityManagerInterface; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Request; @@ -15,20 +17,25 @@ use Symfony\Component\Routing\Attribute\Route; class ProfileController extends AbstractController { + public function __construct( + private readonly EntityManagerInterface $entityManager, + private readonly InternApplicationRepository $internApplicationRepository, + ){} #[Route('/profile', name: 'app_profile')] - public function profile(EntityManagerInterface $entityManager): Response + public function profile(): Response { + // Charger l'utilisateur connecté $user = $this->getUser(); + // Vérifiez les rôles si nécessaire if (!$user) { throw $this->createAccessDeniedException('Vous devez être connecté pour accéder à cette page.'); } if ($user instanceof Intern) { - $internApplicationRepository = $entityManager->getRepository(InternApplication::class); - $internApplications = $internApplicationRepository->findBy([ + $internApplications = $this->internApplicationRepository->findBy([ 'intern' => $user, ]); @@ -45,13 +52,13 @@ class ProfileController extends AbstractController } #[Route('profile/{id}/edit', name: 'app_profile_edit', methods: ['GET', 'POST'])] - public function edit(Request $request, UserApp $userApp, EntityManagerInterface $entityManager): Response + public function edit(Request $request, UserApp $userApp,): Response { $form = $this->createForm(UserAppType::class, $userApp); $form->handleRequest($request); if ($form->isSubmitted() && $form->isValid()) { - $entityManager->flush(); + $this->entityManager->flush(); return $this->redirectToRoute('app_profile', [], Response::HTTP_SEE_OTHER); } @@ -62,17 +69,17 @@ class ProfileController extends AbstractController ]); } - #[Route('/profile/{id}/visit', name: 'app_profile_visit')] - public function visitProfile(EntityManagerInterface $entityManager, int $id): Response + #[Route('/profile/visit/{id}', name: 'app_profile_visit')] + public function visitProfile(int $id): Response { - $user = $entityManager->getRepository(Intern::class)->find($id); + $candidat = $this->entityManager->getRepository(Intern::class)->find($id); - if (!$user) { + if (!$candidat) { throw $this->createNotFoundException('Utilisateur non trouvé.'); } - return $this->render('profile/index.html.twig', [ - 'user' => $user, + return $this->render('profile/visit.html.twig', [ + 'candidat' => $candidat, ]); } @@ -84,4 +91,16 @@ class ProfileController extends AbstractController 'user_app' => $userApp, ]); } + + #[Route('/profile/pickSkill', name: 'app_profile_pickSkill', methods: ['GET'])] + public function pickSkill(UserApp $userApp): Response + { + + return $this->render('skill/index.html.twig', [ + 'user_app' => $userApp, + ]); + } + + + } \ No newline at end of file diff --git a/src/Controller/RegistrationController.php b/src/Controller/RegistrationController.php index ebc0fcd..d4f5141 100644 --- a/src/Controller/RegistrationController.php +++ b/src/Controller/RegistrationController.php @@ -6,19 +6,25 @@ use App\Entity\Employee; use App\Entity\Intern; use App\Entity\UserApp; use App\Form\RegistrationFormType; +use App\Repository\InternApplicationRepository; use Doctrine\ORM\EntityManagerInterface; +use Symfony\Bridge\Doctrine\Form\Type\EntityType; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Bundle\SecurityBundle\Security; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface; use Symfony\Component\Routing\Attribute\Route; +use App\Entity\Company; #[Route('/register', name: 'app_register')] class RegistrationController extends AbstractController { + public function __construct( + private readonly EntityManagerInterface $entityManager, + ){} #[Route('/', name: '_intern')] - public function register(Request $request, UserPasswordHasherInterface $userPasswordHasher, Security $security, EntityManagerInterface $entityManager): Response + public function register(Request $request, UserPasswordHasherInterface $userPasswordHasher, Security $security): Response { $user = new Intern(); $form = $this->createForm(RegistrationFormType::class, $user); @@ -32,44 +38,52 @@ class RegistrationController extends AbstractController // encode the plain password $user->setPassword($userPasswordHasher->hashPassword($user, $plainPassword)); - $entityManager->persist($user); - $entityManager->flush(); - - // do anything else you need here, like send an email + $this->entityManager->persist($user); + $this->entityManager->flush(); return $security->login($user, 'form_login', 'main'); } return $this->render('registration/register.html.twig', [ 'registrationForm' => $form, + 'employee' => False, ]); } #[Route('/employee', name: '_employee')] - public function registerEmployee(Request $request, UserPasswordHasherInterface $userPasswordHasher, Security $security, EntityManagerInterface $entityManager): Response + public function registerEmployee(Request $request, UserPasswordHasherInterface $userPasswordHasher, Security $security): Response { $user = new Employee(); - $form = $this->createForm(RegistrationFormType::class, $user); + $form = $this->createForm(RegistrationFormType::class, $user) + ->add('company', EntityType::class, [ + 'class' => Company::class, + 'choice_label' => 'name', + 'placeholder' => 'Sélectionnez une entreprise', + 'label' => 'Entreprise', + ]); $form->handleRequest($request); if ($form->isSubmitted() && $form->isValid()) { /** @var string $plainPassword */ $plainPassword = $form->get('plainPassword')->getData(); + $company = $form->get('company')->getData(); + $user->setCompany($company); + $user->setRoles(['ROLE_EMPLOYEE']); - // encode the plain password + // Encoder le mot de passe $user->setPassword($userPasswordHasher->hashPassword($user, $plainPassword)); - $entityManager->persist($user); - $entityManager->flush(); - - // do anything else you need here, like send an email + $this->entityManager->persist($user); + $this->entityManager->flush(); return $security->login($user, 'form_login', 'main'); } return $this->render('registration/register.html.twig', [ 'registrationForm' => $form, + 'employee' => True, ]); } + } diff --git a/src/Controller/SecurityController.php b/src/Controller/SecurityController.php index 76bf5c4..ac0642b 100644 --- a/src/Controller/SecurityController.php +++ b/src/Controller/SecurityController.php @@ -2,7 +2,9 @@ namespace App\Controller; +use App\Repository\InternApplicationRepository; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; +use Symfony\Bundle\SecurityBundle\Security; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Routing\Attribute\Route; use Symfony\Component\Security\Http\Authentication\AuthenticationUtils; diff --git a/src/Controller/SkillController.php b/src/Controller/SkillController.php index 914e64c..a6b66e6 100644 --- a/src/Controller/SkillController.php +++ b/src/Controller/SkillController.php @@ -4,6 +4,8 @@ namespace App\Controller; use App\Entity\Skill; use App\Form\SkillType; +use App\Repository\AnnouncementRepository; +use App\Repository\InternApplicationRepository; use App\Repository\SkillRepository; use Doctrine\ORM\EntityManagerInterface; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; @@ -15,25 +17,29 @@ use Symfony\Component\Security\Http\Attribute\IsGranted; #[Route('/skill')] final class SkillController extends AbstractController { + public function __construct( + private readonly EntityManagerInterface $entityManager, + private readonly SkillRepository $skillRepository, + ){} #[Route(name: 'app_skill_index', methods: ['GET'])] - public function index(SkillRepository $skillRepository): Response + public function index(): Response { return $this->render('skill/index.html.twig', [ - 'skills' => $skillRepository->findAll(), + 'skills' => $this->skillRepository->findAll(), ]); } #[Route('/new', name: 'app_skill_new', methods: ['GET', 'POST'])] #[IsGranted('ROLE_ADMIN')] - public function new(Request $request, EntityManagerInterface $entityManager): Response + public function new(Request $request,): Response { $skill = new Skill(); $form = $this->createForm(SkillType::class, $skill); $form->handleRequest($request); if ($form->isSubmitted() && $form->isValid()) { - $entityManager->persist($skill); - $entityManager->flush(); + $this->entityManager->persist($skill); + $this->entityManager->flush(); return $this->redirectToRoute('app_skill_index', [], Response::HTTP_SEE_OTHER); } @@ -54,13 +60,13 @@ final class SkillController extends AbstractController #[Route('/{id}/edit', name: 'app_skill_edit', methods: ['GET', 'POST'])] #[IsGranted('ROLE_ADMIN')] - public function edit(Request $request, Skill $skill, EntityManagerInterface $entityManager): Response + public function edit(Request $request, Skill $skill,): Response { $form = $this->createForm(SkillType::class, $skill); $form->handleRequest($request); if ($form->isSubmitted() && $form->isValid()) { - $entityManager->flush(); + $this->entityManager->flush(); return $this->redirectToRoute('app_skill_index', [], Response::HTTP_SEE_OTHER); } @@ -73,11 +79,11 @@ final class SkillController extends AbstractController #[Route('/{id}', name: 'app_skill_delete', methods: ['POST'])] #[IsGranted('ROLE_ADMIN')] - public function delete(Request $request, Skill $skill, EntityManagerInterface $entityManager): Response + public function delete(Request $request, Skill $skill,): Response { if ($this->isCsrfTokenValid('delete'.$skill->getId(), $request->getPayload()->getString('_token'))) { - $entityManager->remove($skill); - $entityManager->flush(); + $this->entityManager->remove($skill); + $this->entityManager->flush(); } return $this->redirectToRoute('app_skill_index', [], Response::HTTP_SEE_OTHER); diff --git a/src/Controller/UserAppController.php b/src/Controller/UserAppController.php index ad55bd2..8121327 100644 --- a/src/Controller/UserAppController.php +++ b/src/Controller/UserAppController.php @@ -4,6 +4,7 @@ namespace App\Controller; use App\Entity\UserApp; use App\Form\UserAppType; +use App\Repository\AnnouncementRepository; use App\Repository\UserRepository; use Doctrine\ORM\EntityManagerInterface; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; @@ -14,11 +15,15 @@ use Symfony\Component\Routing\Attribute\Route; #[Route('/user')] final class UserAppController extends AbstractController { + public function __construct( + private readonly EntityManagerInterface $entityManager, + private readonly UserRepository $userRepository, + ){} #[Route(name: 'app_user_index', methods: ['GET'])] - public function index(UserRepository $userRepository): Response + public function index(): Response { return $this->render('user_app/index.html.twig', [ - 'user_apps' => $userRepository->findAll(), + 'user_apps' => $this->userRepository->findAll(), ]); } @@ -31,13 +36,13 @@ final class UserAppController extends AbstractController } #[Route('/{id}/edit', name: 'app_user_edit', methods: ['GET', 'POST'])] - public function edit(Request $request, UserApp $userApp, EntityManagerInterface $entityManager): Response + public function edit(Request $request, UserApp $userApp,): Response { $form = $this->createForm(UserAppType::class, $userApp); $form->handleRequest($request); if ($form->isSubmitted() && $form->isValid()) { - $entityManager->flush(); + $this->entityManager->flush(); return $this->redirectToRoute('app_user_index', [], Response::HTTP_SEE_OTHER); } @@ -49,11 +54,11 @@ final class UserAppController extends AbstractController } #[Route('/{id}', name: 'app_user_delete', methods: ['POST'])] - public function delete(Request $request, UserApp $userApp, EntityManagerInterface $entityManager): Response + public function delete(Request $request, UserApp $userApp,): Response { if ($this->isCsrfTokenValid('delete'.$userApp->getId(), $request->getPayload()->getString('_token'))) { - $entityManager->remove($userApp); - $entityManager->flush(); + $this->entityManager->remove($userApp); + $this->entityManager->flush(); } return $this->redirectToRoute('app_user_index', [], Response::HTTP_SEE_OTHER); diff --git a/src/Entity/Company.php b/src/Entity/Company.php index ae8ccaa..1451791 100644 --- a/src/Entity/Company.php +++ b/src/Entity/Company.php @@ -7,6 +7,7 @@ use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; use Doctrine\ORM\Mapping as ORM; + #[ORM\Entity(repositoryClass: CompanyRepository::class)] class Company { diff --git a/src/Entity/Intern.php b/src/Entity/Intern.php index daaf428..0482385 100644 --- a/src/Entity/Intern.php +++ b/src/Entity/Intern.php @@ -7,17 +7,21 @@ use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; use Doctrine\DBAL\Types\Types; use Doctrine\ORM\Mapping as ORM; +use App\Entity\Company; #[ORM\Entity(repositoryClass: InternRepository::class)] class Intern extends UserApp { - #[ORM\Column(type: Types::TEXT,nullable: true)] + #[ORM\Column(type: Types::TEXT, length: 255, nullable: true)] private ?string $coverLetter = null; - #[ORM\Column(length: 255,nullable: true)] + #[ORM\Column(type: Types::TEXT, length: 255, nullable: true)] private ?string $resume = null; + #[ORM\Column(type: Types::TEXT, length: 255, nullable: true)] + private ?string $resumeName = null; + /** * @var Collection */ @@ -74,6 +78,18 @@ class Intern extends UserApp return $this; } + public function getResumeName(): ?string + { + return $this->resumeName; + } + + public function setResumeName(string $resumeName): static + { + $this->resumeName = $resumeName; + + return $this; + } + /** * @return Collection */ diff --git a/src/Entity/Status.php b/src/Entity/Status.php deleted file mode 100644 index e672f8c..0000000 --- a/src/Entity/Status.php +++ /dev/null @@ -1,78 +0,0 @@ - - */ - #[ORM\OneToMany(targetEntity: Announcement::class, mappedBy: 'status')] - private Collection $announcements; - - public function __construct() - { - $this->announcements = new ArrayCollection(); - } - - public function getId(): ?int - { - return $this->id; - } - - public function getLabel(): ?string - { - return $this->label; - } - - public function setLabel(string $label): static - { - $this->label = $label; - - return $this; - } - - /** - * @return Collection - */ - public function getAnnouncements(): Collection - { - return $this->announcements; - } - - public function addAnnouncement(Announcement $announcement): static - { - if (!$this->announcements->contains($announcement)) { - $this->announcements->add($announcement); - $announcement->setStatus($this); - } - - return $this; - } - - public function removeAnnouncement(Announcement $announcement): static - { - if ($this->announcements->removeElement($announcement)) { - // set the owning side to null (unless already changed) - if ($announcement->getStatus() === $this) { - $announcement->setStatus(null); - } - } - - return $this; - } -} diff --git a/src/Entity/UserApp.php b/src/Entity/UserApp.php index 0ccf691..0b82583 100644 --- a/src/Entity/UserApp.php +++ b/src/Entity/UserApp.php @@ -10,7 +10,7 @@ use Symfony\Component\Security\Core\User\UserInterface; #[ORM\Entity(repositoryClass: UserRepository::class)] #[ORM\Table(name: 'userApp')] -#[ORM\InheritanceType('JOINED')] +#[ORM\InheritanceType('SINGLE_TABLE')] #[ORM\DiscriminatorColumn(name: 'DISCRIMINATOR', type: 'string')] #[ORM\DiscriminatorMap(['employee' => Employee::class, 'intern' => Intern::class])] #[ORM\UniqueConstraint(name: 'UNIQ_IDENTIFIER_NICKNAME', fields: ['nickname'])] @@ -186,6 +186,7 @@ class UserApp implements UserInterface, PasswordAuthenticatedUserInterface return $this; } + } diff --git a/src/Form/InternType.php b/src/Form/InternType.php index a2b7931..3e973c2 100644 --- a/src/Form/InternType.php +++ b/src/Form/InternType.php @@ -4,8 +4,11 @@ namespace App\Form; use App\Entity\Intern; use Symfony\Component\Form\AbstractType; +use Symfony\Component\Form\Extension\Core\Type\FileType; +use Symfony\Component\Form\Extension\Core\Type\TextareaType; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\OptionsResolver\OptionsResolver; +use Symfony\Component\Validator\Constraints\File; class InternType extends AbstractType { @@ -20,7 +23,9 @@ class InternType extends AbstractType ->add('tel') ->add('address') ->add('mail') - ->add('coverLetter') + ->add('coverLetter', TextareaType::class, [ + 'required' => false, + ]) ->add('resume') ; } diff --git a/src/Form/RegistrationFormType.php b/src/Form/RegistrationFormType.php index 6aa8031..500a27e 100644 --- a/src/Form/RegistrationFormType.php +++ b/src/Form/RegistrationFormType.php @@ -15,12 +15,19 @@ use Symfony\Component\OptionsResolver\OptionsResolver; use Symfony\Component\Validator\Constraints\IsTrue; use Symfony\Component\Validator\Constraints\Length; use Symfony\Component\Validator\Constraints\NotBlank; +use App\Entity\Company; +use App\Entity\Intern; +use Symfony\Bridge\Doctrine\Form\Type\EntityType; +use Doctrine\ORM\EntityRepository; +use Symfony\Component\Form\Extension\Core\Type\SubmitType; + class RegistrationFormType extends AbstractType { public function buildForm(FormBuilderInterface $builder, array $options): void { $builder + ->add('nickname', TextType::class, [ 'label' => 'Utilisateur : ', ]) @@ -45,10 +52,7 @@ class RegistrationFormType extends AbstractType new NotBlank(), ] ]) -// ->add('plainPassword', PasswordType::class, [ - // instead of being set onto the object directly, - // this is read and encoded in the controller 'mapped' => false, 'attr' => ['autocomplete' => 'new-password'], 'constraints' => [ @@ -58,12 +62,10 @@ class RegistrationFormType extends AbstractType new Length([ 'min' => 6, 'minMessage' => 'Votre mot de passe doit avoir au moins {{ limit }} caractères', - // max length allowed by Symfony for security reasons 'max' => 4096, ]), ], - ]) - ; + ]); } public function configureOptions(OptionsResolver $resolver): void diff --git a/src/Form/ResetPasswordRequestFormType.php b/src/Form/ResetPasswordRequestFormType.php new file mode 100644 index 0000000..b92b33e --- /dev/null +++ b/src/Form/ResetPasswordRequestFormType.php @@ -0,0 +1,25 @@ +add('email', EmailType::class) + ; + } + + public function configureOptions(OptionsResolver $resolver): void + { + $resolver->setDefaults([ + // Configure your form options here + ]); + } +} diff --git a/src/Repository/StatusRepository.php b/src/Repository/StatusRepository.php deleted file mode 100644 index ea2e260..0000000 --- a/src/Repository/StatusRepository.php +++ /dev/null @@ -1,43 +0,0 @@ - - */ -class StatusRepository extends ServiceEntityRepository -{ - public function __construct(ManagerRegistry $registry) - { - parent::__construct($registry, Status::class); - } - -// /** -// * @return Status[] Returns an array of Status objects -// */ -// public function findByExampleField($value): array -// { -// return $this->createQueryBuilder('v') -// ->andWhere('v.exampleField = :val') -// ->setParameter('val', $value) -// ->orderBy('v.id', 'ASC') -// ->setMaxResults(10) -// ->getQuery() -// ->getResult() -// ; -// } - -// public function findOneBySomeField($value): ?Status -// { -// return $this->createQueryBuilder('v') -// ->andWhere('v.exampleField = :val') -// ->setParameter('val', $value) -// ->getQuery() -// ->getOneOrNullResult() -// ; -// } -} diff --git a/src/Security/UserAuthenticator.php b/src/Security/UserAuthenticator.php new file mode 100644 index 0000000..a8d7224 --- /dev/null +++ b/src/Security/UserAuthenticator.php @@ -0,0 +1,60 @@ +getPayload()->getString('nickname'); + + $request->getSession()->set(SecurityRequestAttributes::LAST_USERNAME, $nickname); + + return new Passport( + new UserBadge($nickname), + new PasswordCredentials($request->getPayload()->getString('password')), + [ + new CsrfTokenBadge('authenticate', $request->getPayload()->getString('_csrf_token')), + new RememberMeBadge(), + ] + ); + } + + public function onAuthenticationSuccess(Request $request, TokenInterface $token, string $firewallName): ?Response + { + if ($targetPath = $this->getTargetPath($request->getSession(), $firewallName)) { + return new RedirectResponse($targetPath); + } + + // For example: + return new RedirectResponse($this->urlGenerator->generate('index')); + //throw new \Exception('TODO: provide a valid redirect inside '.__FILE__); + } + + protected function getLoginUrl(Request $request): string + { + return $this->urlGenerator->generate(self::LOGIN_ROUTE); + } +} diff --git a/symfony.lock b/symfony.lock index cf1900f..fdb5abe 100644 --- a/symfony.lock +++ b/symfony.lock @@ -288,6 +288,9 @@ "config/packages/messenger.yaml" ] }, + "symfonycasts/sass-bundle": { + "version": "v0.7.0" + }, "twig/extra-bundle": { "version": "v3.13.0" } diff --git a/templates/announcement/index.html.twig b/templates/announcement/index.html.twig index 0920dd6..debc235 100644 --- a/templates/announcement/index.html.twig +++ b/templates/announcement/index.html.twig @@ -7,84 +7,66 @@

Liste des Annonces

{% if 'ROLE_ADMIN' in app.user.roles %} - -
- - -
+
+ + +
{% endif %} {% if 'ROLE_EMPLOYEE' in app.user.roles %} - - + {% endif %} -
- - - + + +
{% for announcement in announcements %}
- -
+
{% if announcement.status == 'notVerified' %} Non validée {% else %} Validée {% endif %} + +
+ +
-

{{ announcement.title }}

- -

{{ announcement.company.name }}

-
- - Date du stage : {{ announcement.date }} + Date du stage : {{ announcement.date }}
- -
- - {{ announcement.company.address }} + {{ announcement.company.address }}
- - + Détails
@@ -94,4 +76,3 @@
{% endblock %} - diff --git a/templates/announcement/show.html.twig b/templates/announcement/show.html.twig index 260e57c..b4dff6a 100644 --- a/templates/announcement/show.html.twig +++ b/templates/announcement/show.html.twig @@ -80,6 +80,16 @@ {% endif %} + +
+ +
diff --git a/templates/broadcast/FAQ.stream.html.twig b/templates/broadcast/FAQ.stream.html.twig new file mode 100644 index 0000000..988ccf4 --- /dev/null +++ b/templates/broadcast/FAQ.stream.html.twig @@ -0,0 +1,22 @@ +{# Learn how to use Turbo Streams: https://github.com/symfony/ux-turbo#broadcast-doctrine-entities-update #} +{% block create %} + + + +{% endblock %} + +{% block update %} + + + +{% endblock %} + +{% block remove %} + +{% endblock %} diff --git a/templates/degree/index.html.twig b/templates/degree/index.html.twig index 93b9be5..f394046 100644 --- a/templates/degree/index.html.twig +++ b/templates/degree/index.html.twig @@ -35,21 +35,19 @@ {% endif %} {% if 'ROLE_ADMIN' in app.user.roles %} - - - Modifier - + + + Modifier + - -
- - - -
+ +
+ + + +
{% endif %} @@ -68,13 +66,13 @@ {% endif %} {% if 'ROLE_ADMIN' in app.user.roles %} - - + + {% endif %} {% endblock %} diff --git a/templates/employee/applications.html.twig b/templates/employee/applications.html.twig index 18efabb..eb1dc91 100644 --- a/templates/employee/applications.html.twig +++ b/templates/employee/applications.html.twig @@ -3,22 +3,41 @@ {% block title %}Liste des Candidatures{% endblock %} {% block body %} -

Candidatures reçues

+
+

Candidatures reçues

-{% for app in applications %} -
-

Annonce : {{ app.application.title }}

-

Candidat : {{ app.intern.firstName }} {{ app.intern.lastName }}

-

Date : {{ app.applicationDate|date('d/m/Y') }}

-

Statut : {{ app.status }}

+ {% for app in applications %} +
+

Annonce : {{ app.application.title }}

+

Candidat : {{ app.intern.firstName }} {{ app.intern.lastName }}

+

Date : {{ app.applicationDate|date('d/m/Y') }}

+

Statut : {{ app.status|capitalize }}

- - Voir le profil du candidat - + + Voir le profil du candidat + + + {% if app.status == 'En Attente' %} +
+
+ +
+ +
+ +
+
+ {% endif %} +
+ {% else %} +

Aucune candidature pour le moment.

+ {% endfor %}
-{% else %} -

Aucune candidature pour le moment.

-{% endfor %} - {% endblock %} diff --git a/templates/faq/index.html.twig b/templates/faq/index.html.twig index 50d60f1..3f3ee79 100644 --- a/templates/faq/index.html.twig +++ b/templates/faq/index.html.twig @@ -1,55 +1,25 @@ {% extends 'base.html.twig' %} -{% block title %}Liste des FAQs{% endblock %} +{% block title %}FAQ{% endblock %} {% block body %}
-

Liste des FAQs

+

FAQ

-
- - - - - - - - - - - {% for faq in faqs %} - - - - - - - {% endfor %} - -
QuestionRéponseDenrnière modifActions
{{ faq.question }}{{ faq.answer }}{{ faq.updateDate|date("d-m-y") }} - - Voir - - - - Modifier - - -
- - - -
-
+
+ {% for faq in faqs %} +
+

Question : {{ faq.question }}

+

Dernière modification : {{ faq.updateDate|date("d-m-y") }}

+

Réponse : {{ faq.answer }}

+
+
+ {% endfor %}
- -
{% endblock %} diff --git a/templates/intern/index.html.twig b/templates/intern/index.html.twig index 02c128a..29708b1 100644 --- a/templates/intern/index.html.twig +++ b/templates/intern/index.html.twig @@ -48,4 +48,18 @@ {% endfor %} +

Vos compétences :

+
    + {% if app.user.skills|length > 0 %} + {% for internSkill in app.user.skills %} +
  • {{ internSkill.skill.label }}
  • + {% endfor %} + {% else %} +
  • Aucune compétence sélectionnée
  • + {% endif %} +
+ + Sélectionner vos compétences + {% endblock %} diff --git a/templates/intern/resume.html.twig b/templates/intern/resume.html.twig new file mode 100644 index 0000000..d8f2682 --- /dev/null +++ b/templates/intern/resume.html.twig @@ -0,0 +1,23 @@ +{% extends 'base.html.twig' %} + +{% block title %}Resume{% endblock %} + +{% block body %} +
+

Ajouter / Modifier le CV

+ +
+ {{ form_start(form, {'attr': {'enctype': 'multipart/form-data'}}) }} + +
+ {{ form_widget(form) }} +
+ + + + {{ form_end(form) }} +
+
+{% endblock %} diff --git a/templates/profile/employee.html.twig b/templates/profile/employee.html.twig index 1688471..d83f460 100644 --- a/templates/profile/employee.html.twig +++ b/templates/profile/employee.html.twig @@ -8,9 +8,9 @@

Téléphone : {{ app.user.tel }}

Email : {{ app.user.mail }}

- - Voir les candidatures reçues + + Voir les candidatures reçues diff --git a/templates/profile/intern.html.twig b/templates/profile/intern.html.twig index fbfef2b..bcecf29 100644 --- a/templates/profile/intern.html.twig +++ b/templates/profile/intern.html.twig @@ -2,11 +2,30 @@

Bonjour {{ app.user.nickname }}

Vous êtes à la recherche d'un stage.


-

Nom : {{ app.user.firstName }}

-

Prénom : {{ app.user.lastName }}

-

Adresse : {{ app.user.address }}

-

Téléphone : {{ app.user.tel }}

-

Email : {{ app.user.mail }}

+ +
+

Nom : {{ app.user.firstName }}

+

Prénom : {{ app.user.lastName }}

+

Adresse : {{ app.user.address }}

+

Téléphone : {{ app.user.tel }}

+

Email : {{ app.user.mail }}

+
+ + {% if app.user.resume != "" %} +
+
+ + {% if app.user.resumeName != "" %} +

Nom du fichier : {{ app.user.resumeName }}

+ {% endif %} +
+
+ {% endif %} + +
+ Ajouter / Modifier le CV +

Vos diplômes :

    @@ -26,16 +45,24 @@

    Vos compétences :

      - + {% if app.user.skills|length > 0 %} + {% for internSkill in app.user.skills %} +
    • {{ internSkill.skill.label }}
    • + {% endfor %} + {% else %} +
      + Aucune pour le moment + {% endif %}

    Selectionner vos compétences + href="{{ path('app_skill_index',{id: app.user.id}) }}"> Sélectionner vos compétences + diff --git a/templates/profile/visit.html.twig b/templates/profile/visit.html.twig index b202ac7..8a2858a 100644 --- a/templates/profile/visit.html.twig +++ b/templates/profile/visit.html.twig @@ -7,18 +7,18 @@

    Profil du candidat

    -

    Nom : {{ user.lastName }}

    -

    Prénom : {{ user.firstName }}

    -

    Email : {{ user.mail }}

    -

    Téléphone : {{ user.tel }}

    -

    Adresse : {{ user.address }}

    +

    Nom : {{ candidat.lastName }}

    +

    Prénom : {{ candidat.firstName }}

    +

    Email : {{ candidat.mail }}

    +

    Téléphone : {{ candidat.tel }}

    +

    Adresse : {{ candidat.address }}

    Diplômes

      - {% if user.degrees|length > 0 %} - {% for deg in user.degrees %} + {% if candidat.degrees|length > 0 %} + {% for deg in candidat.degrees %}
    • {{ deg.degree.label }} — Obtenu le {{ deg.graduationDate|date('d/m/Y') }}
    • @@ -32,9 +32,9 @@

      Compétences

        - {% if user.skills|length > 0 %} - {% for skill in user.skills %} -
      • {{ skill.label }}
      • + {% if candidat.skills|length > 0 %} + {% for sk in candidat.skills %} +
      • {{ sk.skill.label }}
      • {% endfor %} {% else %}

        Aucune compétence renseignée.

        @@ -43,9 +43,9 @@
    diff --git a/templates/registration/register.html.twig b/templates/registration/register.html.twig index edf72e9..10eaade 100644 --- a/templates/registration/register.html.twig +++ b/templates/registration/register.html.twig @@ -36,6 +36,15 @@ {{ form_errors(registrationForm.mail) }}
+ {% if employee %} +
+ {{ form_label(registrationForm.company, 'Sélectionnez une entreprise', {'label_attr': {'class': 'block text-gray-700 mb-2'}}) }} + {{ form_widget(registrationForm.company, {'attr': {'class': 'w-full px-4 py-2 border rounded-lg focus:outline-none focus:ring-2 focus:ring-teal-500'}}) }} + {{ form_errors(registrationForm.company) }} +
+ {% endif %} + +
{{ form_label(registrationForm.plainPassword, 'Mot de passe', {'label_attr': {'class': 'block text-gray-700 mb-2'}}) }} {{ form_widget(registrationForm.plainPassword, {'attr': {'class': 'w-full px-4 py-2 border rounded-lg focus:outline-none focus:ring-2 focus:ring-teal-500'}}) }} diff --git a/templates/security/reset_password_request.html.twig b/templates/security/reset_password_request.html.twig new file mode 100644 index 0000000..baba306 --- /dev/null +++ b/templates/security/reset_password_request.html.twig @@ -0,0 +1,14 @@ +{% extends 'base.html.twig' %} + +{% block title %}Demande de réinitialisation de mot de passe{% endblock %} + +{% block body %} +
+

Demande de réinitialisation de mot de passe

+ {{ form_start(requestPassForm) }} + {{ form_row(requestPassForm.email) }} + + + {{ form_end(requestPassForm) }} +
+{% endblock %} diff --git a/templates/skill/index.html.twig b/templates/skill/index.html.twig index e5e911f..0b31564 100644 --- a/templates/skill/index.html.twig +++ b/templates/skill/index.html.twig @@ -6,47 +6,70 @@

Liste des Compétences

-
- - - - - - - - - - {% for skill in skills %} - - - - + +
+
IDLabelActions
{{ skill.id }}{{ skill.label }} - - Voir - + {% if 'ROLE_INTERN' in app.user.roles %} +
+ {% endif %} - - Modifier - - - - - - -
-
+ + + + + - {% endfor %} - -
IDLabelActions
-
+ + + {% for skill in skills %} + + {{ skill.id }} + {{ skill.label }} + + {% if 'ROLE_INTERN' in app.user.roles %} + + {% endif %} - + {% if 'ROLE_ADMIN' in app.user.roles %} + + + Modifier + + + +
+ + + +
+ {% endif %} + + + {% endfor %} + + +
+ + {% if 'ROLE_INTERN' in app.user.roles %} +
+ +
+ + {% endif %} + + {% if 'ROLE_ADMIN' in app.user.roles %} + + {% endif %}
{% endblock %}