diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..13566b81b018ad684f3a35fee301741b2734c8f4 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/src/main/java/fr/atlantique/imt/inf211/jobmngt/controller/ApplicationController.java b/src/main/java/fr/atlantique/imt/inf211/jobmngt/controller/ApplicationController.java index f7b83a79f40636e3735d38b8a5a7ca3f35b04801..1404d663cc9cd2a93b18a05abb6f6e3082401121 100644 --- a/src/main/java/fr/atlantique/imt/inf211/jobmngt/controller/ApplicationController.java +++ b/src/main/java/fr/atlantique/imt/inf211/jobmngt/controller/ApplicationController.java @@ -1,33 +1,287 @@ package fr.atlantique.imt.inf211.jobmngt.controller; -import fr.atlantique.imt.inf211.jobmngt.entity.Application; -import fr.atlantique.imt.inf211.jobmngt.service.ApplicationService; +import java.time.LocalDateTime; +import java.util.List; +import java.util.Optional; +import java.util.logging.Logger; + import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.servlet.mvc.support.RedirectAttributes; -import java.util.List; +import fr.atlantique.imt.inf211.jobmngt.entity.Application; +import fr.atlantique.imt.inf211.jobmngt.entity.Candidate; +import fr.atlantique.imt.inf211.jobmngt.entity.QualificationLevel; +import fr.atlantique.imt.inf211.jobmngt.entity.Sector; +import fr.atlantique.imt.inf211.jobmngt.service.ApplicationService; +import fr.atlantique.imt.inf211.jobmngt.service.CandidateService; +import fr.atlantique.imt.inf211.jobmngt.service.QualificationLevelService; +import fr.atlantique.imt.inf211.jobmngt.service.SectorService; +import jakarta.servlet.http.HttpSession; @Controller @RequestMapping("/applications") public class ApplicationController { + private static final Logger logger = Logger.getLogger(ApplicationController.class.getName()); + @Autowired private ApplicationService applicationService; - @GetMapping - public String redirectToApplicationList() { - return "redirect:/applications/list"; + @Autowired + private CandidateService candidateService; + + @Autowired + private QualificationLevelService qualificationLevelService; + + @Autowired + private SectorService sectorService; + + /** + * Affiche le formulaire de candidature. + */ + @GetMapping("/apply") + public String showApplicationForm(HttpSession session, Model model) { + Integer userId = (Integer) session.getAttribute("uid"); + + if (userId == null) { + model.addAttribute("error", "Vous devez être connecté pour postuler."); + return "redirect:/login"; + } + + Optional<Candidate> candidateOpt = candidateService.findById(userId); + if (candidateOpt.isEmpty()) { + model.addAttribute("error", "Utilisateur non trouvé."); + return "error"; + } + + Candidate candidate = candidateOpt.get(); + List<QualificationLevel> qualifications = qualificationLevelService.getAllQualificationLevels(); + List<Sector> sectors = sectorService.getAllSectors(); + + model.addAttribute("application", new Application()); + model.addAttribute("candidate", candidate); + model.addAttribute("qualifications", qualifications); + model.addAttribute("sectors", sectors); + + return "application/apply"; + } + + /** + * Enregistre une candidature et redirige vers la page de confirmation. + */ + @PostMapping("/apply") + public String submitApplication( + @RequestParam("cv") String cv, + @RequestParam("qualificationLevel") int qualificationLevelId, + @RequestParam("sectors") List<Integer> sectorIds, + HttpSession session, + RedirectAttributes redirectAttributes) { + + Integer userId = (Integer) session.getAttribute("uid"); + if (userId == null) { + return "redirect:/login?error=Vous devez être connecté pour postuler."; + } + + Optional<Candidate> candidateOpt = candidateService.findById(userId); + if (candidateOpt.isEmpty()) { + redirectAttributes.addFlashAttribute("error", "Utilisateur non trouvé."); + return "redirect:/error"; + } + + Candidate candidate = candidateOpt.get(); + Optional<QualificationLevel> qualificationLevelOpt = qualificationLevelService.findById(qualificationLevelId); + + if (qualificationLevelOpt.isEmpty()) { + redirectAttributes.addFlashAttribute("error", "Niveau de qualification non trouvé."); + return "redirect:/error"; + } + + QualificationLevel qualificationLevel = qualificationLevelOpt.get(); + List<Sector> sectors = sectorService.getSectorsByIds(sectorIds); + + if (sectors.isEmpty()) { + redirectAttributes.addFlashAttribute("error", "Vous devez sélectionner au moins un secteur."); + return "redirect:/error"; + } + + Application application = new Application(); + application.setCandidate(candidate); + application.setCv(cv); + application.setQualificationlevel(qualificationLevel); + application.setSectors(sectors); + application.setAppdate(LocalDateTime.now()); + + Application savedApplication = applicationService.save(application); + + // Stocke uniquement l'ID en session + session.setAttribute("lastApplicationId", savedApplication.getId()); + + return "redirect:/applications/confirmation"; + } + + /** + * Affiche la page de confirmation avec les détails de la candidature. + */ + @GetMapping("/confirmation") + public String showConfirmationPage(Model model, HttpSession session) { + Integer lastApplicationId = (Integer) session.getAttribute("lastApplicationId"); + + if (lastApplicationId == null) { + System.out.println(" Aucun ID de candidature enregistré."); + return "redirect:/error"; + } + + Optional<Application> applicationOpt = applicationService.findById(lastApplicationId); + if (applicationOpt.isEmpty()) { + System.out.println(" Aucune candidature trouvée en base de données !"); + return "redirect:/error"; + } + + Application application = applicationOpt.get(); + + // Vérifier si l'objet a bien été récupéré + System.out.println(" Candidature trouvée : " + application.getId()); + System.out.println(" CV : " + application.getCv()); + System.out.println(" Qualification : " + (application.getQualificationlevel() != null ? application.getQualificationlevel().getLabel() : "NULL")); + System.out.println(" Secteurs : " + (application.getSectors() != null ? application.getSectors().size() : "NULL")); + System.out.println(" Date : " + application.getAppdate()); + + model.addAttribute("application", application); + return "application/application-confirmation"; } - // Affichage de la liste des candidatures + @GetMapping("/list") public String listApplications(Model model) { List<Application> applications = applicationService.getAllApplications(); - model.addAttribute("applications", applications); + + if (applications.isEmpty()) { + model.addAttribute("error", "Aucune candidature trouvée."); + } + + model.addAttribute("applicationsList", applications); // Renommage de la variable return "application/application-list"; } +/** + * Affiche les détails de la candidature. + */ + + @GetMapping("/details/{id}") + public String showApplicationDetails(@PathVariable int id, Model model) { + Optional<Application> applicationOpt = applicationService.findById(id); +if (applicationOpt.isEmpty()) { + model.addAttribute("error", "Candidature non trouvée."); + return "error"; // Page d'erreur si l'application n'est pas trouvée +} +Application application = applicationOpt.get(); +model.addAttribute("application", application); +return "application/application-details"; + } + + +// suprimer et update candidature + +@GetMapping("/edit/{id}") +public String showEditForm(@PathVariable int id, Model model, HttpSession session) { + Integer userId = (Integer) session.getAttribute("uid"); + + if (userId == null) { + return "redirect:/login"; // Rediriger vers login si non connecté + } + + Optional<Application> applicationOpt = applicationService.findById(id); + if (applicationOpt.isEmpty()) { + model.addAttribute("error", "Candidature non trouvée."); + return "error"; + } + + Application application = applicationOpt.get(); + + // Vérification si l'utilisateur est bien le propriétaire + if (application.getCandidate().getId() != userId) { + model.addAttribute("error", "Vous ne pouvez modifier que vos propres candidatures."); + return "error"; + } + + List<QualificationLevel> qualifications = qualificationLevelService.getAllQualificationLevels(); + List<Sector> sectors = sectorService.getAllSectors(); + + model.addAttribute("application", application); + model.addAttribute("qualifications", qualifications); + model.addAttribute("sectors", sectors); + + return "application/application-edit"; +} + + +/** + * Traite la modification d'une candidature + */ +@PostMapping("/update") +public String updateApplication( + @RequestParam("id") int id, + @RequestParam("cv") String cv, + @RequestParam("qualificationLevel") int qualificationLevelId, + @RequestParam("sectors") List<Integer> sectorIds, + RedirectAttributes redirectAttributes) { + + Optional<Application> applicationOpt = applicationService.findById(id); + if (applicationOpt.isEmpty()) { + redirectAttributes.addFlashAttribute("error", "Candidature non trouvée."); + return "redirect:/applications/list"; + } + + Application application = applicationOpt.get(); + application.setCv(cv); + + Optional<QualificationLevel> qualificationLevelOpt = qualificationLevelService.findById(qualificationLevelId); + if (qualificationLevelOpt.isPresent()) { + application.setQualificationlevel(qualificationLevelOpt.get()); + } + + List<Sector> sectors = sectorService.getSectorsByIds(sectorIds); + application.setSectors(sectors); + + applicationService.save(application); + redirectAttributes.addFlashAttribute("success", "Candidature mise à jour avec succès."); + + return "redirect:/applications/list"; +} + +/** + * Suppression d'une candidature + */ +@GetMapping("/delete/{id}") +public String deleteApplication(@PathVariable int id, RedirectAttributes redirectAttributes, HttpSession session) { + Integer userId = (Integer) session.getAttribute("uid"); + + if (userId == null) { + return "redirect:/login"; + } + + Optional<Application> applicationOpt = applicationService.findById(id); + if (applicationOpt.isEmpty()) { + redirectAttributes.addFlashAttribute("error", "Candidature non trouvée."); + return "redirect:/applications/list"; + } + + Application application = applicationOpt.get(); + + // Vérification que le candidat est bien le propriétaire + if (application.getCandidate().getId() != userId) { + redirectAttributes.addFlashAttribute("error", "Vous n'avez pas l'autorisation de supprimer cette candidature."); + return "redirect:/applications/list"; + } + applicationService.delete(id); + redirectAttributes.addFlashAttribute("success", "Candidature supprimée avec succès."); + return "redirect:/applications/list"; } +} \ No newline at end of file diff --git a/src/main/java/fr/atlantique/imt/inf211/jobmngt/controller/CandidateController.java b/src/main/java/fr/atlantique/imt/inf211/jobmngt/controller/CandidateController.java index accf04d106a41238d0083aba6958e2d18bd57bd1..b0328a5979b69a246c6fc8909987e3b7dfc9c363 100644 --- a/src/main/java/fr/atlantique/imt/inf211/jobmngt/controller/CandidateController.java +++ b/src/main/java/fr/atlantique/imt/inf211/jobmngt/controller/CandidateController.java @@ -1,10 +1,9 @@ package fr.atlantique.imt.inf211.jobmngt.controller; + import java.util.List; -import java.util.Optional; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; -//import org.hibernate.mapping.List; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; @@ -24,7 +23,8 @@ public class CandidateController { private CandidateService candidateService; @GetMapping("/signup") - public String showSignupForm() { + public String showSignupForm(Model model) { + model.addAttribute("candidate", new Candidate()); return "candidate/signupCandidate"; } @@ -34,100 +34,95 @@ public class CandidateController { @RequestParam String lastname, @RequestParam String firstname, @RequestParam String city) { - - // Vérifier si l'email existe déjà - Optional<Candidate> existingCandidate = candidateService.findByMail(mail); - if (existingCandidate.isPresent()) { - ModelAndView mav = new ModelAndView("candidate/signup"); - mav.addObject("error", "Email already exists. Please use another email."); - return mav; - } - - // Vérifier si le mot de passe est assez long - if (password.length() < 4) { - ModelAndView mav = new ModelAndView("candidate/signup"); - mav.addObject("error", "Password must be at least 4 characters long."); + + boolean isRegistered = candidateService.registerCandidate(new Candidate(mail, password, city, lastname, firstname)); + + if (!isRegistered) { + ModelAndView mav = new ModelAndView("candidate/signupCandidate"); + mav.addObject("error", "This email is already registered. Please use another one."); return mav; } - - // Création du candidat et enregistrement - Candidate candidate = new Candidate(mail, password, city, lastname, firstname); - candidateService.registerCandidate(candidate); - - // Redirection vers la page de confirmation + + // Redirection vers confirmation avec un message spécifique ModelAndView mav = new ModelAndView("candidate/confirmation"); mav.addObject("message", "Your account has been successfully created!"); return mav; } + @GetMapping("/list") public String listCandidates(Model model) { List<Candidate> candidates = candidateService.getAllCandidates(); model.addAttribute("candidates", candidates); return "candidate/candidates-list"; } - @GetMapping + + @GetMapping public String redirectToList() { return "redirect:/candidates/list"; } @GetMapping("/details/{id}") -public String getCandidateDetails(@PathVariable int id, Model model) { - Candidate candidate = candidateService.getCandidateById(id); - if (candidate == null) { - model.addAttribute("error", "Le candidat n'existe pas."); - return "error"; - } - model.addAttribute("candidate", candidate); - return "candidate/details"; -} - -@GetMapping("/edit/{id}") -public String showEditForm(@PathVariable int id, Model model) { - Candidate candidate = candidateService.getCandidateById(id); - if (candidate == null) { - model.addAttribute("error", "Le candidat n'existe pas."); - return "error"; + public String getCandidateDetails(@PathVariable int id, Model model) { + Candidate candidate = candidateService.getCandidateById(id); + if (candidate == null) { + model.addAttribute("error", "Le candidat n'existe pas."); + return "error"; + } + model.addAttribute("candidate", candidate); + return "candidate/details"; } - model.addAttribute("candidate", candidate); - return "candidate/editCandidate"; -} -@PostMapping("/edit") -public String updateCandidate(@RequestParam int id, - @RequestParam String mail, - @RequestParam String password, - @RequestParam String lastname, - @RequestParam String firstname, - @RequestParam String city, - Model model) { - Candidate candidate = candidateService.getCandidateById(id); - if (candidate == null) { - model.addAttribute("error", "Le candidat n'existe pas."); - return "error"; + @GetMapping("/edit/{id}") + public String showEditForm(@PathVariable int id, Model model) { + Candidate candidate = candidateService.getCandidateById(id); + if (candidate == null) { + model.addAttribute("error", "Le candidat n'existe pas."); + return "error"; + } + model.addAttribute("candidate", candidate); + return "candidate/editCandidate"; } - candidate.setMail(mail); - candidate.setPassword(password); - candidate.setLastname(lastname); - candidate.setFirstname(firstname); - candidate.setCity(city); - - candidateService.updateCandidate(candidate); - model.addAttribute("message", "Candidat mis à jour avec succès !"); - return "candidate/confirmation"; -} - -@GetMapping("/delete/{id}") -public String deleteCandidate(@PathVariable int id, Model model) { - Candidate candidate = candidateService.getCandidateById(id); - if (candidate == null) { - model.addAttribute("error", "Le candidat n'existe pas."); - return "error"; + @PostMapping("/edit") + public String updateCandidate(@RequestParam int id, + @RequestParam String password, + @RequestParam String lastname, + @RequestParam String firstname, + @RequestParam String city, + Model model) { + Candidate candidate = candidateService.getCandidateById(id); + if (candidate == null) { + model.addAttribute("error", "Le candidat n'existe pas."); + return "error"; + } + + candidate.setPassword(password); + candidate.setLastname(lastname); + candidate.setFirstname(firstname); + candidate.setCity(city); + + candidateService.updateCandidate(candidate); + + // Envoie l’objet candidat pour l’afficher après modification + model.addAttribute("message", "Candidat mis à jour avec succès !"); + model.addAttribute("candidate", candidate); + return "candidate/confirmation"; } + + @GetMapping("/delete/{id}") + public String deleteCandidate(@PathVariable int id, Model model) { + Candidate candidate = candidateService.getCandidateById(id); + + if (candidate == null) { + model.addAttribute("error", "Le candidat avec l'ID " + id + " n'existe pas."); + return "error"; // Affiche une page d'erreur si le candidat n'existe pas + } + + candidateService.deleteCandidate(id); + + // Rediriger vers la liste avec un message de confirmation + model.addAttribute("message", "Le candidat " + candidate.getFirstname() + " " + candidate.getLastname() + " a été supprimé avec succès !"); + return "candidate/confirmationSupp"; // Affichage de la confirmation après suppression + } - candidateService.deleteCandidate(id); - model.addAttribute("message", "Le candidat a été supprimé avec succès !"); - return "candidate/confirmation"; } - -} \ No newline at end of file diff --git a/src/main/java/fr/atlantique/imt/inf211/jobmngt/controller/CompanyController.java b/src/main/java/fr/atlantique/imt/inf211/jobmngt/controller/CompanyController.java index 6042cb24af4e37d1cee57809a4869f3b7278e39b..8ff51acdd8059b2244ae277e03f272d4278a41e7 100644 --- a/src/main/java/fr/atlantique/imt/inf211/jobmngt/controller/CompanyController.java +++ b/src/main/java/fr/atlantique/imt/inf211/jobmngt/controller/CompanyController.java @@ -1,86 +1,38 @@ package fr.atlantique.imt.inf211.jobmngt.controller; -import java.util.List; +import java.util.HashSet; import java.util.Optional; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.servlet.mvc.support.RedirectAttributes; import fr.atlantique.imt.inf211.jobmngt.entity.Company; -import fr.atlantique.imt.inf211.jobmngt.entity.JobOffer; import fr.atlantique.imt.inf211.jobmngt.service.CompanyService; -import fr.atlantique.imt.inf211.jobmngt.service.JobOfferService; - - - @Controller public class CompanyController { @Autowired private CompanyService companyService; - private final JobOfferService jobOfferService; - - public CompanyController(CompanyService companyService, JobOfferService jobOfferService) { - this.jobOfferService = jobOfferService; + public CompanyController(CompanyService companyService) { this.companyService = companyService; } - - @GetMapping("/jobOffers/view/{id}") -public String viewJobOffer(@PathVariable("id") Long id, Model model) { - Optional<JobOffer> offerOpt = jobOfferService.findById(id); - if (offerOpt.isPresent()) { - model.addAttribute("offer", offerOpt.get()); - return "jobOffer/jobOfferView"; - } - return "redirect:/companies"; // Redirige si l'offre n'est pas trouvée -} - - - - - - // // // Afficher les offres d'emploi d'une entreprise spécifique - @GetMapping("/companies/{id}/jobOffers") - public String listCompanyJobOffers(@PathVariable("id") Long companyId, Model model) { - Optional<Company> companyOpt = companyService.findById(companyId); -if (companyOpt.isPresent()) { - Company company = companyOpt.get(); - List<JobOffer> jobOffers = jobOfferService.findByCompany(company); - model.addAttribute("company", company); - model.addAttribute("jobOffers", jobOffers); - return "company/jobOffers"; -} - -model.addAttribute("errorMessage", "Entreprise introuvable !"); -return "error"; - - - } - - - - - - - - @GetMapping("/companies/create") + // Affiche le formulaire d'inscription + @GetMapping("/companies/create") public String showCreateForm(Model model) { - // On passe un objet 'Company' vide pour lier les champs du formulaire - model.addAttribute("company", new Company()); - return "company/companyForm"; + Company company = new Company(); + company.setJobOffers(new HashSet<>()); + model.addAttribute("company", company); + return "company/companyForm"; } - - // Affiche la liste des entreprises @GetMapping("/companies") public String listCompanies(Model model) { @@ -90,19 +42,17 @@ return "error"; // Affiche les détails d'une entreprise @GetMapping("/companies/view/{id}") - public String viewCompany(@PathVariable("id") Long id, Model model) { + public String viewCompany(@PathVariable("id") int id, Model model, RedirectAttributes redirectAttributes) { Optional<Company> companyOpt = companyService.findById(id); -if (companyOpt.isPresent()) { - Company company = companyOpt.get(); - model.addAttribute("company", company); - model.addAttribute("jobOfferCount", companyService.countJobOffersByCompany(id)); - model.addAttribute("jobOffers", companyService.getJobOffersByCompany(id)); + if (companyOpt.isPresent()) { + model.addAttribute("company", companyOpt.get()); return "company/companyView"; + } else { + redirectAttributes.addFlashAttribute("errorMessage", "❌ L'entreprise avec ID " + id + " n'existe pas !"); + return "redirect:/companies"; } - return "redirect:/companies"; } - // Enregistre une entreprise avec vérification des doublons et message de succès @PostMapping("/companies/create") @@ -122,13 +72,13 @@ if (companyOpt.isPresent()) { } catch (Exception e) { model.addAttribute("errorMessage", "❌ Erreur lors de l'inscription !"); model.addAttribute("company", company); - return "company/companyForm"; // Rester sur le formulaire en cas d'erreur + return "company/companyForm"; // 🔹 Rester sur le formulaire en cas d'erreur } } - // Affiche le formulaire de modification d'une entreprise + // Affiche le formulaire de modification d'une entreprise @GetMapping("/companies/{id}/edit") - public String showEditForm(@PathVariable("id") Long id, Model model, RedirectAttributes redirectAttributes) { + public String showEditForm(@PathVariable("id") int id, Model model, RedirectAttributes redirectAttributes) { Optional<Company> companyOpt = companyService.findById(id); if (companyOpt.isPresent()) { @@ -140,42 +90,22 @@ if (companyOpt.isPresent()) { } } - // // Met à jour les informations d'une entreprise avec message de succès + // Met à jour les informations d'une entreprise avec message de succès @PostMapping("/companies/update") -public String updateCompany(@ModelAttribute Company company, RedirectAttributes redirectAttributes) { - try { - // Vérifier si l'entreprise existe avant la mise à jour - Optional<Company> existingCompany = companyService.findById(Long.valueOf(company.getId())); - - if (existingCompany.isPresent()) { - // Mettre à jour les informations de l'entreprise - Company companyToUpdate = existingCompany.get(); - companyToUpdate.setDenomination(company.getDenomination()); - companyToUpdate.setDescription(company.getDescription()); - companyToUpdate.setCity(company.getCity()); - companyToUpdate.setMail(company.getMail()); - - // Enregistrer la mise à jour - companyService.saveCompany(companyToUpdate); + public String updateCompany(Company company, RedirectAttributes redirectAttributes) { + try { + companyService.updateCompany(company); redirectAttributes.addFlashAttribute("successMessage", "✅ L'entreprise a été mise à jour avec succès !"); return "redirect:/companies/view/" + company.getId(); - } else { - redirectAttributes.addFlashAttribute("errorMessage", "❌ L'entreprise n'existe pas !"); - return "redirect:/companies"; + } catch (Exception e) { + redirectAttributes.addFlashAttribute("errorMessage", "❌ Erreur lors de la mise à jour !"); + return "redirect:/companies/" + company.getId() + "/edit"; } - } catch (Exception e) { - // Log de l'erreur pour debugging - e.printStackTrace(); - redirectAttributes.addFlashAttribute("errorMessage", "❌ Erreur lors de la mise à jour : " + e.getMessage()); - return "redirect:/companies/view/" + company.getId(); } -} - - - // Supprime une entreprise + // Supprime une entreprise @GetMapping("/companies/delete/{id}") - public String deleteCompany(@PathVariable("id") Long id, RedirectAttributes redirectAttributes) { + public String deleteCompany(@PathVariable("id") int id, RedirectAttributes redirectAttributes) { try { companyService.deleteCompany(id); redirectAttributes.addFlashAttribute("successMessage", "✅ Entreprise supprimée avec succès !"); @@ -188,3 +118,8 @@ public String updateCompany(@ModelAttribute Company company, RedirectAttributes + + + + + diff --git a/src/main/java/fr/atlantique/imt/inf211/jobmngt/controller/JobOfferController.java b/src/main/java/fr/atlantique/imt/inf211/jobmngt/controller/JobOfferController.java index 2e5c1a9a104342205e375775f201dc94987d9376..984da34404e631795bfc17f761f2baa8c3d9283b 100644 --- a/src/main/java/fr/atlantique/imt/inf211/jobmngt/controller/JobOfferController.java +++ b/src/main/java/fr/atlantique/imt/inf211/jobmngt/controller/JobOfferController.java @@ -17,15 +17,12 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.servlet.mvc.support.RedirectAttributes; -import fr.atlantique.imt.inf211.jobmngt.entity.AppUser; import fr.atlantique.imt.inf211.jobmngt.entity.JobOffer; import fr.atlantique.imt.inf211.jobmngt.entity.Sector; import fr.atlantique.imt.inf211.jobmngt.service.CompanyService; import fr.atlantique.imt.inf211.jobmngt.service.JobOfferService; import fr.atlantique.imt.inf211.jobmngt.service.QualificationLevelService; import fr.atlantique.imt.inf211.jobmngt.service.SectorService; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpSession; @Controller @RequestMapping("/jobs") @@ -36,6 +33,7 @@ public class JobOfferController { private final QualificationLevelService qualificationLevelService; private final SectorService sectorService; + @Autowired public JobOfferController(JobOfferService jobOfferService, CompanyService companyService, @@ -47,139 +45,110 @@ public class JobOfferController { this.sectorService = sectorService; } + // Affiche la liste des offres d'emploi avec log @GetMapping - public String listJobOffers(Model model, HttpServletRequest request) { - HttpSession session = request.getSession(); - AppUser loggedInUser = (AppUser) session.getAttribute("user"); - - // Vérification de l'utilisateur - if (loggedInUser != null) { - model.addAttribute("userType", loggedInUser.getUsertype()); - model.addAttribute("userEmail", loggedInUser.getMail()); - System.out.println("Utilisateur connecté : " + loggedInUser.getMail() + " | Type: " + loggedInUser.getUsertype()); - } else { - model.addAttribute("userType", null); - model.addAttribute("userEmail", null); - System.out.println("Aucun utilisateur connecté."); - } - - model.addAttribute("jobOffers", jobOfferService.getAllJobOffers()); - return "jobOffer/jobOfferList"; // Correspond au fichier "jobOfferList.html" dans /templates/ + public String listJobOffers(Model model) { + List<JobOffer> jobOffers = jobOfferService.getAllJobOffers(); + System.out.println("🔎 Nombre d'offres récupérées: " + jobOffers.size()); + + model.addAttribute("jobOffers", jobOffers); + return "jobOffer/jobOfferList"; } - - - + // Affiche les détails d'une offre @GetMapping("/view/{id}") -public String viewJobOffer(@PathVariable("id") Long id, Model model, RedirectAttributes redirectAttributes) { - System.out.println("🔍 Recherche de l'offre avec ID : " + id); - Optional<JobOffer> jobOfferOpt = jobOfferService.findById(id); - - if (jobOfferOpt.isPresent()) { - model.addAttribute("jobOffer", jobOfferOpt.get()); - return "jobOffer/jobOfferView"; - } else { - System.out.println("❌ L'offre avec ID " + id + " est introuvable en base de données !"); - redirectAttributes.addFlashAttribute("errorMessage", "L'offre d'emploi avec ID " + id + " n'existe pas !"); - return "redirect:/jobs"; - } -} - - -@GetMapping("/company/job/view/{id}") -public String viewCompanyJob(@PathVariable("id") Long jobId, Model model) { - Optional<JobOffer> jobOffer = jobOfferService.findById(jobId); - - if (jobOffer.isEmpty()) { - return "error"; // Rediriger vers une page d'erreur si l'offre n'existe pas + public String viewJobOffer(@PathVariable("id") int id, Model model, RedirectAttributes redirectAttributes) { + Optional<JobOffer> jobOfferOpt = jobOfferService.findById(id); + if (jobOfferOpt.isPresent()) { + model.addAttribute("jobOffer", jobOfferOpt.get()); + return "jobOffer/jobOfferView"; + } else { + redirectAttributes.addFlashAttribute("errorMessage", "L'offre d'emploi avec ID " + id + " n'existe pas !"); + return "redirect:/jobs"; + } } - model.addAttribute("jobOffer", jobOffer.get()); - return "jobOffer/companyJobOfferView"; // Nouveau template dédié -} - - - - - + // Affiche le formulaire de création avec sélection des secteurs @GetMapping("/create") - public String showCreateForm(Model model, HttpServletRequest request) { - -// // Vérifier si l'utilisateur est une entreprise -// HttpSession session = request.getSession(false); -// if (session == null || !"company".equals(session.getAttribute("usertype"))) { -// return "redirect:/login"; // Redirige vers la connexion si ce n'est pas une entreprise -// } - - - - + public String showCreateForm(Model model) { JobOffer jobOffer = new JobOffer(); jobOffer.setPublicationDate(new Date()); model.addAttribute("jobOffer", jobOffer); model.addAttribute("companies", companyService.getAllCompanies()); - model.addAttribute("qualificationLevels", qualificationLevelService.listOfQualificationLevels()); + model.addAttribute("qualificationLevels", qualificationLevelService.getAllQualificationLevels()); model.addAttribute("sectors", sectorService.listOfSectors()); return "jobOffer/jobOfferForm"; } - @PostMapping("/save") - public String saveJobOffer(@ModelAttribute JobOffer jobOffer, - @RequestParam(value = "sectorIds", required = false) List<Long> sectorIds, - RedirectAttributes redirectAttributes, - HttpServletRequest request ) { - - // Vérifier si l'utilisateur est une entreprise - // HttpSession session = request.getSession(false); - // if (session == null || !"company".equals(session.getAttribute("usertype"))) { - // return "redirect:/login"; - // } - try { - if (sectorIds != null && !sectorIds.isEmpty()) { - Set<Sector> selectedSectors = sectorIds.stream() - .map(id -> sectorService.findById(id.intValue())) // - .filter(Optional::isPresent) - .map(Optional::get) - .collect(Collectors.toSet()); - jobOffer.setSectors(selectedSectors); - } - jobOfferService.saveJobOffer(jobOffer); - redirectAttributes.addFlashAttribute("successMessage", "✅ Offre créée avec succès !"); - return "redirect:/jobs"; - } catch (Exception e) { - redirectAttributes.addFlashAttribute("errorMessage", "❌ Erreur lors de la création de l'offre !"); - return "redirect:/jobs/create"; + // Enregistre une offre avec gestion des secteurs et des erreurs + +@PostMapping("/save") +public String saveJobOffer(@ModelAttribute JobOffer jobOffer, + @RequestParam(value = "sectorIds", required = false) List<Integer> sectorIds, + RedirectAttributes redirectAttributes) { + try { + System.out.println("🔹 Tentative d'enregistrement: " + jobOffer); + + // Associer les secteurs sélectionnés à l'offre d'emploi + if (sectorIds != null && !sectorIds.isEmpty()) { + Set<Sector> selectedSectors = sectorIds.stream() + .map(id -> sectorService.findById(id.longValue())) + .filter(Optional::isPresent) + .map(Optional::get) + .collect(Collectors.toSet()); // Convertir la liste en Set + + jobOffer.setSectors(selectedSectors); // Affectation corrigée } + + jobOfferService.saveJobOffer(jobOffer); + System.out.println(" Enregistrement réussi !"); + redirectAttributes.addFlashAttribute("successMessage", " Offre d'emploi créée avec succès !"); + return "redirect:/jobs"; + } catch (Exception e) { + System.err.println(" Erreur lors de l'enregistrement: " + e.getMessage()); + redirectAttributes.addFlashAttribute("errorMessage", " Erreur lors de la création de l'offre !"); + return "redirect:/jobs/create"; } +} + - @GetMapping("/delete/{id}") -public String deleteJobOffer(@PathVariable("id") Long id, HttpServletRequest request, RedirectAttributes redirectAttributes) { +// Supprime une offre d'emploi +@GetMapping("/delete/{id}") +public String deleteJobOffer(@PathVariable("id") int id, RedirectAttributes redirectAttributes) { Optional<JobOffer> jobOfferOpt = jobOfferService.findById(id); + if (jobOfferOpt.isPresent()) { - HttpSession session = request.getSession(false); - String userType = (session != null) ? (String) session.getAttribute("usertype") : null; - String userEmail = (session != null) ? (String) session.getAttribute("useremail") : null; - - JobOffer jobOffer = jobOfferOpt.get(); - - // Vérifie si l'utilisateur est bien une entreprise et le propriétaire de l'offre - if (userType != null && userType.equals("company") && jobOffer.getCompany().getMail().equals(userEmail)) { - try { - jobOfferService.deleteJobOffer(id); - redirectAttributes.addFlashAttribute("successMessage", "✅ Offre supprimée avec succès !"); - } catch (Exception e) { - redirectAttributes.addFlashAttribute("errorMessage", "❌ Erreur lors de la suppression de l'offre !"); - } - } else { - redirectAttributes.addFlashAttribute("errorMessage", "❌ Vous n'avez pas l'autorisation de supprimer cette offre !"); + try { + jobOfferService.deleteJobOffer(id); + redirectAttributes.addFlashAttribute("successMessage", " Offre d'emploi supprimée avec succès !"); + } catch (Exception e) { + redirectAttributes.addFlashAttribute("errorMessage", " Erreur lors de la suppression de l'offre !"); } } else { - redirectAttributes.addFlashAttribute("errorMessage", "❌ L'offre avec ID " + id + " n'existe pas !"); + redirectAttributes.addFlashAttribute("errorMessage", " L'offre d'emploi avec ID " + id + " n'existe pas !"); } + return "redirect:/jobs"; } + + + // Affiche le formulaire de modification + @GetMapping("/{id}/edit") + public String showEditForm(@PathVariable("id") int id, Model model, RedirectAttributes redirectAttributes) { + Optional<JobOffer> jobOfferOpt = jobOfferService.findById(id); + if (jobOfferOpt.isPresent()) { + model.addAttribute("jobOffer", jobOfferOpt.get()); + model.addAttribute("companies", companyService.getAllCompanies()); + model.addAttribute("qualificationLevels", qualificationLevelService.getAllQualificationLevels()); + model.addAttribute("sectors", sectorService.listOfSectors()); + return "jobOffer/jobOfferForm"; + } else { + redirectAttributes.addFlashAttribute("errorMessage", "L'offre d'emploi avec ID " + id + " n'existe pas !"); + return "redirect:/jobs"; + } + } } diff --git a/src/main/java/fr/atlantique/imt/inf211/jobmngt/controller/QualificationLevelController.java b/src/main/java/fr/atlantique/imt/inf211/jobmngt/controller/QualificationLevelController.java index 05080aa0b040cb15b68e5f84b4c957d10fc5f855..28f09930ae4dad72a6ba346c4f7758c6c248453a 100644 --- a/src/main/java/fr/atlantique/imt/inf211/jobmngt/controller/QualificationLevelController.java +++ b/src/main/java/fr/atlantique/imt/inf211/jobmngt/controller/QualificationLevelController.java @@ -18,7 +18,7 @@ public class QualificationLevelController { public ModelAndView listOfQualificationLevels() { ModelAndView modelAndView = new ModelAndView("qualificationLevel/qualificationLevelList"); - modelAndView.addObject("qualificationlevellist", qualificationLevelService.listOfQualificationLevels()); + modelAndView.addObject("qualificationlevellist", qualificationLevelService.getAllQualificationLevels()); return modelAndView; } diff --git a/src/main/java/fr/atlantique/imt/inf211/jobmngt/controller/SectorController.java b/src/main/java/fr/atlantique/imt/inf211/jobmngt/controller/SectorController.java index 6c773ccbfeba3632d6b6e0548ae4b2eac6e49bbc..50bcd722ccd140ab0e7f993f9c7e7adfb3557521 100644 --- a/src/main/java/fr/atlantique/imt/inf211/jobmngt/controller/SectorController.java +++ b/src/main/java/fr/atlantique/imt/inf211/jobmngt/controller/SectorController.java @@ -1,10 +1,10 @@ package fr.atlantique.imt.inf211.jobmngt.controller; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; -import org.springframework.stereotype.Controller; import org.springframework.web.servlet.ModelAndView; -import org.springframework.beans.factory.annotation.Autowired; import fr.atlantique.imt.inf211.jobmngt.service.SectorService; diff --git a/src/main/java/fr/atlantique/imt/inf211/jobmngt/converter/QualificationLevelConverter.java b/src/main/java/fr/atlantique/imt/inf211/jobmngt/converter/QualificationLevelConverter.java index f53845122ac42c2e67b81221b23a9e4d47244275..e7d649ea0543556d83a1e9bf5f9750a1b4b5e938 100644 --- a/src/main/java/fr/atlantique/imt/inf211/jobmngt/converter/QualificationLevelConverter.java +++ b/src/main/java/fr/atlantique/imt/inf211/jobmngt/converter/QualificationLevelConverter.java @@ -1,11 +1,13 @@ package fr.atlantique.imt.inf211.jobmngt.converter; -import org.springframework.core.convert.converter.Converter; // ✅ Import ajouté pour Optional +import org.springframework.core.convert.converter.Converter; import org.springframework.stereotype.Component; import fr.atlantique.imt.inf211.jobmngt.entity.QualificationLevel; import fr.atlantique.imt.inf211.jobmngt.service.QualificationLevelService; +import java.util.Optional; + @Component public class QualificationLevelConverter implements Converter<String, QualificationLevel> { @@ -16,16 +18,13 @@ public class QualificationLevelConverter implements Converter<String, Qualificat } @Override - public QualificationLevel convert(String source) { - if (source == null || source.trim().isEmpty() || source.equals("0")) { - return null; // Retourne null si l'entrée est vide ou "0" - } - + public QualificationLevel convert(String id) { try { - int id = Integer.parseInt(source); - return qualificationLevelService.findById(id).orElse(null); // ✅ Utilisation correcte d'Optional + int parsedId = Integer.parseInt(id); + Optional<QualificationLevel> qualificationLevelOpt = qualificationLevelService.findById(parsedId); + return qualificationLevelOpt.orElse(null); // Renvoie `null` si introuvable (géré en amont) } catch (NumberFormatException e) { - return null; // Gère les erreurs de conversion + return null; // Gestion d'une conversion invalide } } } diff --git a/src/main/java/fr/atlantique/imt/inf211/jobmngt/dao/ApplicationDao.java b/src/main/java/fr/atlantique/imt/inf211/jobmngt/dao/ApplicationDao.java index 1a438337f5de8407e70c9459bb91481c81c43aab..225eaf02b3338d47ffaaa8ad4f38cbae75750bde 100644 --- a/src/main/java/fr/atlantique/imt/inf211/jobmngt/dao/ApplicationDao.java +++ b/src/main/java/fr/atlantique/imt/inf211/jobmngt/dao/ApplicationDao.java @@ -1,6 +1,7 @@ package fr.atlantique.imt.inf211.jobmngt.dao; import java.util.List; +import java.util.Optional; import java.util.logging.Level; import java.util.logging.Logger; @@ -12,9 +13,6 @@ import jakarta.persistence.EntityManager; import jakarta.persistence.PersistenceContext; import jakarta.persistence.TypedQuery; -/** - * DAO pour l'entité Application. - */ @Repository public class ApplicationDao { @@ -29,11 +27,13 @@ public class ApplicationDao { entityManager.persist(transientInstance); } - @Transactional - public void remove(Application persistentInstance) { - logger.log(Level.INFO, "Removing Application instance"); - entityManager.remove(persistentInstance); - } + @Transactional + public void remove(Application application) { + logger.log(Level.INFO, "Removing Application instance"); + if (application != null) { + entityManager.remove(entityManager.contains(application) ? application : entityManager.merge(application)); + } + } @Transactional public Application merge(Application detachedInstance) { @@ -42,50 +42,20 @@ public class ApplicationDao { } @Transactional(readOnly = true) - public Application findById(int id) { - return entityManager.find(Application.class, id); - } +public Optional<Application> findById(int id) { + return Optional.ofNullable(entityManager.find(Application.class, id)); +} - /* - * Retourne toutes les applications triées par un champ et un ordre spécifié. - */ @Transactional(readOnly = true) - public List<Application> findAll(String sort, String order) { - logger.log(Level.INFO, "Fetching all applications sorted by " + sort + " in " + order + " order"); - - String jpql = "SELECT a FROM Application a ORDER BY a." + sort + " " + - (order.equalsIgnoreCase("asc") ? "ASC" : "DESC"); - TypedQuery<Application> query = entityManager.createQuery(jpql, Application.class); + public List<Application> findAll() { + logger.log(Level.INFO, "Fetching all applications"); + TypedQuery<Application> query = entityManager.createQuery("SELECT a FROM Application a ORDER BY a.appdate DESC", Application.class); return query.getResultList(); } +} + - /** - * Récupère les candidatures en fonction d'un secteur d'activité et d'un niveau de qualification donné. - */ - @Transactional(readOnly = true) - public List<Application> findBySectorAndQualification(String sectorLabel, String qualificationLevel) { - logger.log(Level.INFO, "Fetching applications for sector: " + sectorLabel + " and qualification level: " + qualificationLevel); - - String jpql = "SELECT a FROM Application a " + - "JOIN a.sectors s " + - "WHERE s.label = :sectorLabel " + - "AND a.qualificationlevel.label = :qualificationLevel"; // 🛠 Correction ici - - TypedQuery<Application> query = entityManager.createQuery(jpql, Application.class); - query.setParameter("sectorLabel", sectorLabel); - query.setParameter("qualificationLevel", qualificationLevel); - - return query.getResultList(); - } - @Transactional(readOnly = true) -public List<Application> findAll() { - logger.log(Level.INFO, "Fetching all applications"); - String jpql = "SELECT a FROM Application a ORDER BY a.appdate DESC"; - TypedQuery<Application> query = entityManager.createQuery(jpql, Application.class); - return query.getResultList(); -} -} diff --git a/src/main/java/fr/atlantique/imt/inf211/jobmngt/dao/CandidateDao.java b/src/main/java/fr/atlantique/imt/inf211/jobmngt/dao/CandidateDao.java index 6aab7101d41b2e298234126590f2d9691621b23f..99a93f1d5d21fac7e126b59773dacabb9e627fe1 100644 --- a/src/main/java/fr/atlantique/imt/inf211/jobmngt/dao/CandidateDao.java +++ b/src/main/java/fr/atlantique/imt/inf211/jobmngt/dao/CandidateDao.java @@ -1,104 +1,59 @@ package fr.atlantique.imt.inf211.jobmngt.dao; -// Generated 3 mars 2025, 13:07:58 by Hibernate Tools 5.6.15.Final - - -import java.util.List; -import java.util.Optional; -import java.util.logging.Level; -import java.util.logging.Logger; - -import org.springframework.stereotype.Repository; -import org.springframework.transaction.annotation.Transactional; import fr.atlantique.imt.inf211.jobmngt.entity.Candidate; import jakarta.persistence.EntityManager; import jakarta.persistence.PersistenceContext; import jakarta.persistence.TypedQuery; +import org.springframework.stereotype.Repository; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; +import java.util.Optional; -/** - * Home object for domain model class Candidate. - * @see .Candidate - * @author Hibernate Tools - */ @Repository public class CandidateDao { - private static final Logger logger = Logger.getLogger(CandidateDao.class.getName()); + @PersistenceContext + private EntityManager entityManager; - @PersistenceContext private EntityManager entityManager; @Transactional - public void persist(Candidate transientInstance) { - logger.log(Level.INFO, "persisting Candidate instance"); - try { - entityManager.persist(transientInstance); - logger.log(Level.INFO, "persist successful"); - } - catch (RuntimeException re) { - logger.log(Level.SEVERE, "persist failed", re); - throw re; - } + public void persist(Candidate candidate) { + entityManager.persist(candidate); } + @Transactional - public void remove(Candidate persistentInstance) { - logger.log(Level.INFO, "removing Candidate instance"); - try { - entityManager.remove(persistentInstance); - logger.log(Level.INFO, "remove successful"); - } - catch (RuntimeException re) { - logger.log(Level.SEVERE, "remove failed", re); - throw re; - } + public void remove(Candidate candidate) { + entityManager.remove(candidate); } + @Transactional - public Candidate merge(Candidate detachedInstance) { - logger.log(Level.INFO, "merging Candidate instance"); - try { - Candidate result = entityManager.merge(detachedInstance); - logger.log(Level.INFO, "merge successful"); - return result; - } - catch (RuntimeException re) { - logger.log(Level.SEVERE, "merge failed", re); - throw re; - } + public Candidate merge(Candidate candidate) { + return entityManager.merge(candidate); } - @Transactional(readOnly = true) -public List<Candidate> findAll() { - return entityManager.createQuery("SELECT c FROM Candidate c", Candidate.class).getResultList(); -} - - @Transactional - public Candidate findById( int id) { - logger.log(Level.INFO, "getting Candidate instance with id: " + id); - try { - Candidate instance = entityManager.find(Candidate.class, id); - logger.log(Level.INFO, "get successful"); - return instance; - } - catch (RuntimeException re) { - logger.log(Level.SEVERE, "get failed", re); - throw re; - } + public Candidate findById(int id) { + return entityManager.find(Candidate.class, id); } - @Transactional(readOnly = true) + + @Transactional(readOnly = true) public Optional<Candidate> findByMail(String mail) { TypedQuery<Candidate> query = entityManager.createQuery( "SELECT c FROM Candidate c WHERE c.mail = :mail", Candidate.class); query.setParameter("mail", mail); - List<Candidate> result = query.getResultList(); - return result.isEmpty() ? Optional.empty() : Optional.of(result.get(0)); + return query.getResultStream().findFirst(); } - - @Transactional - public void deleteById(int id) { - Candidate candidate = findById(id); - if (candidate != null) { - entityManager.remove(candidate); - } + @Transactional + public void deleteById(int id) { + Candidate candidate = findById(id); + if (candidate != null) { + entityManager.remove(candidate); } -} + } + @Transactional(readOnly = true) + public List<Candidate> findAll() { + return entityManager.createQuery("SELECT c FROM Candidate c", Candidate.class).getResultList(); + } +} diff --git a/src/main/java/fr/atlantique/imt/inf211/jobmngt/dao/OfferMessageDao.java b/src/main/java/fr/atlantique/imt/inf211/jobmngt/dao/OfferMessageDao.java index 8239ee500786a075f23c353c2be437abd7890bec..8e36d6810bd908e290f0c1a4fd05a08f2252c920 100644 --- a/src/main/java/fr/atlantique/imt/inf211/jobmngt/dao/OfferMessageDao.java +++ b/src/main/java/fr/atlantique/imt/inf211/jobmngt/dao/OfferMessageDao.java @@ -3,7 +3,7 @@ package fr.atlantique.imt.inf211.jobmngt.dao; import java.util.logging.Level; - import java.util.logging.Logger; +import java.util.logging.Logger; import org.springframework.stereotype.Repository; import org.springframework.transaction.annotation.Transactional; diff --git a/src/main/java/fr/atlantique/imt/inf211/jobmngt/dao/SectorDao.java b/src/main/java/fr/atlantique/imt/inf211/jobmngt/dao/SectorDao.java index 14369623cff50ab0aa80470cfc1d648405d33651..c3e70de07b62fa29fe8197126091c2548488dff5 100644 --- a/src/main/java/fr/atlantique/imt/inf211/jobmngt/dao/SectorDao.java +++ b/src/main/java/fr/atlantique/imt/inf211/jobmngt/dao/SectorDao.java @@ -10,6 +10,7 @@ import org.springframework.transaction.annotation.Transactional; import fr.atlantique.imt.inf211.jobmngt.entity.Sector; import jakarta.persistence.EntityManager; import jakarta.persistence.PersistenceContext; +import jakarta.persistence.TypedQuery; @Repository public class SectorDao { @@ -20,27 +21,27 @@ public class SectorDao { private EntityManager entityManager; @Transactional - public void persist(Sector sector) { + public void persist(Sector transientInstance) { logger.log(Level.INFO, "Persisting Sector instance"); - entityManager.persist(sector); + entityManager.persist(transientInstance); } @Transactional - public void remove(Sector sector) { + public void remove(Sector persistentInstance) { logger.log(Level.INFO, "Removing Sector instance"); - entityManager.remove(sector); + entityManager.remove(persistentInstance); } @Transactional - public Sector merge(Sector sector) { + public Sector merge(Sector detachedInstance) { logger.log(Level.INFO, "Merging Sector instance"); - return entityManager.merge(sector); + return entityManager.merge(detachedInstance); } @Transactional(readOnly = true) - public Sector findById(int id) { - logger.log(Level.INFO, "Fetching Sector instance with ID: " + id); - return entityManager.find(Sector.class, id); + public Sector findById(Object id) { + logger.log(Level.INFO, "Fetching Sector instance with ID: " + id); + return entityManager.find(Sector.class, id); } @Transactional(readOnly = true) @@ -50,60 +51,44 @@ public class SectorDao { return entityManager.createQuery(query, Long.class).getSingleResult(); } - @Transactional(readOnly = true) public List<Sector> findAll(String sort, String order) { - logger.log(Level.INFO, "Fetching all sectors sorted by " + sort + " in " + order + " order"); - String query = "SELECT s FROM Sector s ORDER BY s." + sort + " " + (order.equalsIgnoreCase("asc") ? "ASC" : "DESC"); - return entityManager.createQuery(query, Sector.class).getResultList(); + if (order == null || (!order.equalsIgnoreCase("ASC") && !order.equalsIgnoreCase("DESC"))) { + order = "ASC"; // Définit une valeur par défaut si `order` est null + } + + // Ici, utilisez `sort` pour définir la colonne par défaut si nécessaire + String sortColumn = (sort != null) ? sort : "id"; + + return entityManager.createQuery("SELECT s FROM Sector s ORDER BY s." + sortColumn + " " + order, Sector.class) + .getResultList(); } - + /** - * ✅ Nouvelle surcharge de findAll() sans paramètres. + * Nouvelle méthode : Récupérer les secteurs ayant un label donné. */ @Transactional(readOnly = true) - public List<Sector> findAll() { - logger.log(Level.INFO, "Fetching all sectors"); - return entityManager.createQuery("SELECT s FROM Sector s", Sector.class).getResultList(); + public List<Sector> findByLabel(String label) { + logger.log(Level.INFO, "Fetching sectors with label: " + label); + + String jpql = "SELECT s FROM Sector s WHERE s.label = :label"; + + TypedQuery<Sector> query = entityManager.createQuery(jpql, Sector.class); + query.setParameter("label", label); + + return query.getResultList(); } - - /** - * ✅ Nouvelle méthode pour récupérer plusieurs secteurs par ID. - */ + @Transactional(readOnly = true) - public List<Sector> findAllById(List<Integer> ids) { - logger.log(Level.INFO, "Fetching sectors with IDs: " + ids); - return entityManager.createQuery("SELECT s FROM Sector s WHERE s.id IN :ids", Sector.class) - .setParameter("ids", ids) - .getResultList(); - } - - /** - * ✅ Nouvelle méthode pour enregistrer un secteur. - */ - @Transactional - public void save(Sector sector) { - logger.log(Level.INFO, "Saving sector: " + sector); - entityManager.persist(sector); - } - - /** - * ✅ Nouvelle méthode pour mettre à jour un secteur. - */ - @Transactional - public void update(Sector sector) { - logger.log(Level.INFO, "Updating sector: " + sector); - entityManager.merge(sector); - } +public List<Sector> findAllByIds(List<Integer> ids) { + logger.log(Level.INFO, "Fetching sectors with IDs: " + ids); + + String jpql = "SELECT s FROM Sector s WHERE s.id IN :ids"; + + TypedQuery<Sector> query = entityManager.createQuery(jpql, Sector.class); + query.setParameter("ids", ids); + + return query.getResultList(); +} - /** - * ✅ Nouvelle méthode pour supprimer un secteur par ID. - */ - @Transactional - public void delete(int id) { - logger.log(Level.INFO, "Deleting sector with ID: " + id); - Sector sector = findById(id); - if (sector != null) { - entityManager.remove(sector); - } - } + } diff --git a/src/main/java/fr/atlantique/imt/inf211/jobmngt/entity/Application.java b/src/main/java/fr/atlantique/imt/inf211/jobmngt/entity/Application.java index 0c6bff3ba9a94dee8386b6537c79b5477b0c5ba9..118837ce6c5fed5b434bfea3d3f8746c44bfe34b 100644 --- a/src/main/java/fr/atlantique/imt/inf211/jobmngt/entity/Application.java +++ b/src/main/java/fr/atlantique/imt/inf211/jobmngt/entity/Application.java @@ -1,14 +1,13 @@ package fr.atlantique.imt.inf211.jobmngt.entity; import java.io.Serializable; -import java.util.Date; +import java.time.LocalDateTime; import java.util.List; import com.fasterxml.jackson.annotation.JsonIdentityInfo; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.ObjectIdGenerators; -import jakarta.persistence.CascadeType; import jakarta.persistence.Column; import jakarta.persistence.Entity; import jakarta.persistence.FetchType; @@ -19,16 +18,13 @@ import jakarta.persistence.JoinColumn; import jakarta.persistence.JoinTable; import jakarta.persistence.ManyToMany; import jakarta.persistence.ManyToOne; -import jakarta.persistence.OneToMany; import jakarta.persistence.SequenceGenerator; import jakarta.persistence.Table; -import jakarta.persistence.Temporal; -import jakarta.persistence.TemporalType; @Entity @Table(name = "application", schema = "public") @JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id") -@JsonIgnoreProperties({"hibernateLazyInitializer", "handler"}) // ✅ Empêche les erreurs de sérialisation JSON +@JsonIgnoreProperties({"hibernateLazyInitializer", "handler"}) public class Application implements Serializable { @Id @@ -39,28 +35,19 @@ public class Application implements Serializable { @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "candidateid", nullable = false) - @JsonIgnoreProperties({"applications"}) // ✅ Évite la surcharge JSON circulaire + @JsonIgnoreProperties({"applications"}) private Candidate candidate; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "qualiflevelid", nullable = false) - @JsonIgnoreProperties({"applications"}) // ✅ Corrige le problème de référence circulaire avec QualificationLevel + @JsonIgnoreProperties({"applications"}) private QualificationLevel qualificationlevel; @Column(name = "cv", nullable = false) private String cv; - @Temporal(TemporalType.DATE) @Column(name = "appdate") - private Date appdate; - - @OneToMany(mappedBy = "application", cascade = CascadeType.ALL, fetch = FetchType.LAZY) - @JsonIgnoreProperties({"application"}) // ✅ Évite les boucles infinies avec les messages - private List<ApplicationMessage> applicationmessages; - - @OneToMany(mappedBy = "application", cascade = CascadeType.ALL, fetch = FetchType.LAZY) - @JsonIgnoreProperties({"application"}) // ✅ Évite les références circulaires avec OfferMessage - private List<OfferMessage> offermessages; + private LocalDateTime appdate; @ManyToMany(fetch = FetchType.LAZY) @JoinTable( @@ -69,13 +56,11 @@ public class Application implements Serializable { joinColumns = { @JoinColumn(name = "applicationid", nullable = false, updatable = false) }, inverseJoinColumns = { @JoinColumn(name = "sectorid", nullable = false, updatable = false) } ) - @JsonIgnoreProperties({"applications"}) // ✅ Empêche la surcharge JSON circulaire + @JsonIgnoreProperties({"applications"}) private List<Sector> sectors; - // ========= CONSTRUCTEURS ========= - - public Application() { - } + // Constructeurs + public Application() {} public Application(int id, Candidate candidate, QualificationLevel qualificationlevel, String cv) { this.id = id; @@ -84,57 +69,22 @@ public class Application implements Serializable { this.cv = cv; } - public Application(int id, Candidate candidate, QualificationLevel qualificationlevel, String cv, Date appdate, - List<ApplicationMessage> applicationmessages, List<OfferMessage> offermessages, List<Sector> sectors) { - this.id = id; - this.candidate = candidate; - this.qualificationlevel = qualificationlevel; - this.cv = cv; - this.appdate = appdate; - this.applicationmessages = applicationmessages; - this.offermessages = offermessages; - this.sectors = sectors; - } - - // ========= GETTERS & SETTERS ========= - - public int getId() { return this.id; } + // Getters et Setters + public int getId() { return id; } public void setId(int id) { this.id = id; } - public Candidate getCandidate() { return this.candidate; } + public Candidate getCandidate() { return candidate; } public void setCandidate(Candidate candidate) { this.candidate = candidate; } - public QualificationLevel getQualificationlevel() { return this.qualificationlevel; } + public QualificationLevel getQualificationlevel() { return qualificationlevel; } public void setQualificationlevel(QualificationLevel qualificationlevel) { this.qualificationlevel = qualificationlevel; } - public String getCv() { return this.cv; } + public String getCv() { return cv; } public void setCv(String cv) { this.cv = cv; } - public Date getAppdate() { return this.appdate; } - public void setAppdate(Date appdate) { this.appdate = appdate; } - - public List<ApplicationMessage> getApplicationmessages() { return this.applicationmessages; } - public void setApplicationmessages(List<ApplicationMessage> applicationmessages) { this.applicationmessages = applicationmessages; } + public LocalDateTime getAppdate() { return appdate; } + public void setAppdate(LocalDateTime appdate) { this.appdate = appdate; } - public List<OfferMessage> getOffermessages() { return this.offermessages; } - public void setOffermessages(List<OfferMessage> offermessages) { this.offermessages = offermessages; } - - public List<Sector> getSectors() { return this.sectors; } + public List<Sector> getSectors() { return sectors; } public void setSectors(List<Sector> sectors) { this.sectors = sectors; } } - - - - - - - - - - - - - - - - diff --git a/src/main/java/fr/atlantique/imt/inf211/jobmngt/entity/JobOffer.java b/src/main/java/fr/atlantique/imt/inf211/jobmngt/entity/JobOffer.java index 57c17440d85de235b37fc3b4bedf833eb04f8da5..32cb94f2d9a227021ca6b5bb2d86b18d02d38bde 100644 --- a/src/main/java/fr/atlantique/imt/inf211/jobmngt/entity/JobOffer.java +++ b/src/main/java/fr/atlantique/imt/inf211/jobmngt/entity/JobOffer.java @@ -8,6 +8,7 @@ import org.springframework.format.annotation.DateTimeFormat; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import jakarta.persistence.CascadeType; import jakarta.persistence.Column; import jakarta.persistence.Entity; import jakarta.persistence.FetchType; @@ -26,23 +27,22 @@ import jakarta.persistence.TemporalType; @Entity @Table(name="joboffer", schema="public") -@JsonIgnoreProperties({"offerMessages"}) // ✅ Évite la surcharge JSON circulaire +@JsonIgnoreProperties({"offerMessages"}) // Évite la surcharge JSON circulaire public class JobOffer implements java.io.Serializable { @Id @SequenceGenerator(name = "JOBOFFER_ID_GENERATOR", sequenceName = "JOBOFFER_ID_SEQ", allocationSize = 1) @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "JOBOFFER_ID_GENERATOR") @Column(name="id", unique = true, nullable = false) -private Long id; // ✅ Correct - + private Integer id; // Modifié de int à Integer @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "compid", nullable = false) + @JoinColumn(name = "compid", nullable = true) // nullable = true pour éviter les erreurs si null private Company company; @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "qualiflevelid", nullable = true) -private QualificationLevel qualificationLevel; + @JoinColumn(name = "qualiflevelid", nullable = true) // nullable = true pour éviter les erreurs si null + private QualificationLevel qualificationLevel; @Column(name="title", nullable = false, length = 50) private String title; @@ -51,30 +51,33 @@ private QualificationLevel qualificationLevel; private String taskDescription; @Temporal(TemporalType.DATE) -@DateTimeFormat(pattern = "yyyy-MM-dd") -@Column(name="publicationdate") -private Date publicationDate; - @ManyToMany(fetch = FetchType.LAZY) + @DateTimeFormat(pattern = "yyyy-MM-dd") + + + + private Date publicationDate; + + @ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL) @JoinTable(name="indexjoboffersector", schema="public", joinColumns = { @JoinColumn(name="jobofferid", nullable = false, updatable = false) }, inverseJoinColumns = { @JoinColumn(name="sectorid", nullable = false, updatable = false) }) - @JsonIgnoreProperties({"applications", "jobOffers"}) // Empêche les boucles JSON infinies + @JsonIgnoreProperties({"applications", "jobOffers"}) private Set<Sector> sectors = new HashSet<>(); - @OneToMany(fetch = FetchType.LAZY, mappedBy = "jobOffer") // Correction du mappedBy + @OneToMany(fetch = FetchType.LAZY, mappedBy = "jobOffer", cascade = CascadeType.ALL) private Set<OfferMessage> offerMessages = new HashSet<>(); public JobOffer() {} - public JobOffer(Long id, Company company, QualificationLevel qualificationLevel, String title) { + public JobOffer(Integer id, Company company, QualificationLevel qualificationLevel, String title) { this.id = id; this.company = company; this.qualificationLevel = qualificationLevel; this.title = title; } - public JobOffer(Long id, Company company, QualificationLevel qualificationLevel, String title, + public JobOffer(Integer id, Company company, QualificationLevel qualificationLevel, String title, String taskDescription, Date publicationDate, Set<Sector> sectors, Set<OfferMessage> offerMessages) { this.id = id; this.company = company; @@ -86,9 +89,8 @@ private Date publicationDate; this.offerMessages = offerMessages; } - public Long getId() { return id; } -public void setId(Long id) { this.id = id; } - + public Integer getId() { return id; } + public void setId(Integer id) { this.id = id; } public Company getCompany() { return company; } public void setCompany(Company company) { this.company = company; } @@ -111,6 +113,3 @@ public void setId(Long id) { this.id = id; } public Set<OfferMessage> getOfferMessages() { return offerMessages; } public void setOfferMessages(Set<OfferMessage> offerMessages) { this.offerMessages = offerMessages; } } - - - diff --git a/src/main/java/fr/atlantique/imt/inf211/jobmngt/entity/OfferMessage.java b/src/main/java/fr/atlantique/imt/inf211/jobmngt/entity/OfferMessage.java index 6151cec1ab626724f01939c0fc650036f4d69f58..9abb7e72b0545ff464369c08d6866a135aee2f9e 100644 --- a/src/main/java/fr/atlantique/imt/inf211/jobmngt/entity/OfferMessage.java +++ b/src/main/java/fr/atlantique/imt/inf211/jobmngt/entity/OfferMessage.java @@ -35,7 +35,7 @@ public class OfferMessage implements java.io.Serializable { @ManyToOne(fetch=FetchType.LAZY) @JoinColumn(name="jobofferid", nullable=false) - private JobOffer jobOffer; // ✅ Correction du nom de l'attribut + private JobOffer jobOffer; // Correction du nom de l'attribut @Temporal(TemporalType.DATE) @Column(name="sentdate", length=13) diff --git a/src/main/java/fr/atlantique/imt/inf211/jobmngt/service/AppUserServiceImpl.java b/src/main/java/fr/atlantique/imt/inf211/jobmngt/service/AppUserServiceImpl.java index f81a13c234848c481d5fd7d7c50d659877a8a624..7ea784b71879ad3381bfc6a902c378c23866034c 100644 --- a/src/main/java/fr/atlantique/imt/inf211/jobmngt/service/AppUserServiceImpl.java +++ b/src/main/java/fr/atlantique/imt/inf211/jobmngt/service/AppUserServiceImpl.java @@ -1,13 +1,13 @@ package fr.atlantique.imt.inf211.jobmngt.service; -import java.util.List; -import java.util.Optional; +import fr.atlantique.imt.inf211.jobmngt.dao.AppUserDao; +import fr.atlantique.imt.inf211.jobmngt.entity.AppUser; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; +import org.springframework.beans.factory.annotation.Autowired; -import fr.atlantique.imt.inf211.jobmngt.dao.AppUserDao; -import fr.atlantique.imt.inf211.jobmngt.entity.AppUser; +import java.util.List; +import java.util.Optional; @Component public class AppUserServiceImpl implements AppUserService { @@ -31,3 +31,5 @@ public class AppUserServiceImpl implements AppUserService { return appUserDao.checkLogin(u); } } + + diff --git a/src/main/java/fr/atlantique/imt/inf211/jobmngt/service/ApplicationService.java b/src/main/java/fr/atlantique/imt/inf211/jobmngt/service/ApplicationService.java index 6c09cb0a22914d64f75dcd0be9e2313579d3f041..bcc6957b168f84d6eadb9ddf9f9ad22b987d9264 100644 --- a/src/main/java/fr/atlantique/imt/inf211/jobmngt/service/ApplicationService.java +++ b/src/main/java/fr/atlantique/imt/inf211/jobmngt/service/ApplicationService.java @@ -1,21 +1,12 @@ package fr.atlantique.imt.inf211.jobmngt.service; -import fr.atlantique.imt.inf211.jobmngt.dao.ApplicationDao; import fr.atlantique.imt.inf211.jobmngt.entity.Application; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - import java.util.List; +import java.util.Optional; -@Service -public class ApplicationService { - - @Autowired - private ApplicationDao applicationDao; - - @Transactional(readOnly = true) - public List<Application> getAllApplications() { - return applicationDao.findAll(); - } +public interface ApplicationService { + Application save(Application application); + Optional<Application> findById(int id); + List<Application> getAllApplications(); + void delete(int id); } diff --git a/src/main/java/fr/atlantique/imt/inf211/jobmngt/service/ApplicationServiceImpl.java b/src/main/java/fr/atlantique/imt/inf211/jobmngt/service/ApplicationServiceImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..9b1079c9fe53717b4fc26ca40c929f46ec777692 --- /dev/null +++ b/src/main/java/fr/atlantique/imt/inf211/jobmngt/service/ApplicationServiceImpl.java @@ -0,0 +1,47 @@ +package fr.atlantique.imt.inf211.jobmngt.service; + +import java.util.List; +import java.util.Optional; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import fr.atlantique.imt.inf211.jobmngt.dao.ApplicationDao; +import fr.atlantique.imt.inf211.jobmngt.entity.Application; + +@Service +public class ApplicationServiceImpl implements ApplicationService { + + @Autowired + private ApplicationDao applicationDao; + + @Override + @Transactional + public Application save(Application application) { + applicationDao.persist(application); + return application; + } + + + @Override + @Transactional(readOnly = true) + public Optional<Application> findById(int id) { + return applicationDao.findById(id); + } + + + @Override + @Transactional(readOnly = true) + public List<Application> getAllApplications() { + return applicationDao.findAll(); + } + + @Transactional + public void delete(int id) { + Optional<Application> applicationOpt = applicationDao.findById(id); + if (applicationOpt.isPresent()) { + applicationDao.remove(applicationOpt.get()); + } + } +} diff --git a/src/main/java/fr/atlantique/imt/inf211/jobmngt/service/CandidateService.java b/src/main/java/fr/atlantique/imt/inf211/jobmngt/service/CandidateService.java index 563f502b6f73aefb36115bc519a867d77004bca9..5ce638cd8b49c3e7357cb27ff8636755a139dd53 100644 --- a/src/main/java/fr/atlantique/imt/inf211/jobmngt/service/CandidateService.java +++ b/src/main/java/fr/atlantique/imt/inf211/jobmngt/service/CandidateService.java @@ -4,13 +4,14 @@ import fr.atlantique.imt.inf211.jobmngt.entity.Candidate; import java.util.List; import java.util.Optional; + public interface CandidateService { List<Candidate> getAllCandidates(); Candidate getCandidateById(int id); void createCandidate(Candidate candidate); - void registerCandidate(Candidate candidate); - + boolean registerCandidate(Candidate candidate); Optional<Candidate> findByMail(String mail); void updateCandidate(Candidate candidate); void deleteCandidate(int id); + Optional<Candidate> findById(int id); } diff --git a/src/main/java/fr/atlantique/imt/inf211/jobmngt/service/CandidateServiceImpl.java b/src/main/java/fr/atlantique/imt/inf211/jobmngt/service/CandidateServiceImpl.java index 45b93faa975f22fbf7616e70c3e6aaab115746e6..a8d9fd8164d11e58b410f91f5ca67baeaee223e2 100644 --- a/src/main/java/fr/atlantique/imt/inf211/jobmngt/service/CandidateServiceImpl.java +++ b/src/main/java/fr/atlantique/imt/inf211/jobmngt/service/CandidateServiceImpl.java @@ -1,13 +1,13 @@ package fr.atlantique.imt.inf211.jobmngt.service; -import java.util.List; -import java.util.Optional; - +import fr.atlantique.imt.inf211.jobmngt.dao.CandidateDao; +import fr.atlantique.imt.inf211.jobmngt.entity.Candidate; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; -import fr.atlantique.imt.inf211.jobmngt.dao.CandidateDao; -import fr.atlantique.imt.inf211.jobmngt.entity.Candidate; +import java.util.List; +import java.util.Optional; @Service public class CandidateServiceImpl implements CandidateService { @@ -29,26 +29,46 @@ public class CandidateServiceImpl implements CandidateService { public void createCandidate(Candidate candidate) { candidateDao.persist(candidate); } + @Override - public void registerCandidate(Candidate candidate) { + @Transactional + public boolean registerCandidate(Candidate candidate) { + Optional<Candidate> existingCandidate = candidateDao.findByMail(candidate.getMail()); + + if (existingCandidate.isPresent()) { + return false; + } + candidateDao.persist(candidate); + return true; } @Override public Optional<Candidate> findByMail(String mail) { - return (Optional<Candidate>) candidateDao.findByMail(mail); + return candidateDao.findByMail(mail); } @Override - public void updateCandidate(Candidate candidate) { - candidateDao.merge(candidate); +public void updateCandidate(Candidate candidate) { + Candidate existingCandidate = candidateDao.findById(candidate.getId()); + if (existingCandidate != null) { + // Ne pas autoriser la modification de l'email + candidate.setMail(existingCandidate.getMail()); + candidateDao.merge(candidate); + } } - @Override public void deleteCandidate(int id) { - Candidate candidate = candidateDao.findById(id); - if (candidate != null) { - candidateDao.remove(candidate); + Candidate candidate = candidateDao.findById(id); + if (candidate != null) { + candidateDao.remove(candidate); + } + } + @Override + public Optional<Candidate> findById(int id) { + Candidate candidate = candidateDao.findById(id); + return Optional.ofNullable(candidate); } + + } -} \ No newline at end of file diff --git a/src/main/java/fr/atlantique/imt/inf211/jobmngt/service/CompanyService.java b/src/main/java/fr/atlantique/imt/inf211/jobmngt/service/CompanyService.java index defab4b734f96c27948527e2b58c98b59f706576..5dee21b833ee923beb3ab20c9be871ce0de353c8 100644 --- a/src/main/java/fr/atlantique/imt/inf211/jobmngt/service/CompanyService.java +++ b/src/main/java/fr/atlantique/imt/inf211/jobmngt/service/CompanyService.java @@ -4,18 +4,12 @@ import java.util.List; import java.util.Optional; import fr.atlantique.imt.inf211.jobmngt.entity.Company; -import fr.atlantique.imt.inf211.jobmngt.entity.JobOffer; public interface CompanyService { void saveCompany(Company company); List<Company> getAllCompanies(); - Optional<Company> findById(Long id); + Optional<Company> findById(int id); Optional<Company> findByMail(String mail); // Ajout pour vérifier les doublons void updateCompany(Company company); // Mise à jour d'une entreprise - void deleteCompany(Long id); // Supprimer une entreprise - int countJobOffersByCompany(Long companyId); - List<JobOffer> getJobOffersByCompany(Long companyId); - - - + void deleteCompany(int id); // Supprimer une entreprise } diff --git a/src/main/java/fr/atlantique/imt/inf211/jobmngt/service/CompanyServiceImpl.java b/src/main/java/fr/atlantique/imt/inf211/jobmngt/service/CompanyServiceImpl.java index 77fed4b57a7500e52b98134050169c4007f4ae17..cc0f5c4adcdc37379dc112e37714a008d19b4257 100644 --- a/src/main/java/fr/atlantique/imt/inf211/jobmngt/service/CompanyServiceImpl.java +++ b/src/main/java/fr/atlantique/imt/inf211/jobmngt/service/CompanyServiceImpl.java @@ -41,7 +41,7 @@ public class CompanyServiceImpl implements CompanyService { @Override public Optional<Company> findByMail(String mail) { - return companyDao.findByMail(mail); // ✅ Vérifier si l'entreprise existe déjà + return companyDao.findByMail(mail); // Vérifier si l'entreprise existe déjà } @Override diff --git a/src/main/java/fr/atlantique/imt/inf211/jobmngt/service/JobOfferServiceImpl.java b/src/main/java/fr/atlantique/imt/inf211/jobmngt/service/JobOfferServiceImpl.java index 305f200ee5cf6eb250d00cc522e4df09eeff831e..c67c11884ad3b07988feae3a1818f603908627d9 100644 --- a/src/main/java/fr/atlantique/imt/inf211/jobmngt/service/JobOfferServiceImpl.java +++ b/src/main/java/fr/atlantique/imt/inf211/jobmngt/service/JobOfferServiceImpl.java @@ -8,7 +8,6 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import fr.atlantique.imt.inf211.jobmngt.dao.JobOfferDao; -import fr.atlantique.imt.inf211.jobmngt.entity.Company; import fr.atlantique.imt.inf211.jobmngt.entity.JobOffer; @Service @@ -26,44 +25,34 @@ public class JobOfferServiceImpl implements JobOfferService { return jobOfferDao.findAll(); } - public Optional<JobOffer> findById(Long id) { - Optional<JobOffer> jobOfferOpt = jobOfferDao.findById(id); - System.out.println("🔍 Vérification BDD pour l'offre ID " + id + " : " + (jobOfferOpt.isPresent() ? "Trouvée ✅" : "Non trouvée ❌")); - return jobOfferOpt; + @Override + public Optional<JobOffer> findById(int id) { + return jobOfferDao.findById(id); } - @Override - public void saveJobOffer(JobOffer jobOffer) { +public void saveJobOffer(JobOffer jobOffer) { + try { if (jobOffer.getPublicationDate() == null) { - jobOffer.setPublicationDate(new Date()); + jobOffer.setPublicationDate(new Date()); } + System.out.println("🔹 Tentative d'enregistrement: " + jobOffer); jobOfferDao.save(jobOffer); + System.out.println(" Enregistrement réussi !"); + } catch (Exception e) { + System.err.println(" Erreur lors de l'enregistrement: " + e.getMessage()); + e.printStackTrace(); } +} - // @Override - // public void updateJobOffer(JobOffer jobOffer) { - // jobOfferDao.save(jobOffer); - // } - - @Override - public void deleteJobOffer(Long id) { // ✅ Correction int → Long - jobOfferDao.deleteById(id); - } @Override - public List<JobOffer> getJobOffersByCompanyId(Long companyId) { - return jobOfferDao.findByCompanyId(companyId); // 🔹 Récupère les offres par entreprise + public void updateJobOffer(JobOffer jobOffer) { + jobOfferDao.save(jobOffer); } @Override - public List<JobOffer> findByCompany(Company company) { - // TODO Auto-generated method stub - throw new UnsupportedOperationException("Unimplemented method 'findByCompany'"); + public void deleteJobOffer(int id) { + jobOfferDao.deleteById(id); } - - - - - } diff --git a/src/main/java/fr/atlantique/imt/inf211/jobmngt/service/QualificationLevelService.java b/src/main/java/fr/atlantique/imt/inf211/jobmngt/service/QualificationLevelService.java index d5072b991496f0cdc55ec929cffa5d32c6382cb5..ed09cd76ee77f7132c532bdeacd0b9e14524fdf4 100644 --- a/src/main/java/fr/atlantique/imt/inf211/jobmngt/service/QualificationLevelService.java +++ b/src/main/java/fr/atlantique/imt/inf211/jobmngt/service/QualificationLevelService.java @@ -5,13 +5,7 @@ import java.util.Optional; import fr.atlantique.imt.inf211.jobmngt.entity.QualificationLevel; - public interface QualificationLevelService { - - public List<QualificationLevel> listOfQualificationLevels(); - - public long countQualificationLevel(); - + List<QualificationLevel> getAllQualificationLevels(); Optional<QualificationLevel> findById(int id); - } diff --git a/src/main/java/fr/atlantique/imt/inf211/jobmngt/service/QualificationLevelServiceImpl.java b/src/main/java/fr/atlantique/imt/inf211/jobmngt/service/QualificationLevelServiceImpl.java index 55bde7dbfbec3ad979917f27d23f457657920993..bdfa524641d733a83f549f6ac3ded7a7e415f75c 100644 --- a/src/main/java/fr/atlantique/imt/inf211/jobmngt/service/QualificationLevelServiceImpl.java +++ b/src/main/java/fr/atlantique/imt/inf211/jobmngt/service/QualificationLevelServiceImpl.java @@ -12,25 +12,17 @@ import fr.atlantique.imt.inf211.jobmngt.entity.QualificationLevel; @Service public class QualificationLevelServiceImpl implements QualificationLevelService { - private final QualificationLevelDao qualificationLevelDao; - @Autowired - public QualificationLevelServiceImpl(QualificationLevelDao qualificationLevelDao) { - this.qualificationLevelDao = qualificationLevelDao; - } + private QualificationLevelDao qualificationLevelDao; @Override - public List<QualificationLevel> listOfQualificationLevels() { - return qualificationLevelDao.findAll("id", "ASC"); + public List<QualificationLevel> getAllQualificationLevels() { + return qualificationLevelDao.findAll("id", "ASC"); // Ajout des paramètres manquants } + @Override - public long countQualificationLevel() { - return qualificationLevelDao.count(); - } - - @Override - public Optional<QualificationLevel> findById(int id) { - return qualificationLevelDao.findById(id); // ✅ Corrigé, pas besoin de orElse(null) - } +public Optional<QualificationLevel> findById(int id) { + return Optional.ofNullable(qualificationLevelDao.findById(id)); +} } diff --git a/src/main/java/fr/atlantique/imt/inf211/jobmngt/service/SectorService.java b/src/main/java/fr/atlantique/imt/inf211/jobmngt/service/SectorService.java index b4c628bec929534e1d66b20ce2591c4b0ddcb30c..1032ba0850f5864bbf6ba09fbf18bff180e4753d 100644 --- a/src/main/java/fr/atlantique/imt/inf211/jobmngt/service/SectorService.java +++ b/src/main/java/fr/atlantique/imt/inf211/jobmngt/service/SectorService.java @@ -6,10 +6,9 @@ import java.util.Optional; import fr.atlantique.imt.inf211.jobmngt.entity.Sector; public interface SectorService { - List<Sector> listOfSectors(); // ✅ Ajout de cette méthode - Optional<Sector> findById(int id); // ✅ Changer int en Long - - void saveSector(Sector sector); - void updateSector(Sector sector); - void deleteSector(int id); + List<Sector> getAllSectors(); + List<Sector> getSectorsByIds(List<Integer> sectorIds); + Optional<Sector> findById(long id); + Object listOfSectors(); + public Optional<Sector> findById(int id); } diff --git a/src/main/java/fr/atlantique/imt/inf211/jobmngt/service/SectorServiceImpl.java b/src/main/java/fr/atlantique/imt/inf211/jobmngt/service/SectorServiceImpl.java index 7405fab14e2b766d08a4277eca6d2ffbee69e240..bc6f1b56ed92c9b2e9e0c6dafa9e9ee5d190d62c 100644 --- a/src/main/java/fr/atlantique/imt/inf211/jobmngt/service/SectorServiceImpl.java +++ b/src/main/java/fr/atlantique/imt/inf211/jobmngt/service/SectorServiceImpl.java @@ -13,30 +13,32 @@ import fr.atlantique.imt.inf211.jobmngt.entity.Sector; public class SectorServiceImpl implements SectorService { @Autowired - private SectorDao sectorDao; + SectorDao sectorDao; @Override - public List<Sector> listOfSectors() { - return sectorDao.findAll(); // ✅ Appel de la nouvelle méthode sans arguments + public List<Sector> getAllSectors() { + return sectorDao.findAll(null, null); } - @Override - public Optional<Sector> findById(int id) { - return Optional.ofNullable(sectorDao.findById(id)); + + public List<Sector> getSectorsByIds(List<Integer> sectorIds) { + return sectorDao.findAllByIds(sectorIds); } @Override - public void saveSector(Sector sector) { - sectorDao.save(sector); + public Optional<Sector> findById(int id) { + return Optional.ofNullable(sectorDao.findById(id)); } @Override - public void updateSector(Sector sector) { - sectorDao.update(sector); + public Optional<Sector> findById(long id) { + // TODO Auto-generated method stub + throw new UnsupportedOperationException("Unimplemented method 'findById'"); } @Override - public void deleteSector(int id) { - sectorDao.delete(id); + public Object listOfSectors() { + // TODO Auto-generated method stub + throw new UnsupportedOperationException("Unimplemented method 'listOfSectors'"); } } diff --git a/src/main/resources/static/css/gyj_imt.css b/src/main/resources/static/css/gyj_imt.css index 3e785e015a71cf55f1a4abba4be53e9ae9e13250..fae8405c753b39e5943feb2ea79137246e36ac93 100644 --- a/src/main/resources/static/css/gyj_imt.css +++ b/src/main/resources/static/css/gyj_imt.css @@ -84,3 +84,68 @@ text-align: left; padding-left: 5px; } + +.card-cover { + height: 250px; + display: flex; + align-items: center; + justify-content: center; + text-align: center; + background-size: cover; + background-position: center; + border-radius: 10px; + transition: transform 0.3s ease-in-out; +} + +.card-cover:hover { + transform: scale(1.05); +} + +.card-cover { + height: 250px; /* Uniformiser la taille */ + display: flex; + align-items: center; + justify-content: center; + text-align: center; + background-size: cover; + background-position: center; + border-radius: 10px; + transition: transform 0.3s ease-in-out; +} + +.card-cover:hover { + transform: scale(1.05); +} + +.card-black { + background-color: black !important; +} + +.card-black h2 { + color: white !important; +} + +.card-cover { + height: 250px; /* Uniformiser la taille */ + display: flex; + align-items: center; + justify-content: center; + text-align: center; + background-size: cover; + background-position: center; + border-radius: 10px; + transition: transform 0.3s ease-in-out; +} + +.card-cover:hover { + transform: scale(1.05); +} + +.card-black { + background-color: black !important; +} + +.card-black h2 { + color: white !important; +} + diff --git a/src/main/resources/static/img/postuler.jpeg b/src/main/resources/static/img/postuler.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..719afa2cb849e0cd116298087f7d6aab814d5dab Binary files /dev/null and b/src/main/resources/static/img/postuler.jpeg differ diff --git a/src/main/resources/templates/application/application-confirmation.html b/src/main/resources/templates/application/application-confirmation.html new file mode 100644 index 0000000000000000000000000000000000000000..49c8ab4c0d24fd87c8419c8f3120fa7036c754d8 --- /dev/null +++ b/src/main/resources/templates/application/application-confirmation.html @@ -0,0 +1,36 @@ +<!DOCTYPE html> +<html xmlns:th="http://www.thymeleaf.org"> +<head> + <meta charset="UTF-8"> + <title>Confirmation de Candidature</title> + <link rel="stylesheet" th:href="@{/css/bootstrap.min.css}"> +</head> +<body> + <div class="container"> + <div class="alert alert-success mt-5 text-center"> + <h2> Votre candidature a été soumise avec succès !</h2> + </div> + + <h3 class="mt-4">📄 Détails de la candidature :</h3> + + <div th:if="${application != null}"> + <table class="table table-bordered"> + <tr><th>ID</th><td th:text="${application.id != null ? application.id : 'Non spécifié'}"></td></tr> + <tr><th> CV</th><td th:text="${application.cv != null ? application.cv : 'Non spécifié'}"></td></tr> + <tr><th> Niveau de qualification</th> + <td th:text="${application.qualificationlevel != null ? application.qualificationlevel.label : 'Non spécifié'}"></td> + </tr> + <tr><th> Secteurs d'activité</th> + <td th:each="sector : ${application.sectors}" th:text="${sector.label}"></td> + </tr> + <tr><th> Date de dépôt</th> + <td th:text="${application.appdate != null ? application.appdate : 'Non spécifié'}"></td> + </tr> + + </table> + </div> + + <a href="/" class="btn btn-primary mt-3"> Retour à l'accueil</a> + </div> +</body> +</html> diff --git a/src/main/resources/templates/application/application-details.html b/src/main/resources/templates/application/application-details.html new file mode 100644 index 0000000000000000000000000000000000000000..4a53d5b0d38cedcd9c3949f8e676ea2f5cfa13eb --- /dev/null +++ b/src/main/resources/templates/application/application-details.html @@ -0,0 +1,49 @@ +<!DOCTYPE html> +<html xmlns:th="http://www.thymeleaf.org"> +<head> + <meta charset="UTF-8"> + <title>Détails de la Candidature</title> + <link rel="stylesheet" th:href="@{/css/bootstrap.min.css}"> +</head> +<body> + <div class="container mt-5"> + <h2 class="mb-4"> Détails de la Candidature</h2> + + <div th:if="${error}" class="alert alert-warning"> + <p th:text="${error}"></p> + </div> + + <div class="card"> + <div class="card-body"> + <h5 class="card-title"> + Nom: + <span th:if="${application.candidate != null}" th:text="${application.candidate.firstname + ' ' + application.candidate.lastname}"></span> + <span th:unless="${application.candidate != null}">Non disponible</span> + </h5> + + <p class="card-text"> + <span th:if="${application.cv != null}" th:text="'CV: ' + ${application.cv}"></span> + <span th:unless="${application.cv != null}">Non disponible</span> + </p> + + <p class="card-text"> + <span th:if="${application.qualificationlevel != null}" th:text="'Niveau de Qualification: ' + ${application.qualificationlevel.label}"></span> + <span th:unless="${application.qualificationlevel != null}">Non disponible</span> + </p> + + <p class="card-text"> + <span th:each="sector : ${application.sectors}" th:text="'Secteur: ' + ${sector.label}"></span> + <span th:if="${#lists.isEmpty(application.sectors)}">Secteurs non disponibles</span> + </p> + + <p class="card-text"> + <span th:if="${application.appdate != null}" th:text="'Date de dépôt: ' + ${application.appdate}"></span> + <span th:unless="${application.appdate != null}">Non disponible</span> + </p> + </div> + </div> + + <a th:href="@{/applications/list}" class="btn btn-primary mt-3">Retour à la liste des candidatures</a> + </div> +</body> +</html> \ No newline at end of file diff --git a/src/main/resources/templates/application/application-edit.html b/src/main/resources/templates/application/application-edit.html new file mode 100644 index 0000000000000000000000000000000000000000..f68c9eca601803bc0fefcd04d0de283c53478c41 --- /dev/null +++ b/src/main/resources/templates/application/application-edit.html @@ -0,0 +1,17 @@ +<form th:action="@{/applications/update}" method="post"> + <input type="hidden" name="id" th:value="${application.id}"> + <label>CV :</label> + <input type="text" name="cv" th:value="${application.cv}" required> + + <label>Niveau de qualification :</label> + <select name="qualificationLevel"> + <option th:each="q : ${qualifications}" th:value="${q.id}" th:text="${q.label}"></option> + </select> + + <label>Secteurs :</label> + <select name="sectors" multiple> + <option th:each="s : ${sectors}" th:value="${s.id}" th:text="${s.label}"></option> + </select> + + <button type="submit">Modifier</button> +</form> diff --git a/src/main/resources/templates/application/application-list.html b/src/main/resources/templates/application/application-list.html index 51c91843050143eeb24b54a98cfcf2ae6a3e2ad4..2200f3182c91b13442415c476cc118d9565b44c9 100644 --- a/src/main/resources/templates/application/application-list.html +++ b/src/main/resources/templates/application/application-list.html @@ -6,41 +6,71 @@ <link rel="stylesheet" th:href="@{/css/bootstrap.min.css}"> </head> <body> - <div class="container"> - <h2 class="mt-5">Liste des Candidatures</h2> + <div class="container mt-5"> + <h2 class="mb-4">Liste des Candidatures</h2> - <table class="table table-striped mt-3"> + <div th:if="${error}" class="alert alert-warning"> + <p th:text="${error}"></p> + </div> + + <table class="table table-bordered table-striped" th:if="${applicationsList}"> <thead> <tr> <th>ID</th> - <th>Nom du Candidat</th> + <th>Nom</th> <th>Prénom</th> <th>CV</th> <th>Niveau de Qualification</th> - <th>Secteurs</th> - <th>Date de Dépôt</th> + <th>Secteurs d'activité</th> + <th>Date de dépôt</th> + <th>Détails</th> + <th>Modifier</th> + <th>Supprimer</th> </tr> </thead> <tbody> - <tr th:each="application : ${applications}"> - <td th:text="${application.id}"></td> - <td th:text="${application.candidate.lastname}"></td> - <td th:text="${application.candidate.firstname}"></td> - <td> - <a th:href="@{/cv/{cvFile}(cvFile=${application.cv})}" target="_blank">Voir CV</a> - </td> - <td th:text="${application.qualificationlevel.label}"></td> + <tr th:each="app : ${applicationsList}"> + <td th:text="${app.id}"></td> + <td th:text="${app.candidate.firstname}"></td> + <td th:text="${app.candidate.lastname}"></td> + <td><a th:href="@{${app.cv}}" th:text="${app.cv}"></a></td> + <td th:text="${app.qualificationlevel.label}"></td> <td> <ul> - <li th:each="sector : ${application.sectors}" th:text="${sector.label}"></li> + <li th:each="sector : ${app.sectors}" th:text="${sector.label}"></li> </ul> </td> - <td th:text="${application.appdate}"></td> + <td th:text="${app.appdate}"></td> + <td> + <a th:href="@{/applications/details/{id}(id=${app.id})}" class="btn btn-info">Détails</a> + </td> + + <!-- Vérification que l'utilisateur est connecté et est le propriétaire --> + <td th:if="${session.uid != null && session.uid == app.candidate.id}"> + <a th:href="@{/applications/edit/{id}(id=${app.id})}" class="btn btn-warning">Modifier</a> + </td> + <td th:if="${session.uid != null && session.uid == app.candidate.id}"> + <a th:href="@{/applications/delete/{id}(id=${app.id})}" class="btn btn-danger" + onclick="return confirm('Êtes-vous sûr de vouloir supprimer cette candidature ?');"> + Supprimer + </a> + </td> + + <!-- Affichage d'un message si l'utilisateur n'est pas connecté --> + <td th:if="${session.uid == null}" colspan="2"> + <a th:href="@{/login}" class="btn btn-secondary">Se connecter</a> + </td> </tr> </tbody> </table> - <a th:href="@{/}" class="btn btn-secondary mt-3">Retour</a> + <a th:href="@{/}" class="btn btn-primary mt-3">Retour à l'accueil</a> </div> </body> </html> + + + + + + diff --git a/src/main/resources/templates/application/application-update-form.html b/src/main/resources/templates/application/application-update-form.html new file mode 100644 index 0000000000000000000000000000000000000000..26266c1eb803c2a61e4fa4d794429159bb970af7 --- /dev/null +++ b/src/main/resources/templates/application/application-update-form.html @@ -0,0 +1,46 @@ +<!DOCTYPE html> +<html xmlns:th="http://www.thymeleaf.org"> +<head> + <meta charset="UTF-8"> + <title>Mettre à jour la Candidature</title> + <link rel="stylesheet" th:href="@{/css/bootstrap.min.css}"> +</head> +<body> + <div class="container mt-5"> + <h2 class="mb-4">Modifier ma Candidature</h2> + + <form th:action="@{/applications/update/{id}(id=${application.id})}" method="post"> + <div class="form-group"> + <label for="cv">CV</label> + <input type="text" id="cv" name="cv" class="form-control" th:value="${application.cv}" required> + </div> + + <div class="form-group"> + <label for="qualificationLevel">Niveau de Qualification</label> + <select id="qualificationLevel" name="qualificationLevel" class="form-control"> + <option th:each="qualification : ${qualifications}" + th:value="${qualification.id}" + th:text="${qualification.label}" + th:selected="${qualification.id == application.qualificationlevel.id}"> + </option> + </select> + </div> + + <div class="form-group"> + <label>Secteurs d'activité</label> + <select multiple name="sectors" class="form-control"> + <option th:each="sector : ${sectors}" + th:value="${sector.id}" + th:text="${sector.label}" + th:selected="${application.sectors.contains(sector)}"> + </option> + </select> + </div> + + <button type="submit" class="btn btn-primary mt-3">Mettre à jour</button> + </form> + + <a th:href="@{/applications/list}" class="btn btn-secondary mt-3">Retour à la liste des candidatures</a> + </div> +</body> +</html> diff --git a/src/main/resources/templates/application/apply.html b/src/main/resources/templates/application/apply.html new file mode 100644 index 0000000000000000000000000000000000000000..4615526e200b1aff678ccab99012d1ea5eb414a7 --- /dev/null +++ b/src/main/resources/templates/application/apply.html @@ -0,0 +1,74 @@ +<!DOCTYPE html> +<html xmlns:th="http://www.thymeleaf.org"> +<head> + <meta charset="UTF-8"> + <title>Postuler à une offre</title> + <link rel="stylesheet" th:href="@{/css/bootstrap.min.css}"> + <style> + body { + background-color: #f8f9fa; /* Couleur de fond */ + } + .container { + max-width: 600px; + margin-top: 50px; + background: #ffffff; + padding: 20px; + border-radius: 10px; + box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.1); + } + h2 { + text-align: center; + color: #007bff; /* Bleu Bootstrap */ + } + label { + font-weight: bold; + color: #343a40; + } + .form-control { + margin-bottom: 10px; + } + .btn-submit { + background-color: #007bff; + color: white; + width: 100%; + } + .btn-submit:hover { + background-color: #0056b3; + } + </style> +</head> +<body> + <div class="container"> + <h2> Postuler à une offre</h2> + + <form th:action="@{/applications/apply}" method="post"> + <!-- Champ CV --> + <div class="form-group"> + <label for="cv">CV :</label> + <input type="text" id="cv" name="cv" class="form-control" placeholder="Lien vers votre CV" required> + </div> + + <!-- Niveau de qualification --> + <div class="form-group"> + <label for="qualificationLevel">Niveau de qualification :</label> + <select id="qualificationLevel" name="qualificationLevel" class="form-control" required> + <option value="">Choisir un niveau</option> + <option th:each="qualification : ${qualifications}" th:value="${qualification.id}" th:text="${qualification.label}"></option> + </select> + </div> + + <!-- Secteurs d'activité --> + <div class="form-group"> + <label for="sectors">Secteurs d'activité :</label> + <select id="sectors" name="sectors" class="form-control" multiple required> + <option th:each="sector : ${sectors}" th:value="${sector.id}" th:text="${sector.label}"></option> + </select> + <small class="form-text text-muted">Maintenez la touche Ctrl (Cmd sur Mac) pour sélectionner plusieurs options.</small> + </div> + + <!-- Bouton de soumission --> + <button type="submit" class="btn btn-submit"> Soumettre</button> + </form> + </div> +</body> +</html> diff --git a/src/main/resources/templates/application/my-application-list.html b/src/main/resources/templates/application/my-application-list.html new file mode 100644 index 0000000000000000000000000000000000000000..15d8a4447c1d6fa55d93f03f6d45e9ef37d16910 --- /dev/null +++ b/src/main/resources/templates/application/my-application-list.html @@ -0,0 +1,43 @@ +<!DOCTYPE html> +<html xmlns:th="http://www.thymeleaf.org"> +<head> + <meta charset="UTF-8"> + <title>My Applications</title> + <link rel="stylesheet" th:href="@{/css/bootstrap.min.css}"> +</head> +<body> + <div class="container"> + <h2 class="mt-5">My Applications</h2> + + <!-- Message d'erreur --> + <div th:if="${error}" class="alert alert-danger" th:text="${error}"></div> + + <table class="table table-striped mt-3"> + <thead> + <tr> + <th>ID</th> + <th>CV</th> + <th>Qualification Level</th> + <th>Sector(s)</th> + <th>Application Date</th> + </tr> + </thead> + <tbody> + <tr th:each="application : ${applications}"> + <td th:text="${application.id}"></td> + <td th:text="${application.cv}"></td> + <td th:text="${application.qualificationlevel.label}"></td> + <td> + <ul> + <li th:each="sector : ${application.sectors}" th:text="${sector.label}"></li> + </ul> + </td> + <td th:text="${#dates.format(application.appdate, 'yyyy-MM-dd')}"></td> + </tr> + </tbody> + </table> + + <a th:href="@{/}" class="btn btn-secondary mt-3">Back to Home</a> + </div> +</body> +</html> diff --git a/src/main/resources/templates/baseTemplate/nav.html b/src/main/resources/templates/baseTemplate/nav.html index 50a1225f59538ce9c942ccac695ed32c8fa176a0..36532658f8e5cad9ec42eda3dd4815dcf37db6ef 100644 --- a/src/main/resources/templates/baseTemplate/nav.html +++ b/src/main/resources/templates/baseTemplate/nav.html @@ -43,12 +43,11 @@ <li class="nav-item"> <a class="nav-link" th:href="@{/jobs}">Jobs</a> </li> - <li class="nav-item"> - <a class="nav-link" href="/">Candidates </a> + <a class="nav-link" th:href="@{/candidates/list}">Candidates</a> </li> <li class="nav-item"> - <a class="nav-link" href="/">Applications</a> + <a class="nav-link" th:href="@{/applications/list}">Applications</a> </li> <li class="nav-item"> <a class="nav-link" th:href="@{/qualificationLevels}">Qualification levels</a> @@ -56,7 +55,6 @@ <li class="nav-item"> <a class="nav-link" th:href="@{/sectors}">Sectors</a> </li> - </ul> </div> diff --git a/src/main/resources/templates/candidate/candidates-list.html b/src/main/resources/templates/candidate/candidates-list.html index 7a4f23a9b8e85bcd6ad60f70fbf54c42df317432..039447c90e40d3dca0a29cd98e7432b9eb005b83 100644 --- a/src/main/resources/templates/candidate/candidates-list.html +++ b/src/main/resources/templates/candidate/candidates-list.html @@ -32,6 +32,7 @@ <td th:text="${candidate.mail}"></td> <td> <a th:href="@{/candidates/details/{id}(id=${candidate.id})}" class="btn btn-info btn-sm">Détails</a> + <span th:if="${#ctx.session.uid} != null and ${#ctx.session.uid} == ${candidate.id} ">PEUT SUPPRIMER</span> </td> </tr> </tbody> diff --git a/src/main/resources/templates/candidate/confirmation.html b/src/main/resources/templates/candidate/confirmation.html index 4746bdbee768888d900394e682041d0d1cb37b6d..8a22d725d2dd69e9120247d20355b72a469b08a1 100644 --- a/src/main/resources/templates/candidate/confirmation.html +++ b/src/main/resources/templates/candidate/confirmation.html @@ -1,14 +1,34 @@ <!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <head> - <title>Registration Successful</title> - <link rel="stylesheet" th:href="@{/css/bootstrap.min.css}" /> + <meta charset="UTF-8"> + <title>Confirmation</title> + <link rel="stylesheet" th:href="@{/css/bootstrap.min.css}"> </head> -<body class="container mt-5"> - <div class="alert alert-success text-center"> - <h2>Operation Successful</h2> - <p th:text="${message}"></p> - <a th:href="@{/login}" class="btn btn-primary">Go to Login</a> +<body> + <div class="container"> + <div class="alert alert-success mt-5 text-center"> + <h2>Operation Successful</h2> + <p th:text="${message}"></p> + </div> + + <!-- Affichage des infos du candidat uniquement si c'est une modification --> + <div th:if="${candidate != null}"> + <h3>Informations mises à jour :</h3> + <table class="table table-bordered"> + <tr><th>ID</th><td th:text="${candidate.id}"></td></tr> + <tr><th>Nom</th><td th:text="${candidate.lastname}"></td></tr> + <tr><th>Prénom</th><td th:text="${candidate.firstname}"></td></tr> + <tr><th>Email</th><td th:text="${candidate.mail}"></td></tr> + <tr><th>Ville</th><td th:text="${candidate.city}"></td></tr> + </table> + </div> + + <!-- Bouton différent selon la situation --> + <div class="text-center"> + <a th:if="${candidate != null}" th:href="@{/candidates/list}" class="btn btn-primary">Retour à la liste des candidats</a> + <a th:if="${candidate == null}" th:href="@{/login}" class="btn btn-primary">Go to Login</a> + </div> </div> </body> </html> diff --git a/src/main/resources/templates/candidate/confirmationSupp.html b/src/main/resources/templates/candidate/confirmationSupp.html new file mode 100644 index 0000000000000000000000000000000000000000..a8ebbf083b54a7d5ec3e83107bcd51533c418614 --- /dev/null +++ b/src/main/resources/templates/candidate/confirmationSupp.html @@ -0,0 +1,18 @@ +<!DOCTYPE html> +<html xmlns:th="http://www.thymeleaf.org"> +<head> + <meta charset="UTF-8"> + <title>Confirmation</title> + <link rel="stylesheet" th:href="@{/css/bootstrap.min.css}"> +</head> +<body> + <div class="container"> + <div class="alert alert-success mt-5"> + <h2>Opération Réussie </h2> + <p th:text="${message}"></p> + </div> + + <a th:href="@{/candidates/list}" class="btn btn-primary">Retour à la liste des candidats</a> + </div> +</body> +</html> diff --git a/src/main/resources/templates/candidate/editCandidate.html b/src/main/resources/templates/candidate/editCandidate.html index 5a9a4e54424a22ad7728516d77d0fba0ccbc789f..8bc1e65f63dff81577a04e2e1c90e51ec3c3d776 100644 --- a/src/main/resources/templates/candidate/editCandidate.html +++ b/src/main/resources/templates/candidate/editCandidate.html @@ -14,7 +14,8 @@ <div class="form-group"> <label>Email :</label> - <input type="email" name="mail" class="form-control" th:value="${candidate.mail}" required> + <!-- <input type="email" name="mail" class="form-control" th:value="${candidate.mail}" required> --> + <input type="email" class="form-control" name="mail" required th:value="${candidate.mail}" readonly /> </div> <div class="form-group"> diff --git a/src/main/resources/templates/candidate/signupCandidate.html b/src/main/resources/templates/candidate/signupCandidate.html index f65ae0ca113bcebf27bc51195131fdd2f28ee338..f8d74e5e6e033c038888c4f69ec112a65775d012 100644 --- a/src/main/resources/templates/candidate/signupCandidate.html +++ b/src/main/resources/templates/candidate/signupCandidate.html @@ -16,7 +16,7 @@ <form th:action="@{/candidates/signup}" method="post"> <div class="mb-3"> <label for="mail" class="form-label">Email address</label> - <input type="email" class="form-control" id="mail" name="mail" required> + <input type="email" class="form-control" name="mail" required th:value="${mail}" /> </div> <div class="mb-3"> <label for="password" class="form-label">Password</label> @@ -24,15 +24,15 @@ </div> <div class="mb-3"> <label for="lastname" class="form-label">Last Name</label> - <input type="text" class="form-control" id="lastname" name="lastname" required> + <input type="text" class="form-control" id="lastname" name="lastname" th:value="${lastname}" required> </div> <div class="mb-3"> <label for="firstname" class="form-label">First Name</label> - <input type="text" class="form-control" id="firstname" name="firstname" required> + <input type="text" class="form-control" id="firstname" name="firstname" th:value="${firstname}" required> </div> <div class="mb-3"> <label for="city" class="form-label">City</label> - <input type="text" class="form-control" id="city" name="city" required> + <input type="text" class="form-control" id="city" name="city" th:value="${city}" required> </div> <button type="submit" class="btn btn-primary">Sign Up</button> diff --git a/src/main/resources/templates/index.html b/src/main/resources/templates/index.html index c1991881ba5db7603cc296318ec59feabfcef978..d53f468fed2d575137455cbab6fcbe5c80ab9573 100644 --- a/src/main/resources/templates/index.html +++ b/src/main/resources/templates/index.html @@ -5,7 +5,7 @@ <header> <h1 class="pb-2 border-bottom">GetYourJob</h1> </header> - +<!-- <div class="row row-cols-1 row-cols-lg-3 align-items-stretch g-4 py-5"> <article class="col"> <a th:href="@{/companies}" @@ -27,8 +27,8 @@ </a> </article> - <!-- ✅ Section Candidats --> - <article class="col"> + ✅ Section Candidats --> + <!-- <article class="col"> <a th:href="@{/candidates}" class="nav-link card card-cover h-100 overflow-hidden text-white bg-dark rounded-5 shadow-lg" style="background-image: url('/img/candidates.jpg'); background-size: cover;"> @@ -47,7 +47,47 @@ </div> </a> </article> - </div> + </div> --> + <!-- bouton pour permettre aux candidats de soumettre une candidature depuis l'accueil. --> + <!-- <article class="col"> + <a th:href="@{/applications/apply}" + class="nav-link card card-cover h-100 overflow-hidden text-white bg-black rounded-5 shadow-lg" + style="background-image: url('/img/postuler.jpeg'); background-size: cover; background-position: center; height: 250px;"> + <div class="d-flex flex-column h-100 p-5 pb-3 text-shadow-1 text-center"> + <h2 class="pt-5 mt-5 mb-4 display-6 lh-1 fw-bold text-dark">Postuler</h2> + </div> + </a> +</article> --> + +<div class="row row-cols-1 row-cols-lg-3 align-items-stretch g-4 py-5"> + <article class="col"> + <a th:href="@{/companies}" class="nav-link card card-cover h-100 overflow-hidden text-white bg-dark rounded-5 shadow-lg" + style="background-image: url('/img/companies.jpg'); background-size: cover;"> + <div class="d-flex flex-column h-100 p-5 pb-3 text-white text-shadow-1"> + <h2 class="pt-5 mt-5 mb-4 display-6 lh-1 fw-bold">Companies</h2> + </div> + </a> + </article> + + <article class="col"> + <a th:href="@{/candidates}" class="nav-link card card-cover h-100 overflow-hidden text-white bg-dark rounded-5 shadow-lg" + style="background-image: url('/img/candidates.jpg'); background-size: cover;"> + <div class="d-flex flex-column h-100 p-5 pb-3 text-white text-shadow-1"> + <h2 class="pt-5 mt-5 mb-4 display-6 lh-1 fw-bold">Candidates</h2> + </div> + </a> + </article> + + <!-- ✅ Déplacement de "Postuler" dans la même ligne --> + <article class="col"> + <a th:href="@{/applications/apply}" class="nav-link card card-cover h-100 overflow-hidden text-white bg-dark rounded-5 shadow-lg" + style="background-image: url('/img/postuler.jpeg'); background-size: cover;"> + <div class="d-flex flex-column h-100 p-5 pb-3 text-white text-shadow-1"> + <h2 class="pt-5 mt-5 mb-4 display-6 lh-1 fw-bold text-dark">Postuler</h2> + </div> + </a> + </article> +</div> </section> diff --git a/src/main/resources/templates/login.html b/src/main/resources/templates/login.html index 6eb88d0a63673d4559c96bcbbb0bb368212f8f87..fbaa5e7d82095b9735edaf37a77c33436b1ff78e 100644 --- a/src/main/resources/templates/login.html +++ b/src/main/resources/templates/login.html @@ -1,17 +1,18 @@ <!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org" th:fragment="article(subcontent)" th:replace="~{/baseTemplate/base :: layout(~{},~{::section})}"> + <section class="modal modal-sheet position-static d-block bg-body-secondary p-4 py-md-5" tabindex="-1"> <div class="modal-dialog" role="document"> <div class="modal-content rounded-4 shadow"> <header class="modal-header p-5 pb-4 border-bottom-0"> <h1 class="fw-bold mb-0 fs-2">Sign in</h1> - <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"> - </button> + <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button> </header> - <article class="modal-body p-5 pt-0"> + + <article class="modal-body p-5 pt-0"> <small class="text-secondary">Log in by entering your email address and password.</small> - <form action="login" method="post"> + <form action="/login" method="post"> <fieldset class="mb-3 form-floating"> <input type="email" id="uid" class="form-control rounded-3" name="mail" autofocus="autofocus" required placeholder="name@domain.com" /> @@ -24,15 +25,17 @@ </fieldset> <input type="submit" value="Sign in" class="w-100 mb-2 btn btn-lg rounded-3 btn-primary" /> </form> - <!-- check if an error is returned in the model--> - <p th:if="${error}" th:text="${error}"> - </p> + <!-- Affichage des erreurs de connexion --> + <div th:if="${error}" class="alert alert-danger mt-3" role="alert"> + <p th:text="${error}"></p> + </div> </article> + <footer class="modal-body p-5 pt-0"> <hr class="my-4"> <a th:href="@{/companies/create}" class="btn w-100 mb-2 btn btn-lg rounded-3 btn-secondary">Sign up as company</a> - <a th:href="@{/candidates/create}" class="btn w-100 mb-2 btn btn-lg rounded-3 btn-secondary">Sign up as candidate</a> + <a th:href="@{/candidates/signup}" class="btn w-100 mb-2 btn btn-lg rounded-3 btn-secondary">Sign up as candidate</a> <small class="text-secondary">By clicking Sign up, you agree to the terms of use.</small> </footer> </div> diff --git a/target/classes/fr/atlantique/imt/inf211/jobmngt/JobmngtApplication.class b/target/classes/fr/atlantique/imt/inf211/jobmngt/JobmngtApplication.class index f0a90d1bbf5e1de067104184ac2327e4bc6ec7c1..2b36ca8b345ac2dd44982ef1e6536e08114e7ef7 100644 Binary files a/target/classes/fr/atlantique/imt/inf211/jobmngt/JobmngtApplication.class and b/target/classes/fr/atlantique/imt/inf211/jobmngt/JobmngtApplication.class differ diff --git a/target/classes/fr/atlantique/imt/inf211/jobmngt/config/WebConfig.class b/target/classes/fr/atlantique/imt/inf211/jobmngt/config/WebConfig.class index 52731e8e29e734dfac6fcc14f364098385bfd1a1..50d5c3e4b986652913b1a08586ee99d4b13ff9fb 100644 Binary files a/target/classes/fr/atlantique/imt/inf211/jobmngt/config/WebConfig.class and b/target/classes/fr/atlantique/imt/inf211/jobmngt/config/WebConfig.class differ diff --git a/target/classes/fr/atlantique/imt/inf211/jobmngt/controller/ApplicationController.class b/target/classes/fr/atlantique/imt/inf211/jobmngt/controller/ApplicationController.class index d7ebe118993688dafa83677cd105b558fd88f827..ebb1cd07638a3a84ad4cd146dee28fb7cb71cd97 100644 Binary files a/target/classes/fr/atlantique/imt/inf211/jobmngt/controller/ApplicationController.class and b/target/classes/fr/atlantique/imt/inf211/jobmngt/controller/ApplicationController.class differ diff --git a/target/classes/fr/atlantique/imt/inf211/jobmngt/controller/CandidateController.class b/target/classes/fr/atlantique/imt/inf211/jobmngt/controller/CandidateController.class index 034a4816d5c366e2990a916e824458867e368983..d0c06cda510e698f9a8eb1d00514346491c3e182 100644 Binary files a/target/classes/fr/atlantique/imt/inf211/jobmngt/controller/CandidateController.class and b/target/classes/fr/atlantique/imt/inf211/jobmngt/controller/CandidateController.class differ diff --git a/target/classes/fr/atlantique/imt/inf211/jobmngt/controller/CompanyController.class b/target/classes/fr/atlantique/imt/inf211/jobmngt/controller/CompanyController.class index 6fa4a5e213abde873ba8a21688586a4100af7857..d1170384285d05a36a5981b3d1e94267dbdd2c68 100644 Binary files a/target/classes/fr/atlantique/imt/inf211/jobmngt/controller/CompanyController.class and b/target/classes/fr/atlantique/imt/inf211/jobmngt/controller/CompanyController.class differ diff --git a/target/classes/fr/atlantique/imt/inf211/jobmngt/controller/JobOfferController.class b/target/classes/fr/atlantique/imt/inf211/jobmngt/controller/JobOfferController.class index d429a64a81f9c60bff5c28a77060dafbfc490ff1..9a669740b433576d8024308d6bdad897138692e2 100644 Binary files a/target/classes/fr/atlantique/imt/inf211/jobmngt/controller/JobOfferController.class and b/target/classes/fr/atlantique/imt/inf211/jobmngt/controller/JobOfferController.class differ diff --git a/target/classes/fr/atlantique/imt/inf211/jobmngt/controller/LoginController.class b/target/classes/fr/atlantique/imt/inf211/jobmngt/controller/LoginController.class index c6b9bca2963fb3926af9de26de9db52e68724823..4b6498c7530594a9ae6854bfdabd29b9635afd40 100644 Binary files a/target/classes/fr/atlantique/imt/inf211/jobmngt/controller/LoginController.class and b/target/classes/fr/atlantique/imt/inf211/jobmngt/controller/LoginController.class differ diff --git a/target/classes/fr/atlantique/imt/inf211/jobmngt/controller/PagesController.class b/target/classes/fr/atlantique/imt/inf211/jobmngt/controller/PagesController.class index 947d212e8ad107f1e14b34dc66b858003ed260ec..0ef37c9b68e7a07cc1bb5892a079629c4eb40aa4 100644 Binary files a/target/classes/fr/atlantique/imt/inf211/jobmngt/controller/PagesController.class and b/target/classes/fr/atlantique/imt/inf211/jobmngt/controller/PagesController.class differ diff --git a/target/classes/fr/atlantique/imt/inf211/jobmngt/controller/QualificationLevelController.class b/target/classes/fr/atlantique/imt/inf211/jobmngt/controller/QualificationLevelController.class index a192bc80992984f36a4c4d20b52f60a87282e06f..0c3f48963ee425f88e19fdfcb134f219dfc2e2bb 100644 Binary files a/target/classes/fr/atlantique/imt/inf211/jobmngt/controller/QualificationLevelController.class and b/target/classes/fr/atlantique/imt/inf211/jobmngt/controller/QualificationLevelController.class differ diff --git a/target/classes/fr/atlantique/imt/inf211/jobmngt/controller/SectorController.class b/target/classes/fr/atlantique/imt/inf211/jobmngt/controller/SectorController.class index 891e652c6835417fc6eb01c4fa8296edae1ee9ac..a01cecaf77cb22655abbdd6ad8d10dc170b3df1a 100644 Binary files a/target/classes/fr/atlantique/imt/inf211/jobmngt/controller/SectorController.class and b/target/classes/fr/atlantique/imt/inf211/jobmngt/controller/SectorController.class differ diff --git a/target/classes/fr/atlantique/imt/inf211/jobmngt/converter/CompanyConverter.class b/target/classes/fr/atlantique/imt/inf211/jobmngt/converter/CompanyConverter.class index 69b5b745c27680d537d723367dd1d26780b226b5..63f6a7a42c4a8879294bfd611192931bdfdc3e42 100644 Binary files a/target/classes/fr/atlantique/imt/inf211/jobmngt/converter/CompanyConverter.class and b/target/classes/fr/atlantique/imt/inf211/jobmngt/converter/CompanyConverter.class differ diff --git a/target/classes/fr/atlantique/imt/inf211/jobmngt/converter/QualificationLevelConverter.class b/target/classes/fr/atlantique/imt/inf211/jobmngt/converter/QualificationLevelConverter.class index 9ce0a6e9a3c41b63bd37e3c586e739612988e00e..4e3504981e3513a7882bcb924f0fa95e66fd0fd2 100644 Binary files a/target/classes/fr/atlantique/imt/inf211/jobmngt/converter/QualificationLevelConverter.class and b/target/classes/fr/atlantique/imt/inf211/jobmngt/converter/QualificationLevelConverter.class differ diff --git a/target/classes/fr/atlantique/imt/inf211/jobmngt/dao/AppUserDao.class b/target/classes/fr/atlantique/imt/inf211/jobmngt/dao/AppUserDao.class index 032e02035d15e3cd03cc5465cf6782a91152f9bc..4dbc86467838cb1ed89cc2c06242f59e43de5aea 100644 Binary files a/target/classes/fr/atlantique/imt/inf211/jobmngt/dao/AppUserDao.class and b/target/classes/fr/atlantique/imt/inf211/jobmngt/dao/AppUserDao.class differ diff --git a/target/classes/fr/atlantique/imt/inf211/jobmngt/dao/ApplicationDao.class b/target/classes/fr/atlantique/imt/inf211/jobmngt/dao/ApplicationDao.class index 8c9c5a69cb587e39f2cad47fbcb3968ad0ed3e69..f17cb506f20ad9b2fc5b03eabbc1fdb9d79d772b 100644 Binary files a/target/classes/fr/atlantique/imt/inf211/jobmngt/dao/ApplicationDao.class and b/target/classes/fr/atlantique/imt/inf211/jobmngt/dao/ApplicationDao.class differ diff --git a/target/classes/fr/atlantique/imt/inf211/jobmngt/dao/ApplicationMessageDao.class b/target/classes/fr/atlantique/imt/inf211/jobmngt/dao/ApplicationMessageDao.class index 34cddd48297530f563983d20ec2e73bb96bf0f3f..56c4b4b35f7e8dff2a54a4aca76fc7ccd4a06708 100644 Binary files a/target/classes/fr/atlantique/imt/inf211/jobmngt/dao/ApplicationMessageDao.class and b/target/classes/fr/atlantique/imt/inf211/jobmngt/dao/ApplicationMessageDao.class differ diff --git a/target/classes/fr/atlantique/imt/inf211/jobmngt/dao/CandidateDao.class b/target/classes/fr/atlantique/imt/inf211/jobmngt/dao/CandidateDao.class index 55b7090135c7e5ac4e8850371f500b20ca3e0ac6..64ebd03df2efd75d4e2ac34daaa591a03703f052 100644 Binary files a/target/classes/fr/atlantique/imt/inf211/jobmngt/dao/CandidateDao.class and b/target/classes/fr/atlantique/imt/inf211/jobmngt/dao/CandidateDao.class differ diff --git a/target/classes/fr/atlantique/imt/inf211/jobmngt/dao/CompanyDao.class b/target/classes/fr/atlantique/imt/inf211/jobmngt/dao/CompanyDao.class index 8b5ac987bcea7c911a43544b101158a224ff8f04..203a0ae5a34ee846ced862c5091760e6bad31ca1 100644 Binary files a/target/classes/fr/atlantique/imt/inf211/jobmngt/dao/CompanyDao.class and b/target/classes/fr/atlantique/imt/inf211/jobmngt/dao/CompanyDao.class differ diff --git a/target/classes/fr/atlantique/imt/inf211/jobmngt/dao/JobOfferDao.class b/target/classes/fr/atlantique/imt/inf211/jobmngt/dao/JobOfferDao.class index a925598f027de2690213cf12ef27ff30629aba44..8135d3d754e03900af1d7f62cd7ac4372c63ceb3 100644 Binary files a/target/classes/fr/atlantique/imt/inf211/jobmngt/dao/JobOfferDao.class and b/target/classes/fr/atlantique/imt/inf211/jobmngt/dao/JobOfferDao.class differ diff --git a/target/classes/fr/atlantique/imt/inf211/jobmngt/dao/OfferMessageDao.class b/target/classes/fr/atlantique/imt/inf211/jobmngt/dao/OfferMessageDao.class index e2e091720c172faf1caf03efab85aea2c3a52172..302b39e7f7dd0dda1d8f17acee94d675dfe0e537 100644 Binary files a/target/classes/fr/atlantique/imt/inf211/jobmngt/dao/OfferMessageDao.class and b/target/classes/fr/atlantique/imt/inf211/jobmngt/dao/OfferMessageDao.class differ diff --git a/target/classes/fr/atlantique/imt/inf211/jobmngt/dao/QualificationLevelDao.class b/target/classes/fr/atlantique/imt/inf211/jobmngt/dao/QualificationLevelDao.class index bd4c56bce609290a508f726faf416a5571881247..8007f008519c4bf388d1662bebad7f2dcaa43986 100644 Binary files a/target/classes/fr/atlantique/imt/inf211/jobmngt/dao/QualificationLevelDao.class and b/target/classes/fr/atlantique/imt/inf211/jobmngt/dao/QualificationLevelDao.class differ diff --git a/target/classes/fr/atlantique/imt/inf211/jobmngt/dao/SectorDao.class b/target/classes/fr/atlantique/imt/inf211/jobmngt/dao/SectorDao.class index f48edc2c76094ce5b76bb6b44c83a78cb9d3b444..09d33755ab8a624dbcfd1b0dd22bd9c993391a0b 100644 Binary files a/target/classes/fr/atlantique/imt/inf211/jobmngt/dao/SectorDao.class and b/target/classes/fr/atlantique/imt/inf211/jobmngt/dao/SectorDao.class differ diff --git a/target/classes/fr/atlantique/imt/inf211/jobmngt/entity/AppUser.class b/target/classes/fr/atlantique/imt/inf211/jobmngt/entity/AppUser.class index ca1884563592394285cda6b3c92ce79bbb94cb11..090606a3afcb7e323b9644541b2b5bab499e6c61 100644 Binary files a/target/classes/fr/atlantique/imt/inf211/jobmngt/entity/AppUser.class and b/target/classes/fr/atlantique/imt/inf211/jobmngt/entity/AppUser.class differ diff --git a/target/classes/fr/atlantique/imt/inf211/jobmngt/entity/Application.class b/target/classes/fr/atlantique/imt/inf211/jobmngt/entity/Application.class index 572bd81d49af528d4f85be3005e84686055e7fca..5fddf38c1f2c12a3257598eb8e3d038927f808f6 100644 Binary files a/target/classes/fr/atlantique/imt/inf211/jobmngt/entity/Application.class and b/target/classes/fr/atlantique/imt/inf211/jobmngt/entity/Application.class differ diff --git a/target/classes/fr/atlantique/imt/inf211/jobmngt/entity/ApplicationMessage.class b/target/classes/fr/atlantique/imt/inf211/jobmngt/entity/ApplicationMessage.class index 94b5d8300bea8f896a3b89ebe32d6d49e72167ef..3ea69a3c3b7a79cc8e8032110bc7340cb4dd49ff 100644 Binary files a/target/classes/fr/atlantique/imt/inf211/jobmngt/entity/ApplicationMessage.class and b/target/classes/fr/atlantique/imt/inf211/jobmngt/entity/ApplicationMessage.class differ diff --git a/target/classes/fr/atlantique/imt/inf211/jobmngt/entity/Candidate.class b/target/classes/fr/atlantique/imt/inf211/jobmngt/entity/Candidate.class index 1e2bc7aa657a3cfe9be477d995cdb16276863040..135543e0180417a02d8be1df9de1e55ba45586f5 100644 Binary files a/target/classes/fr/atlantique/imt/inf211/jobmngt/entity/Candidate.class and b/target/classes/fr/atlantique/imt/inf211/jobmngt/entity/Candidate.class differ diff --git a/target/classes/fr/atlantique/imt/inf211/jobmngt/entity/Company.class b/target/classes/fr/atlantique/imt/inf211/jobmngt/entity/Company.class index a1fd23885096354fe952948017a5a2239e96ceb5..4b6589240fa1bb74d160a97f895a5bee30bdec99 100644 Binary files a/target/classes/fr/atlantique/imt/inf211/jobmngt/entity/Company.class and b/target/classes/fr/atlantique/imt/inf211/jobmngt/entity/Company.class differ diff --git a/target/classes/fr/atlantique/imt/inf211/jobmngt/entity/JobOffer.class b/target/classes/fr/atlantique/imt/inf211/jobmngt/entity/JobOffer.class index f3064e3c51cc5ec1e6890cb1635b6adb53523dab..d0c222ab2361940776710d9a425e073324eeddbc 100644 Binary files a/target/classes/fr/atlantique/imt/inf211/jobmngt/entity/JobOffer.class and b/target/classes/fr/atlantique/imt/inf211/jobmngt/entity/JobOffer.class differ diff --git a/target/classes/fr/atlantique/imt/inf211/jobmngt/entity/OfferMessage.class b/target/classes/fr/atlantique/imt/inf211/jobmngt/entity/OfferMessage.class index c3808951a49b5bab19ef144587e807649ef7254b..2bf7663fdb299a1f49f3cfa134e7ee56109f1ff1 100644 Binary files a/target/classes/fr/atlantique/imt/inf211/jobmngt/entity/OfferMessage.class and b/target/classes/fr/atlantique/imt/inf211/jobmngt/entity/OfferMessage.class differ diff --git a/target/classes/fr/atlantique/imt/inf211/jobmngt/entity/QualificationLevel.class b/target/classes/fr/atlantique/imt/inf211/jobmngt/entity/QualificationLevel.class index b9fff9b0711bc03004b71f3a6436d5583a60c8ae..79b9c5db3994ec9fc109e6191645f40a949a30ff 100644 Binary files a/target/classes/fr/atlantique/imt/inf211/jobmngt/entity/QualificationLevel.class and b/target/classes/fr/atlantique/imt/inf211/jobmngt/entity/QualificationLevel.class differ diff --git a/target/classes/fr/atlantique/imt/inf211/jobmngt/entity/Sector.class b/target/classes/fr/atlantique/imt/inf211/jobmngt/entity/Sector.class index 4a368de5745fae2cbcee9180b53724f6df60f07a..dc2efbc4ec65c937d69e1b36c9c0b999dadd6a65 100644 Binary files a/target/classes/fr/atlantique/imt/inf211/jobmngt/entity/Sector.class and b/target/classes/fr/atlantique/imt/inf211/jobmngt/entity/Sector.class differ diff --git a/target/classes/fr/atlantique/imt/inf211/jobmngt/service/AppUserService.class b/target/classes/fr/atlantique/imt/inf211/jobmngt/service/AppUserService.class index 9d72472a36a6ab69616234ea7df7a8b0f74d3aa5..347b8c84689a6cc0ce961a09f81891b049a7dec3 100644 Binary files a/target/classes/fr/atlantique/imt/inf211/jobmngt/service/AppUserService.class and b/target/classes/fr/atlantique/imt/inf211/jobmngt/service/AppUserService.class differ diff --git a/target/classes/fr/atlantique/imt/inf211/jobmngt/service/AppUserServiceImpl.class b/target/classes/fr/atlantique/imt/inf211/jobmngt/service/AppUserServiceImpl.class index 3228527ea8ab8d6aa2fbdc25684e9fe6230ed4e0..b7d4f38bb88c61a88aa0531663e2870e6d6b3e81 100644 Binary files a/target/classes/fr/atlantique/imt/inf211/jobmngt/service/AppUserServiceImpl.class and b/target/classes/fr/atlantique/imt/inf211/jobmngt/service/AppUserServiceImpl.class differ diff --git a/target/classes/fr/atlantique/imt/inf211/jobmngt/service/ApplicationService.class b/target/classes/fr/atlantique/imt/inf211/jobmngt/service/ApplicationService.class index e69c4e36058d14d7685097aadf83d243bab68fcf..9039bc596b01e2ab3fc4598fd060419606c97e53 100644 Binary files a/target/classes/fr/atlantique/imt/inf211/jobmngt/service/ApplicationService.class and b/target/classes/fr/atlantique/imt/inf211/jobmngt/service/ApplicationService.class differ diff --git a/target/classes/fr/atlantique/imt/inf211/jobmngt/service/ApplicationServiceImpl.class b/target/classes/fr/atlantique/imt/inf211/jobmngt/service/ApplicationServiceImpl.class new file mode 100644 index 0000000000000000000000000000000000000000..0276f5fbd3ba7d4de348c33ca1a0fb0813c409e0 Binary files /dev/null and b/target/classes/fr/atlantique/imt/inf211/jobmngt/service/ApplicationServiceImpl.class differ diff --git a/target/classes/fr/atlantique/imt/inf211/jobmngt/service/CandidateService.class b/target/classes/fr/atlantique/imt/inf211/jobmngt/service/CandidateService.class index 9f0685154fb00d5101ae34c83ffb2ad0fb37888e..b53649f409c330bc61f4e400f2630086e32f4a4e 100644 Binary files a/target/classes/fr/atlantique/imt/inf211/jobmngt/service/CandidateService.class and b/target/classes/fr/atlantique/imt/inf211/jobmngt/service/CandidateService.class differ diff --git a/target/classes/fr/atlantique/imt/inf211/jobmngt/service/CandidateServiceImpl.class b/target/classes/fr/atlantique/imt/inf211/jobmngt/service/CandidateServiceImpl.class index 58e6e22527f9af417da7dc694e7c913c307d8b5a..044c6bb116c183d91051d000a621cd1c4bbdd870 100644 Binary files a/target/classes/fr/atlantique/imt/inf211/jobmngt/service/CandidateServiceImpl.class and b/target/classes/fr/atlantique/imt/inf211/jobmngt/service/CandidateServiceImpl.class differ diff --git a/target/classes/fr/atlantique/imt/inf211/jobmngt/service/CompanyService.class b/target/classes/fr/atlantique/imt/inf211/jobmngt/service/CompanyService.class index e2861966110f6a9d7e4017cb32fa8e8136582dd6..531c366e00e39c8d642c1344b34582c97fe73e08 100644 Binary files a/target/classes/fr/atlantique/imt/inf211/jobmngt/service/CompanyService.class and b/target/classes/fr/atlantique/imt/inf211/jobmngt/service/CompanyService.class differ diff --git a/target/classes/fr/atlantique/imt/inf211/jobmngt/service/CompanyServiceImpl.class b/target/classes/fr/atlantique/imt/inf211/jobmngt/service/CompanyServiceImpl.class index 8ad1a9e13a4bda5e25887a5aab25d99113405907..7603576a2573c5fa12706c591dff3ff3da7d3ff9 100644 Binary files a/target/classes/fr/atlantique/imt/inf211/jobmngt/service/CompanyServiceImpl.class and b/target/classes/fr/atlantique/imt/inf211/jobmngt/service/CompanyServiceImpl.class differ diff --git a/target/classes/fr/atlantique/imt/inf211/jobmngt/service/JobOfferService.class b/target/classes/fr/atlantique/imt/inf211/jobmngt/service/JobOfferService.class index 26391a03bc3ab02727f3298cfefbca83ab08cd5f..331abe9a8037f5ae8fb6f5bf213ae75d3cd11c95 100644 Binary files a/target/classes/fr/atlantique/imt/inf211/jobmngt/service/JobOfferService.class and b/target/classes/fr/atlantique/imt/inf211/jobmngt/service/JobOfferService.class differ diff --git a/target/classes/fr/atlantique/imt/inf211/jobmngt/service/JobOfferServiceImpl.class b/target/classes/fr/atlantique/imt/inf211/jobmngt/service/JobOfferServiceImpl.class index 07d82d2396b8f375655256c2aeaa82ffe73a2cd6..0e2b451e33427573d29944f7307137fa13bd7dc1 100644 Binary files a/target/classes/fr/atlantique/imt/inf211/jobmngt/service/JobOfferServiceImpl.class and b/target/classes/fr/atlantique/imt/inf211/jobmngt/service/JobOfferServiceImpl.class differ diff --git a/target/classes/fr/atlantique/imt/inf211/jobmngt/service/QualificationLevelService.class b/target/classes/fr/atlantique/imt/inf211/jobmngt/service/QualificationLevelService.class index 9041f0c3c890f54d2e7470b8a8e0ad3971f33fd9..1b70eef46d04839cbe15a53e61fb03fafbfb0716 100644 Binary files a/target/classes/fr/atlantique/imt/inf211/jobmngt/service/QualificationLevelService.class and b/target/classes/fr/atlantique/imt/inf211/jobmngt/service/QualificationLevelService.class differ diff --git a/target/classes/fr/atlantique/imt/inf211/jobmngt/service/QualificationLevelServiceImpl.class b/target/classes/fr/atlantique/imt/inf211/jobmngt/service/QualificationLevelServiceImpl.class index 76a96deda1f4926ec672cd327a12bd1eb3771e39..65051ed719687baf738b9e59335caa59eac0262d 100644 Binary files a/target/classes/fr/atlantique/imt/inf211/jobmngt/service/QualificationLevelServiceImpl.class and b/target/classes/fr/atlantique/imt/inf211/jobmngt/service/QualificationLevelServiceImpl.class differ diff --git a/target/classes/fr/atlantique/imt/inf211/jobmngt/service/SectorService.class b/target/classes/fr/atlantique/imt/inf211/jobmngt/service/SectorService.class index 61d79354cd1102fc1cbb5035aa590819dcdbc583..ad6840b8f640dd1a00ced437059aa871aedb98d8 100644 Binary files a/target/classes/fr/atlantique/imt/inf211/jobmngt/service/SectorService.class and b/target/classes/fr/atlantique/imt/inf211/jobmngt/service/SectorService.class differ diff --git a/target/classes/fr/atlantique/imt/inf211/jobmngt/service/SectorServiceImpl.class b/target/classes/fr/atlantique/imt/inf211/jobmngt/service/SectorServiceImpl.class index 8c17b588ea26399177cd62cc785a7da081b85237..9592705e7684f3567598e4b8b7b472147a8bba1d 100644 Binary files a/target/classes/fr/atlantique/imt/inf211/jobmngt/service/SectorServiceImpl.class and b/target/classes/fr/atlantique/imt/inf211/jobmngt/service/SectorServiceImpl.class differ diff --git a/target/classes/static/css/gyj_imt.css b/target/classes/static/css/gyj_imt.css index 3e785e015a71cf55f1a4abba4be53e9ae9e13250..fae8405c753b39e5943feb2ea79137246e36ac93 100644 --- a/target/classes/static/css/gyj_imt.css +++ b/target/classes/static/css/gyj_imt.css @@ -84,3 +84,68 @@ text-align: left; padding-left: 5px; } + +.card-cover { + height: 250px; + display: flex; + align-items: center; + justify-content: center; + text-align: center; + background-size: cover; + background-position: center; + border-radius: 10px; + transition: transform 0.3s ease-in-out; +} + +.card-cover:hover { + transform: scale(1.05); +} + +.card-cover { + height: 250px; /* Uniformiser la taille */ + display: flex; + align-items: center; + justify-content: center; + text-align: center; + background-size: cover; + background-position: center; + border-radius: 10px; + transition: transform 0.3s ease-in-out; +} + +.card-cover:hover { + transform: scale(1.05); +} + +.card-black { + background-color: black !important; +} + +.card-black h2 { + color: white !important; +} + +.card-cover { + height: 250px; /* Uniformiser la taille */ + display: flex; + align-items: center; + justify-content: center; + text-align: center; + background-size: cover; + background-position: center; + border-radius: 10px; + transition: transform 0.3s ease-in-out; +} + +.card-cover:hover { + transform: scale(1.05); +} + +.card-black { + background-color: black !important; +} + +.card-black h2 { + color: white !important; +} + diff --git a/target/classes/static/img/postuler.jpeg b/target/classes/static/img/postuler.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..719afa2cb849e0cd116298087f7d6aab814d5dab Binary files /dev/null and b/target/classes/static/img/postuler.jpeg differ diff --git a/target/classes/templates/application/application-confirmation.html b/target/classes/templates/application/application-confirmation.html new file mode 100644 index 0000000000000000000000000000000000000000..49c8ab4c0d24fd87c8419c8f3120fa7036c754d8 --- /dev/null +++ b/target/classes/templates/application/application-confirmation.html @@ -0,0 +1,36 @@ +<!DOCTYPE html> +<html xmlns:th="http://www.thymeleaf.org"> +<head> + <meta charset="UTF-8"> + <title>Confirmation de Candidature</title> + <link rel="stylesheet" th:href="@{/css/bootstrap.min.css}"> +</head> +<body> + <div class="container"> + <div class="alert alert-success mt-5 text-center"> + <h2> Votre candidature a été soumise avec succès !</h2> + </div> + + <h3 class="mt-4">📄 Détails de la candidature :</h3> + + <div th:if="${application != null}"> + <table class="table table-bordered"> + <tr><th>ID</th><td th:text="${application.id != null ? application.id : 'Non spécifié'}"></td></tr> + <tr><th> CV</th><td th:text="${application.cv != null ? application.cv : 'Non spécifié'}"></td></tr> + <tr><th> Niveau de qualification</th> + <td th:text="${application.qualificationlevel != null ? application.qualificationlevel.label : 'Non spécifié'}"></td> + </tr> + <tr><th> Secteurs d'activité</th> + <td th:each="sector : ${application.sectors}" th:text="${sector.label}"></td> + </tr> + <tr><th> Date de dépôt</th> + <td th:text="${application.appdate != null ? application.appdate : 'Non spécifié'}"></td> + </tr> + + </table> + </div> + + <a href="/" class="btn btn-primary mt-3"> Retour à l'accueil</a> + </div> +</body> +</html> diff --git a/target/classes/templates/application/application-details.html b/target/classes/templates/application/application-details.html new file mode 100644 index 0000000000000000000000000000000000000000..4a53d5b0d38cedcd9c3949f8e676ea2f5cfa13eb --- /dev/null +++ b/target/classes/templates/application/application-details.html @@ -0,0 +1,49 @@ +<!DOCTYPE html> +<html xmlns:th="http://www.thymeleaf.org"> +<head> + <meta charset="UTF-8"> + <title>Détails de la Candidature</title> + <link rel="stylesheet" th:href="@{/css/bootstrap.min.css}"> +</head> +<body> + <div class="container mt-5"> + <h2 class="mb-4"> Détails de la Candidature</h2> + + <div th:if="${error}" class="alert alert-warning"> + <p th:text="${error}"></p> + </div> + + <div class="card"> + <div class="card-body"> + <h5 class="card-title"> + Nom: + <span th:if="${application.candidate != null}" th:text="${application.candidate.firstname + ' ' + application.candidate.lastname}"></span> + <span th:unless="${application.candidate != null}">Non disponible</span> + </h5> + + <p class="card-text"> + <span th:if="${application.cv != null}" th:text="'CV: ' + ${application.cv}"></span> + <span th:unless="${application.cv != null}">Non disponible</span> + </p> + + <p class="card-text"> + <span th:if="${application.qualificationlevel != null}" th:text="'Niveau de Qualification: ' + ${application.qualificationlevel.label}"></span> + <span th:unless="${application.qualificationlevel != null}">Non disponible</span> + </p> + + <p class="card-text"> + <span th:each="sector : ${application.sectors}" th:text="'Secteur: ' + ${sector.label}"></span> + <span th:if="${#lists.isEmpty(application.sectors)}">Secteurs non disponibles</span> + </p> + + <p class="card-text"> + <span th:if="${application.appdate != null}" th:text="'Date de dépôt: ' + ${application.appdate}"></span> + <span th:unless="${application.appdate != null}">Non disponible</span> + </p> + </div> + </div> + + <a th:href="@{/applications/list}" class="btn btn-primary mt-3">Retour à la liste des candidatures</a> + </div> +</body> +</html> \ No newline at end of file diff --git a/target/classes/templates/application/application-edit.html b/target/classes/templates/application/application-edit.html new file mode 100644 index 0000000000000000000000000000000000000000..f68c9eca601803bc0fefcd04d0de283c53478c41 --- /dev/null +++ b/target/classes/templates/application/application-edit.html @@ -0,0 +1,17 @@ +<form th:action="@{/applications/update}" method="post"> + <input type="hidden" name="id" th:value="${application.id}"> + <label>CV :</label> + <input type="text" name="cv" th:value="${application.cv}" required> + + <label>Niveau de qualification :</label> + <select name="qualificationLevel"> + <option th:each="q : ${qualifications}" th:value="${q.id}" th:text="${q.label}"></option> + </select> + + <label>Secteurs :</label> + <select name="sectors" multiple> + <option th:each="s : ${sectors}" th:value="${s.id}" th:text="${s.label}"></option> + </select> + + <button type="submit">Modifier</button> +</form> diff --git a/target/classes/templates/application/application-list.html b/target/classes/templates/application/application-list.html index 51c91843050143eeb24b54a98cfcf2ae6a3e2ad4..2200f3182c91b13442415c476cc118d9565b44c9 100644 --- a/target/classes/templates/application/application-list.html +++ b/target/classes/templates/application/application-list.html @@ -6,41 +6,71 @@ <link rel="stylesheet" th:href="@{/css/bootstrap.min.css}"> </head> <body> - <div class="container"> - <h2 class="mt-5">Liste des Candidatures</h2> + <div class="container mt-5"> + <h2 class="mb-4">Liste des Candidatures</h2> - <table class="table table-striped mt-3"> + <div th:if="${error}" class="alert alert-warning"> + <p th:text="${error}"></p> + </div> + + <table class="table table-bordered table-striped" th:if="${applicationsList}"> <thead> <tr> <th>ID</th> - <th>Nom du Candidat</th> + <th>Nom</th> <th>Prénom</th> <th>CV</th> <th>Niveau de Qualification</th> - <th>Secteurs</th> - <th>Date de Dépôt</th> + <th>Secteurs d'activité</th> + <th>Date de dépôt</th> + <th>Détails</th> + <th>Modifier</th> + <th>Supprimer</th> </tr> </thead> <tbody> - <tr th:each="application : ${applications}"> - <td th:text="${application.id}"></td> - <td th:text="${application.candidate.lastname}"></td> - <td th:text="${application.candidate.firstname}"></td> - <td> - <a th:href="@{/cv/{cvFile}(cvFile=${application.cv})}" target="_blank">Voir CV</a> - </td> - <td th:text="${application.qualificationlevel.label}"></td> + <tr th:each="app : ${applicationsList}"> + <td th:text="${app.id}"></td> + <td th:text="${app.candidate.firstname}"></td> + <td th:text="${app.candidate.lastname}"></td> + <td><a th:href="@{${app.cv}}" th:text="${app.cv}"></a></td> + <td th:text="${app.qualificationlevel.label}"></td> <td> <ul> - <li th:each="sector : ${application.sectors}" th:text="${sector.label}"></li> + <li th:each="sector : ${app.sectors}" th:text="${sector.label}"></li> </ul> </td> - <td th:text="${application.appdate}"></td> + <td th:text="${app.appdate}"></td> + <td> + <a th:href="@{/applications/details/{id}(id=${app.id})}" class="btn btn-info">Détails</a> + </td> + + <!-- Vérification que l'utilisateur est connecté et est le propriétaire --> + <td th:if="${session.uid != null && session.uid == app.candidate.id}"> + <a th:href="@{/applications/edit/{id}(id=${app.id})}" class="btn btn-warning">Modifier</a> + </td> + <td th:if="${session.uid != null && session.uid == app.candidate.id}"> + <a th:href="@{/applications/delete/{id}(id=${app.id})}" class="btn btn-danger" + onclick="return confirm('Êtes-vous sûr de vouloir supprimer cette candidature ?');"> + Supprimer + </a> + </td> + + <!-- Affichage d'un message si l'utilisateur n'est pas connecté --> + <td th:if="${session.uid == null}" colspan="2"> + <a th:href="@{/login}" class="btn btn-secondary">Se connecter</a> + </td> </tr> </tbody> </table> - <a th:href="@{/}" class="btn btn-secondary mt-3">Retour</a> + <a th:href="@{/}" class="btn btn-primary mt-3">Retour à l'accueil</a> </div> </body> </html> + + + + + + diff --git a/target/classes/templates/application/application-update-form.html b/target/classes/templates/application/application-update-form.html new file mode 100644 index 0000000000000000000000000000000000000000..26266c1eb803c2a61e4fa4d794429159bb970af7 --- /dev/null +++ b/target/classes/templates/application/application-update-form.html @@ -0,0 +1,46 @@ +<!DOCTYPE html> +<html xmlns:th="http://www.thymeleaf.org"> +<head> + <meta charset="UTF-8"> + <title>Mettre à jour la Candidature</title> + <link rel="stylesheet" th:href="@{/css/bootstrap.min.css}"> +</head> +<body> + <div class="container mt-5"> + <h2 class="mb-4">Modifier ma Candidature</h2> + + <form th:action="@{/applications/update/{id}(id=${application.id})}" method="post"> + <div class="form-group"> + <label for="cv">CV</label> + <input type="text" id="cv" name="cv" class="form-control" th:value="${application.cv}" required> + </div> + + <div class="form-group"> + <label for="qualificationLevel">Niveau de Qualification</label> + <select id="qualificationLevel" name="qualificationLevel" class="form-control"> + <option th:each="qualification : ${qualifications}" + th:value="${qualification.id}" + th:text="${qualification.label}" + th:selected="${qualification.id == application.qualificationlevel.id}"> + </option> + </select> + </div> + + <div class="form-group"> + <label>Secteurs d'activité</label> + <select multiple name="sectors" class="form-control"> + <option th:each="sector : ${sectors}" + th:value="${sector.id}" + th:text="${sector.label}" + th:selected="${application.sectors.contains(sector)}"> + </option> + </select> + </div> + + <button type="submit" class="btn btn-primary mt-3">Mettre à jour</button> + </form> + + <a th:href="@{/applications/list}" class="btn btn-secondary mt-3">Retour à la liste des candidatures</a> + </div> +</body> +</html> diff --git a/target/classes/templates/application/apply.html b/target/classes/templates/application/apply.html new file mode 100644 index 0000000000000000000000000000000000000000..4615526e200b1aff678ccab99012d1ea5eb414a7 --- /dev/null +++ b/target/classes/templates/application/apply.html @@ -0,0 +1,74 @@ +<!DOCTYPE html> +<html xmlns:th="http://www.thymeleaf.org"> +<head> + <meta charset="UTF-8"> + <title>Postuler à une offre</title> + <link rel="stylesheet" th:href="@{/css/bootstrap.min.css}"> + <style> + body { + background-color: #f8f9fa; /* Couleur de fond */ + } + .container { + max-width: 600px; + margin-top: 50px; + background: #ffffff; + padding: 20px; + border-radius: 10px; + box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.1); + } + h2 { + text-align: center; + color: #007bff; /* Bleu Bootstrap */ + } + label { + font-weight: bold; + color: #343a40; + } + .form-control { + margin-bottom: 10px; + } + .btn-submit { + background-color: #007bff; + color: white; + width: 100%; + } + .btn-submit:hover { + background-color: #0056b3; + } + </style> +</head> +<body> + <div class="container"> + <h2> Postuler à une offre</h2> + + <form th:action="@{/applications/apply}" method="post"> + <!-- Champ CV --> + <div class="form-group"> + <label for="cv">CV :</label> + <input type="text" id="cv" name="cv" class="form-control" placeholder="Lien vers votre CV" required> + </div> + + <!-- Niveau de qualification --> + <div class="form-group"> + <label for="qualificationLevel">Niveau de qualification :</label> + <select id="qualificationLevel" name="qualificationLevel" class="form-control" required> + <option value="">Choisir un niveau</option> + <option th:each="qualification : ${qualifications}" th:value="${qualification.id}" th:text="${qualification.label}"></option> + </select> + </div> + + <!-- Secteurs d'activité --> + <div class="form-group"> + <label for="sectors">Secteurs d'activité :</label> + <select id="sectors" name="sectors" class="form-control" multiple required> + <option th:each="sector : ${sectors}" th:value="${sector.id}" th:text="${sector.label}"></option> + </select> + <small class="form-text text-muted">Maintenez la touche Ctrl (Cmd sur Mac) pour sélectionner plusieurs options.</small> + </div> + + <!-- Bouton de soumission --> + <button type="submit" class="btn btn-submit"> Soumettre</button> + </form> + </div> +</body> +</html> diff --git a/target/classes/templates/application/my-application-list.html b/target/classes/templates/application/my-application-list.html new file mode 100644 index 0000000000000000000000000000000000000000..15d8a4447c1d6fa55d93f03f6d45e9ef37d16910 --- /dev/null +++ b/target/classes/templates/application/my-application-list.html @@ -0,0 +1,43 @@ +<!DOCTYPE html> +<html xmlns:th="http://www.thymeleaf.org"> +<head> + <meta charset="UTF-8"> + <title>My Applications</title> + <link rel="stylesheet" th:href="@{/css/bootstrap.min.css}"> +</head> +<body> + <div class="container"> + <h2 class="mt-5">My Applications</h2> + + <!-- Message d'erreur --> + <div th:if="${error}" class="alert alert-danger" th:text="${error}"></div> + + <table class="table table-striped mt-3"> + <thead> + <tr> + <th>ID</th> + <th>CV</th> + <th>Qualification Level</th> + <th>Sector(s)</th> + <th>Application Date</th> + </tr> + </thead> + <tbody> + <tr th:each="application : ${applications}"> + <td th:text="${application.id}"></td> + <td th:text="${application.cv}"></td> + <td th:text="${application.qualificationlevel.label}"></td> + <td> + <ul> + <li th:each="sector : ${application.sectors}" th:text="${sector.label}"></li> + </ul> + </td> + <td th:text="${#dates.format(application.appdate, 'yyyy-MM-dd')}"></td> + </tr> + </tbody> + </table> + + <a th:href="@{/}" class="btn btn-secondary mt-3">Back to Home</a> + </div> +</body> +</html> diff --git a/target/classes/templates/baseTemplate/nav.html b/target/classes/templates/baseTemplate/nav.html index 50a1225f59538ce9c942ccac695ed32c8fa176a0..36532658f8e5cad9ec42eda3dd4815dcf37db6ef 100644 --- a/target/classes/templates/baseTemplate/nav.html +++ b/target/classes/templates/baseTemplate/nav.html @@ -43,12 +43,11 @@ <li class="nav-item"> <a class="nav-link" th:href="@{/jobs}">Jobs</a> </li> - <li class="nav-item"> - <a class="nav-link" href="/">Candidates </a> + <a class="nav-link" th:href="@{/candidates/list}">Candidates</a> </li> <li class="nav-item"> - <a class="nav-link" href="/">Applications</a> + <a class="nav-link" th:href="@{/applications/list}">Applications</a> </li> <li class="nav-item"> <a class="nav-link" th:href="@{/qualificationLevels}">Qualification levels</a> @@ -56,7 +55,6 @@ <li class="nav-item"> <a class="nav-link" th:href="@{/sectors}">Sectors</a> </li> - </ul> </div> diff --git a/target/classes/templates/candidate/candidates-list.html b/target/classes/templates/candidate/candidates-list.html index 7a4f23a9b8e85bcd6ad60f70fbf54c42df317432..039447c90e40d3dca0a29cd98e7432b9eb005b83 100644 --- a/target/classes/templates/candidate/candidates-list.html +++ b/target/classes/templates/candidate/candidates-list.html @@ -32,6 +32,7 @@ <td th:text="${candidate.mail}"></td> <td> <a th:href="@{/candidates/details/{id}(id=${candidate.id})}" class="btn btn-info btn-sm">Détails</a> + <span th:if="${#ctx.session.uid} != null and ${#ctx.session.uid} == ${candidate.id} ">PEUT SUPPRIMER</span> </td> </tr> </tbody> diff --git a/target/classes/templates/candidate/confirmation.html b/target/classes/templates/candidate/confirmation.html index 4746bdbee768888d900394e682041d0d1cb37b6d..8a22d725d2dd69e9120247d20355b72a469b08a1 100644 --- a/target/classes/templates/candidate/confirmation.html +++ b/target/classes/templates/candidate/confirmation.html @@ -1,14 +1,34 @@ <!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <head> - <title>Registration Successful</title> - <link rel="stylesheet" th:href="@{/css/bootstrap.min.css}" /> + <meta charset="UTF-8"> + <title>Confirmation</title> + <link rel="stylesheet" th:href="@{/css/bootstrap.min.css}"> </head> -<body class="container mt-5"> - <div class="alert alert-success text-center"> - <h2>Operation Successful</h2> - <p th:text="${message}"></p> - <a th:href="@{/login}" class="btn btn-primary">Go to Login</a> +<body> + <div class="container"> + <div class="alert alert-success mt-5 text-center"> + <h2>Operation Successful</h2> + <p th:text="${message}"></p> + </div> + + <!-- Affichage des infos du candidat uniquement si c'est une modification --> + <div th:if="${candidate != null}"> + <h3>Informations mises à jour :</h3> + <table class="table table-bordered"> + <tr><th>ID</th><td th:text="${candidate.id}"></td></tr> + <tr><th>Nom</th><td th:text="${candidate.lastname}"></td></tr> + <tr><th>Prénom</th><td th:text="${candidate.firstname}"></td></tr> + <tr><th>Email</th><td th:text="${candidate.mail}"></td></tr> + <tr><th>Ville</th><td th:text="${candidate.city}"></td></tr> + </table> + </div> + + <!-- Bouton différent selon la situation --> + <div class="text-center"> + <a th:if="${candidate != null}" th:href="@{/candidates/list}" class="btn btn-primary">Retour à la liste des candidats</a> + <a th:if="${candidate == null}" th:href="@{/login}" class="btn btn-primary">Go to Login</a> + </div> </div> </body> </html> diff --git a/target/classes/templates/candidate/confirmationSupp.html b/target/classes/templates/candidate/confirmationSupp.html new file mode 100644 index 0000000000000000000000000000000000000000..a8ebbf083b54a7d5ec3e83107bcd51533c418614 --- /dev/null +++ b/target/classes/templates/candidate/confirmationSupp.html @@ -0,0 +1,18 @@ +<!DOCTYPE html> +<html xmlns:th="http://www.thymeleaf.org"> +<head> + <meta charset="UTF-8"> + <title>Confirmation</title> + <link rel="stylesheet" th:href="@{/css/bootstrap.min.css}"> +</head> +<body> + <div class="container"> + <div class="alert alert-success mt-5"> + <h2>Opération Réussie </h2> + <p th:text="${message}"></p> + </div> + + <a th:href="@{/candidates/list}" class="btn btn-primary">Retour à la liste des candidats</a> + </div> +</body> +</html> diff --git a/target/classes/templates/candidate/editCandidate.html b/target/classes/templates/candidate/editCandidate.html index 5a9a4e54424a22ad7728516d77d0fba0ccbc789f..8bc1e65f63dff81577a04e2e1c90e51ec3c3d776 100644 --- a/target/classes/templates/candidate/editCandidate.html +++ b/target/classes/templates/candidate/editCandidate.html @@ -14,7 +14,8 @@ <div class="form-group"> <label>Email :</label> - <input type="email" name="mail" class="form-control" th:value="${candidate.mail}" required> + <!-- <input type="email" name="mail" class="form-control" th:value="${candidate.mail}" required> --> + <input type="email" class="form-control" name="mail" required th:value="${candidate.mail}" readonly /> </div> <div class="form-group"> diff --git a/target/classes/templates/candidate/signupCandidate.html b/target/classes/templates/candidate/signupCandidate.html index f65ae0ca113bcebf27bc51195131fdd2f28ee338..f8d74e5e6e033c038888c4f69ec112a65775d012 100644 --- a/target/classes/templates/candidate/signupCandidate.html +++ b/target/classes/templates/candidate/signupCandidate.html @@ -16,7 +16,7 @@ <form th:action="@{/candidates/signup}" method="post"> <div class="mb-3"> <label for="mail" class="form-label">Email address</label> - <input type="email" class="form-control" id="mail" name="mail" required> + <input type="email" class="form-control" name="mail" required th:value="${mail}" /> </div> <div class="mb-3"> <label for="password" class="form-label">Password</label> @@ -24,15 +24,15 @@ </div> <div class="mb-3"> <label for="lastname" class="form-label">Last Name</label> - <input type="text" class="form-control" id="lastname" name="lastname" required> + <input type="text" class="form-control" id="lastname" name="lastname" th:value="${lastname}" required> </div> <div class="mb-3"> <label for="firstname" class="form-label">First Name</label> - <input type="text" class="form-control" id="firstname" name="firstname" required> + <input type="text" class="form-control" id="firstname" name="firstname" th:value="${firstname}" required> </div> <div class="mb-3"> <label for="city" class="form-label">City</label> - <input type="text" class="form-control" id="city" name="city" required> + <input type="text" class="form-control" id="city" name="city" th:value="${city}" required> </div> <button type="submit" class="btn btn-primary">Sign Up</button> diff --git a/target/classes/templates/index.html b/target/classes/templates/index.html index c1991881ba5db7603cc296318ec59feabfcef978..d53f468fed2d575137455cbab6fcbe5c80ab9573 100644 --- a/target/classes/templates/index.html +++ b/target/classes/templates/index.html @@ -5,7 +5,7 @@ <header> <h1 class="pb-2 border-bottom">GetYourJob</h1> </header> - +<!-- <div class="row row-cols-1 row-cols-lg-3 align-items-stretch g-4 py-5"> <article class="col"> <a th:href="@{/companies}" @@ -27,8 +27,8 @@ </a> </article> - <!-- ✅ Section Candidats --> - <article class="col"> + ✅ Section Candidats --> + <!-- <article class="col"> <a th:href="@{/candidates}" class="nav-link card card-cover h-100 overflow-hidden text-white bg-dark rounded-5 shadow-lg" style="background-image: url('/img/candidates.jpg'); background-size: cover;"> @@ -47,7 +47,47 @@ </div> </a> </article> - </div> + </div> --> + <!-- bouton pour permettre aux candidats de soumettre une candidature depuis l'accueil. --> + <!-- <article class="col"> + <a th:href="@{/applications/apply}" + class="nav-link card card-cover h-100 overflow-hidden text-white bg-black rounded-5 shadow-lg" + style="background-image: url('/img/postuler.jpeg'); background-size: cover; background-position: center; height: 250px;"> + <div class="d-flex flex-column h-100 p-5 pb-3 text-shadow-1 text-center"> + <h2 class="pt-5 mt-5 mb-4 display-6 lh-1 fw-bold text-dark">Postuler</h2> + </div> + </a> +</article> --> + +<div class="row row-cols-1 row-cols-lg-3 align-items-stretch g-4 py-5"> + <article class="col"> + <a th:href="@{/companies}" class="nav-link card card-cover h-100 overflow-hidden text-white bg-dark rounded-5 shadow-lg" + style="background-image: url('/img/companies.jpg'); background-size: cover;"> + <div class="d-flex flex-column h-100 p-5 pb-3 text-white text-shadow-1"> + <h2 class="pt-5 mt-5 mb-4 display-6 lh-1 fw-bold">Companies</h2> + </div> + </a> + </article> + + <article class="col"> + <a th:href="@{/candidates}" class="nav-link card card-cover h-100 overflow-hidden text-white bg-dark rounded-5 shadow-lg" + style="background-image: url('/img/candidates.jpg'); background-size: cover;"> + <div class="d-flex flex-column h-100 p-5 pb-3 text-white text-shadow-1"> + <h2 class="pt-5 mt-5 mb-4 display-6 lh-1 fw-bold">Candidates</h2> + </div> + </a> + </article> + + <!-- ✅ Déplacement de "Postuler" dans la même ligne --> + <article class="col"> + <a th:href="@{/applications/apply}" class="nav-link card card-cover h-100 overflow-hidden text-white bg-dark rounded-5 shadow-lg" + style="background-image: url('/img/postuler.jpeg'); background-size: cover;"> + <div class="d-flex flex-column h-100 p-5 pb-3 text-white text-shadow-1"> + <h2 class="pt-5 mt-5 mb-4 display-6 lh-1 fw-bold text-dark">Postuler</h2> + </div> + </a> + </article> +</div> </section> diff --git a/target/classes/templates/login.html b/target/classes/templates/login.html index 6eb88d0a63673d4559c96bcbbb0bb368212f8f87..fbaa5e7d82095b9735edaf37a77c33436b1ff78e 100644 --- a/target/classes/templates/login.html +++ b/target/classes/templates/login.html @@ -1,17 +1,18 @@ <!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org" th:fragment="article(subcontent)" th:replace="~{/baseTemplate/base :: layout(~{},~{::section})}"> + <section class="modal modal-sheet position-static d-block bg-body-secondary p-4 py-md-5" tabindex="-1"> <div class="modal-dialog" role="document"> <div class="modal-content rounded-4 shadow"> <header class="modal-header p-5 pb-4 border-bottom-0"> <h1 class="fw-bold mb-0 fs-2">Sign in</h1> - <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"> - </button> + <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button> </header> - <article class="modal-body p-5 pt-0"> + + <article class="modal-body p-5 pt-0"> <small class="text-secondary">Log in by entering your email address and password.</small> - <form action="login" method="post"> + <form action="/login" method="post"> <fieldset class="mb-3 form-floating"> <input type="email" id="uid" class="form-control rounded-3" name="mail" autofocus="autofocus" required placeholder="name@domain.com" /> @@ -24,15 +25,17 @@ </fieldset> <input type="submit" value="Sign in" class="w-100 mb-2 btn btn-lg rounded-3 btn-primary" /> </form> - <!-- check if an error is returned in the model--> - <p th:if="${error}" th:text="${error}"> - </p> + <!-- Affichage des erreurs de connexion --> + <div th:if="${error}" class="alert alert-danger mt-3" role="alert"> + <p th:text="${error}"></p> + </div> </article> + <footer class="modal-body p-5 pt-0"> <hr class="my-4"> <a th:href="@{/companies/create}" class="btn w-100 mb-2 btn btn-lg rounded-3 btn-secondary">Sign up as company</a> - <a th:href="@{/candidates/create}" class="btn w-100 mb-2 btn btn-lg rounded-3 btn-secondary">Sign up as candidate</a> + <a th:href="@{/candidates/signup}" class="btn w-100 mb-2 btn btn-lg rounded-3 btn-secondary">Sign up as candidate</a> <small class="text-secondary">By clicking Sign up, you agree to the terms of use.</small> </footer> </div> diff --git a/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst b/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst index 270ec476364e0131b4b034d1c21555aa1792d2b1..35313550cab125c17caea98db584f277ab2490c3 100644 --- a/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst +++ b/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst @@ -1,43 +1,44 @@ fr\atlantique\imt\inf211\jobmngt\controller\CompanyController.class -fr\atlantique\imt\inf211\jobmngt\dao\ApplicationDao.class fr\atlantique\imt\inf211\jobmngt\dao\OfferMessageDao.class -fr\atlantique\imt\inf211\jobmngt\service\AppUserService.class fr\atlantique\imt\inf211\jobmngt\service\CompanyServiceImpl.class +fr\atlantique\imt\inf211\jobmngt\dao\QualificationLevelDao.class +fr\atlantique\imt\inf211\jobmngt\dao\CandidateDao.class +fr\atlantique\imt\inf211\jobmngt\controller\JobOfferController.class +fr\atlantique\imt\inf211\jobmngt\dao\JobOfferDao.class +fr\atlantique\imt\inf211\jobmngt\service\CandidateService.class +fr\atlantique\imt\inf211\jobmngt\dao\ApplicationMessageDao.class +fr\atlantique\imt\inf211\jobmngt\entity\Candidate.class +fr\atlantique\imt\inf211\jobmngt\controller\LoginController.class +fr\atlantique\imt\inf211\jobmngt\config\WebConfig.class +fr\atlantique\imt\inf211\jobmngt\service\JobOfferService.class +fr\atlantique\imt\inf211\jobmngt\controller\ApplicationController.class +fr\atlantique\imt\inf211\jobmngt\service\CandidateServiceImpl.class +fr\atlantique\imt\inf211\jobmngt\service\SectorServiceImpl.class +fr\atlantique\imt\inf211\jobmngt\controller\QualificationLevelController.class +fr\atlantique\imt\inf211\jobmngt\dao\ApplicationDao.class +fr\atlantique\imt\inf211\jobmngt\service\AppUserService.class fr\atlantique\imt\inf211\jobmngt\dao\AppUserDao.class fr\atlantique\imt\inf211\jobmngt\dao\CompanyDao.class -fr\atlantique\imt\inf211\jobmngt\dao\QualificationLevelDao.class fr\atlantique\imt\inf211\jobmngt\entity\QualificationLevel.class fr\atlantique\imt\inf211\jobmngt\service\JobOfferServiceImpl.class fr\atlantique\imt\inf211\jobmngt\controller\PagesController.class -fr\atlantique\imt\inf211\jobmngt\dao\CandidateDao.class fr\atlantique\imt\inf211\jobmngt\dao\SectorDao.class fr\atlantique\imt\inf211\jobmngt\entity\ApplicationMessage.class fr\atlantique\imt\inf211\jobmngt\entity\Application.class -fr\atlantique\imt\inf211\jobmngt\controller\JobOfferController.class fr\atlantique\imt\inf211\jobmngt\service\SectorService.class fr\atlantique\imt\inf211\jobmngt\entity\JobOffer.class -fr\atlantique\imt\inf211\jobmngt\dao\JobOfferDao.class -fr\atlantique\imt\inf211\jobmngt\service\CandidateService.class +fr\atlantique\imt\inf211\jobmngt\service\ApplicationServiceImpl.class fr\atlantique\imt\inf211\jobmngt\converter\QualificationLevelConverter.class fr\atlantique\imt\inf211\jobmngt\service\QualificationLevelService.class -fr\atlantique\imt\inf211\jobmngt\dao\ApplicationMessageDao.class fr\atlantique\imt\inf211\jobmngt\service\AppUserServiceImpl.class -fr\atlantique\imt\inf211\jobmngt\entity\Candidate.class fr\atlantique\imt\inf211\jobmngt\entity\Sector.class -fr\atlantique\imt\inf211\jobmngt\controller\LoginController.class fr\atlantique\imt\inf211\jobmngt\service\CompanyService.class -fr\atlantique\imt\inf211\jobmngt\config\WebConfig.class fr\atlantique\imt\inf211\jobmngt\entity\OfferMessage.class fr\atlantique\imt\inf211\jobmngt\entity\Company.class fr\atlantique\imt\inf211\jobmngt\service\QualificationLevelServiceImpl.class fr\atlantique\imt\inf211\jobmngt\JobmngtApplication.class fr\atlantique\imt\inf211\jobmngt\controller\SectorController.class fr\atlantique\imt\inf211\jobmngt\entity\AppUser.class -fr\atlantique\imt\inf211\jobmngt\service\JobOfferService.class -fr\atlantique\imt\inf211\jobmngt\controller\ApplicationController.class fr\atlantique\imt\inf211\jobmngt\service\ApplicationService.class -fr\atlantique\imt\inf211\jobmngt\service\CandidateServiceImpl.class fr\atlantique\imt\inf211\jobmngt\controller\CandidateController.class fr\atlantique\imt\inf211\jobmngt\converter\CompanyConverter.class -fr\atlantique\imt\inf211\jobmngt\service\SectorServiceImpl.class -fr\atlantique\imt\inf211\jobmngt\controller\QualificationLevelController.class diff --git a/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst b/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst index 4c0de8faaeb45ef4fdd6ff5ffafb826bbd6c9b63..6646ede2f30f239d1fc9b576e5a070bda455cf0f 100644 --- a/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst +++ b/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst @@ -1,43 +1,44 @@ -C:\Users\rania\Desktop\jobmngt\jobmngt\src\main\java\fr\atlantique\imt\inf211\jobmngt\JobmngtApplication.java -C:\Users\rania\Desktop\jobmngt\jobmngt\src\main\java\fr\atlantique\imt\inf211\jobmngt\service\CompanyServiceImpl.java -C:\Users\rania\Desktop\jobmngt\jobmngt\src\main\java\fr\atlantique\imt\inf211\jobmngt\service\JobOfferServiceImpl.java -C:\Users\rania\Desktop\jobmngt\jobmngt\src\main\java\fr\atlantique\imt\inf211\jobmngt\entity\OfferMessage.java -C:\Users\rania\Desktop\jobmngt\jobmngt\src\main\java\fr\atlantique\imt\inf211\jobmngt\entity\Company.java -C:\Users\rania\Desktop\jobmngt\jobmngt\src\main\java\fr\atlantique\imt\inf211\jobmngt\service\JobOfferService.java -C:\Users\rania\Desktop\jobmngt\jobmngt\src\main\java\fr\atlantique\imt\inf211\jobmngt\controller\CompanyController.java -C:\Users\rania\Desktop\jobmngt\jobmngt\src\main\java\fr\atlantique\imt\inf211\jobmngt\service\CandidateServiceImpl.java -C:\Users\rania\Desktop\jobmngt\jobmngt\src\main\java\fr\atlantique\imt\inf211\jobmngt\converter\QualificationLevelConverter.java -C:\Users\rania\Desktop\jobmngt\jobmngt\src\main\java\fr\atlantique\imt\inf211\jobmngt\converter\CompanyConverter.java -C:\Users\rania\Desktop\jobmngt\jobmngt\src\main\java\fr\atlantique\imt\inf211\jobmngt\entity\AppUser.java -C:\Users\rania\Desktop\jobmngt\jobmngt\src\main\java\fr\atlantique\imt\inf211\jobmngt\entity\Candidate.java -C:\Users\rania\Desktop\jobmngt\jobmngt\src\main\java\fr\atlantique\imt\inf211\jobmngt\entity\QualificationLevel.java -C:\Users\rania\Desktop\jobmngt\jobmngt\src\main\java\fr\atlantique\imt\inf211\jobmngt\service\CandidateService.java -C:\Users\rania\Desktop\jobmngt\jobmngt\src\main\java\fr\atlantique\imt\inf211\jobmngt\entity\Sector.java -C:\Users\rania\Desktop\jobmngt\jobmngt\src\main\java\fr\atlantique\imt\inf211\jobmngt\dao\CandidateDao.java -C:\Users\rania\Desktop\jobmngt\jobmngt\src\main\java\fr\atlantique\imt\inf211\jobmngt\config\WebConfig.java -C:\Users\rania\Desktop\jobmngt\jobmngt\src\main\java\fr\atlantique\imt\inf211\jobmngt\service\AppUserServiceImpl.java -C:\Users\rania\Desktop\jobmngt\jobmngt\src\main\java\fr\atlantique\imt\inf211\jobmngt\service\CompanyService.java -C:\Users\rania\Desktop\jobmngt\jobmngt\src\main\java\fr\atlantique\imt\inf211\jobmngt\dao\JobOfferDao.java -C:\Users\rania\Desktop\jobmngt\jobmngt\src\main\java\fr\atlantique\imt\inf211\jobmngt\dao\ApplicationMessageDao.java -C:\Users\rania\Desktop\jobmngt\jobmngt\src\main\java\fr\atlantique\imt\inf211\jobmngt\dao\OfferMessageDao.java -C:\Users\rania\Desktop\jobmngt\jobmngt\src\main\java\fr\atlantique\imt\inf211\jobmngt\service\SectorServiceImpl.java -C:\Users\rania\Desktop\jobmngt\jobmngt\src\main\java\fr\atlantique\imt\inf211\jobmngt\entity\JobOffer.java -C:\Users\rania\Desktop\jobmngt\jobmngt\src\main\java\fr\atlantique\imt\inf211\jobmngt\controller\SectorController.java -C:\Users\rania\Desktop\jobmngt\jobmngt\src\main\java\fr\atlantique\imt\inf211\jobmngt\dao\SectorDao.java -C:\Users\rania\Desktop\jobmngt\jobmngt\src\main\java\fr\atlantique\imt\inf211\jobmngt\dao\CompanyDao.java -C:\Users\rania\Desktop\jobmngt\jobmngt\src\main\java\fr\atlantique\imt\inf211\jobmngt\entity\ApplicationMessage.java -C:\Users\rania\Desktop\jobmngt\jobmngt\src\main\java\fr\atlantique\imt\inf211\jobmngt\service\AppUserService.java -C:\Users\rania\Desktop\jobmngt\jobmngt\src\main\java\fr\atlantique\imt\inf211\jobmngt\controller\QualificationLevelController.java -C:\Users\rania\Desktop\jobmngt\jobmngt\src\main\java\fr\atlantique\imt\inf211\jobmngt\controller\JobOfferController.java -C:\Users\rania\Desktop\jobmngt\jobmngt\src\main\java\fr\atlantique\imt\inf211\jobmngt\controller\LoginController.java -C:\Users\rania\Desktop\jobmngt\jobmngt\src\main\java\fr\atlantique\imt\inf211\jobmngt\controller\PagesController.java -C:\Users\rania\Desktop\jobmngt\jobmngt\src\main\java\fr\atlantique\imt\inf211\jobmngt\dao\QualificationLevelDao.java -C:\Users\rania\Desktop\jobmngt\jobmngt\src\main\java\fr\atlantique\imt\inf211\jobmngt\service\SectorService.java -C:\Users\rania\Desktop\jobmngt\jobmngt\src\main\java\fr\atlantique\imt\inf211\jobmngt\service\QualificationLevelService.java -C:\Users\rania\Desktop\jobmngt\jobmngt\src\main\java\fr\atlantique\imt\inf211\jobmngt\controller\CandidateController.java -C:\Users\rania\Desktop\jobmngt\jobmngt\src\main\java\fr\atlantique\imt\inf211\jobmngt\dao\AppUserDao.java -C:\Users\rania\Desktop\jobmngt\jobmngt\src\main\java\fr\atlantique\imt\inf211\jobmngt\service\ApplicationService.java -C:\Users\rania\Desktop\jobmngt\jobmngt\src\main\java\fr\atlantique\imt\inf211\jobmngt\controller\ApplicationController.java -C:\Users\rania\Desktop\jobmngt\jobmngt\src\main\java\fr\atlantique\imt\inf211\jobmngt\dao\ApplicationDao.java -C:\Users\rania\Desktop\jobmngt\jobmngt\src\main\java\fr\atlantique\imt\inf211\jobmngt\service\QualificationLevelServiceImpl.java -C:\Users\rania\Desktop\jobmngt\jobmngt\src\main\java\fr\atlantique\imt\inf211\jobmngt\entity\Application.java +C:\Users\LENOVO\Desktop\JobManagement-1\JobmngmntVersionAFP\src\main\java\fr\atlantique\imt\inf211\jobmngt\dao\OfferMessageDao.java +C:\Users\LENOVO\Desktop\JobManagement-1\JobmngmntVersionAFP\src\main\java\fr\atlantique\imt\inf211\jobmngt\entity\AppUser.java +C:\Users\LENOVO\Desktop\JobManagement-1\JobmngmntVersionAFP\src\main\java\fr\atlantique\imt\inf211\jobmngt\service\SectorServiceImpl.java +C:\Users\LENOVO\Desktop\JobManagement-1\JobmngmntVersionAFP\src\main\java\fr\atlantique\imt\inf211\jobmngt\service\AppUserServiceImpl.java +C:\Users\LENOVO\Desktop\JobManagement-1\JobmngmntVersionAFP\src\main\java\fr\atlantique\imt\inf211\jobmngt\service\ApplicationService.java +C:\Users\LENOVO\Desktop\JobManagement-1\JobmngmntVersionAFP\src\main\java\fr\atlantique\imt\inf211\jobmngt\entity\ApplicationMessage.java +C:\Users\LENOVO\Desktop\JobManagement-1\JobmngmntVersionAFP\src\main\java\fr\atlantique\imt\inf211\jobmngt\entity\Candidate.java +C:\Users\LENOVO\Desktop\JobManagement-1\JobmngmntVersionAFP\src\main\java\fr\atlantique\imt\inf211\jobmngt\controller\PagesController.java +C:\Users\LENOVO\Desktop\JobManagement-1\JobmngmntVersionAFP\src\main\java\fr\atlantique\imt\inf211\jobmngt\controller\JobOfferController.java +C:\Users\LENOVO\Desktop\JobManagement-1\JobmngmntVersionAFP\src\main\java\fr\atlantique\imt\inf211\jobmngt\entity\Company.java +C:\Users\LENOVO\Desktop\JobManagement-1\JobmngmntVersionAFP\src\main\java\fr\atlantique\imt\inf211\jobmngt\controller\CompanyController.java +C:\Users\LENOVO\Desktop\JobManagement-1\JobmngmntVersionAFP\src\main\java\fr\atlantique\imt\inf211\jobmngt\dao\ApplicationDao.java +C:\Users\LENOVO\Desktop\JobManagement-1\JobmngmntVersionAFP\src\main\java\fr\atlantique\imt\inf211\jobmngt\service\CandidateServiceImpl.java +C:\Users\LENOVO\Desktop\JobManagement-1\JobmngmntVersionAFP\src\main\java\fr\atlantique\imt\inf211\jobmngt\entity\Application.java +C:\Users\LENOVO\Desktop\JobManagement-1\JobmngmntVersionAFP\src\main\java\fr\atlantique\imt\inf211\jobmngt\controller\CandidateController.java +C:\Users\LENOVO\Desktop\JobManagement-1\JobmngmntVersionAFP\src\main\java\fr\atlantique\imt\inf211\jobmngt\controller\QualificationLevelController.java +C:\Users\LENOVO\Desktop\JobManagement-1\JobmngmntVersionAFP\src\main\java\fr\atlantique\imt\inf211\jobmngt\service\AppUserService.java +C:\Users\LENOVO\Desktop\JobManagement-1\JobmngmntVersionAFP\src\main\java\fr\atlantique\imt\inf211\jobmngt\service\QualificationLevelServiceImpl.java +C:\Users\LENOVO\Desktop\JobManagement-1\JobmngmntVersionAFP\src\main\java\fr\atlantique\imt\inf211\jobmngt\dao\QualificationLevelDao.java +C:\Users\LENOVO\Desktop\JobManagement-1\JobmngmntVersionAFP\src\main\java\fr\atlantique\imt\inf211\jobmngt\config\WebConfig.java +C:\Users\LENOVO\Desktop\JobManagement-1\JobmngmntVersionAFP\src\main\java\fr\atlantique\imt\inf211\jobmngt\entity\JobOffer.java +C:\Users\LENOVO\Desktop\JobManagement-1\JobmngmntVersionAFP\src\main\java\fr\atlantique\imt\inf211\jobmngt\service\ApplicationServiceImpl.java +C:\Users\LENOVO\Desktop\JobManagement-1\JobmngmntVersionAFP\src\main\java\fr\atlantique\imt\inf211\jobmngt\service\CompanyServiceImpl.java +C:\Users\LENOVO\Desktop\JobManagement-1\JobmngmntVersionAFP\src\main\java\fr\atlantique\imt\inf211\jobmngt\controller\ApplicationController.java +C:\Users\LENOVO\Desktop\JobManagement-1\JobmngmntVersionAFP\src\main\java\fr\atlantique\imt\inf211\jobmngt\service\SectorService.java +C:\Users\LENOVO\Desktop\JobManagement-1\JobmngmntVersionAFP\src\main\java\fr\atlantique\imt\inf211\jobmngt\service\JobOfferService.java +C:\Users\LENOVO\Desktop\JobManagement-1\JobmngmntVersionAFP\src\main\java\fr\atlantique\imt\inf211\jobmngt\service\JobOfferServiceImpl.java +C:\Users\LENOVO\Desktop\JobManagement-1\JobmngmntVersionAFP\src\main\java\fr\atlantique\imt\inf211\jobmngt\dao\JobOfferDao.java +C:\Users\LENOVO\Desktop\JobManagement-1\JobmngmntVersionAFP\src\main\java\fr\atlantique\imt\inf211\jobmngt\dao\CandidateDao.java +C:\Users\LENOVO\Desktop\JobManagement-1\JobmngmntVersionAFP\src\main\java\fr\atlantique\imt\inf211\jobmngt\service\CompanyService.java +C:\Users\LENOVO\Desktop\JobManagement-1\JobmngmntVersionAFP\src\main\java\fr\atlantique\imt\inf211\jobmngt\service\CandidateService.java +C:\Users\LENOVO\Desktop\JobManagement-1\JobmngmntVersionAFP\src\main\java\fr\atlantique\imt\inf211\jobmngt\service\QualificationLevelService.java +C:\Users\LENOVO\Desktop\JobManagement-1\JobmngmntVersionAFP\src\main\java\fr\atlantique\imt\inf211\jobmngt\converter\QualificationLevelConverter.java +C:\Users\LENOVO\Desktop\JobManagement-1\JobmngmntVersionAFP\src\main\java\fr\atlantique\imt\inf211\jobmngt\entity\Sector.java +C:\Users\LENOVO\Desktop\JobManagement-1\JobmngmntVersionAFP\src\main\java\fr\atlantique\imt\inf211\jobmngt\converter\CompanyConverter.java +C:\Users\LENOVO\Desktop\JobManagement-1\JobmngmntVersionAFP\src\main\java\fr\atlantique\imt\inf211\jobmngt\JobmngtApplication.java +C:\Users\LENOVO\Desktop\JobManagement-1\JobmngmntVersionAFP\src\main\java\fr\atlantique\imt\inf211\jobmngt\dao\ApplicationMessageDao.java +C:\Users\LENOVO\Desktop\JobManagement-1\JobmngmntVersionAFP\src\main\java\fr\atlantique\imt\inf211\jobmngt\dao\CompanyDao.java +C:\Users\LENOVO\Desktop\JobManagement-1\JobmngmntVersionAFP\src\main\java\fr\atlantique\imt\inf211\jobmngt\dao\SectorDao.java +C:\Users\LENOVO\Desktop\JobManagement-1\JobmngmntVersionAFP\src\main\java\fr\atlantique\imt\inf211\jobmngt\dao\AppUserDao.java +C:\Users\LENOVO\Desktop\JobManagement-1\JobmngmntVersionAFP\src\main\java\fr\atlantique\imt\inf211\jobmngt\entity\OfferMessage.java +C:\Users\LENOVO\Desktop\JobManagement-1\JobmngmntVersionAFP\src\main\java\fr\atlantique\imt\inf211\jobmngt\entity\QualificationLevel.java +C:\Users\LENOVO\Desktop\JobManagement-1\JobmngmntVersionAFP\src\main\java\fr\atlantique\imt\inf211\jobmngt\controller\LoginController.java +C:\Users\LENOVO\Desktop\JobManagement-1\JobmngmntVersionAFP\src\main\java\fr\atlantique\imt\inf211\jobmngt\controller\SectorController.java diff --git a/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/createdFiles.lst b/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/createdFiles.lst deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/inputFiles.lst b/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/inputFiles.lst deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000