diff --git a/README.md b/README.md new file mode 100644 index 0000000000000000000000000000000000000000..10f9468f2116b4a9fd050741e822fdc2fbd7404b --- /dev/null +++ b/README.md @@ -0,0 +1,93 @@ +# JobMngmnt + + + +## Getting started + +To make it easy for you to get started with GitLab, here's a list of recommended next steps. + +Already a pro? Just edit this README.md and make it your own. Want to make it easy? [Use the template at the bottom](#editing-this-readme)! + +## Add your files + +- [ ] [Create](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#create-a-file) or [upload](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#upload-a-file) files +- [ ] [Add files using the command line](https://docs.gitlab.com/ee/gitlab-basics/add-file.html#add-a-file-using-the-command-line) or push an existing Git repository with the following command: + +``` +cd existing_repo +git remote add origin https://gitlab.imt-atlantique.fr/m23cheri/jobmngmnt.git +git branch -M main +git push -uf origin main +``` + +## Integrate with your tools + +- [ ] [Set up project integrations](https://gitlab.imt-atlantique.fr/m23cheri/jobmngmnt/-/settings/integrations) + +## Collaborate with your team + +- [ ] [Invite team members and collaborators](https://docs.gitlab.com/ee/user/project/members/) +- [ ] [Create a new merge request](https://docs.gitlab.com/ee/user/project/merge_requests/creating_merge_requests.html) +- [ ] [Automatically close issues from merge requests](https://docs.gitlab.com/ee/user/project/issues/managing_issues.html#closing-issues-automatically) +- [ ] [Enable merge request approvals](https://docs.gitlab.com/ee/user/project/merge_requests/approvals/) +- [ ] [Set auto-merge](https://docs.gitlab.com/ee/user/project/merge_requests/merge_when_pipeline_succeeds.html) + +## Test and Deploy + +Use the built-in continuous integration in GitLab. + +- [ ] [Get started with GitLab CI/CD](https://docs.gitlab.com/ee/ci/quick_start/) +- [ ] [Analyze your code for known vulnerabilities with Static Application Security Testing (SAST)](https://docs.gitlab.com/ee/user/application_security/sast/) +- [ ] [Deploy to Kubernetes, Amazon EC2, or Amazon ECS using Auto Deploy](https://docs.gitlab.com/ee/topics/autodevops/requirements.html) +- [ ] [Use pull-based deployments for improved Kubernetes management](https://docs.gitlab.com/ee/user/clusters/agent/) +- [ ] [Set up protected environments](https://docs.gitlab.com/ee/ci/environments/protected_environments.html) + +*** + +# Editing this README + +When you're ready to make this README your own, just edit this file and use the handy template below (or feel free to structure it however you want - this is just a starting point!). Thanks to [makeareadme.com](https://www.makeareadme.com/) for this template. + +## Suggestions for a good README + +Every project is different, so consider which of these sections apply to yours. The sections used in the template are suggestions for most open source projects. Also keep in mind that while a README can be too long and detailed, too long is better than too short. If you think your README is too long, consider utilizing another form of documentation rather than cutting out information. + +## Name +Choose a self-explaining name for your project. + +## Description +Let people know what your project can do specifically. Provide context and add a link to any reference visitors might be unfamiliar with. A list of Features or a Background subsection can also be added here. If there are alternatives to your project, this is a good place to list differentiating factors. + +## Badges +On some READMEs, you may see small images that convey metadata, such as whether or not all the tests are passing for the project. You can use Shields to add some to your README. Many services also have instructions for adding a badge. + +## Visuals +Depending on what you are making, it can be a good idea to include screenshots or even a video (you'll frequently see GIFs rather than actual videos). Tools like ttygif can help, but check out Asciinema for a more sophisticated method. + +## Installation +Within a particular ecosystem, there may be a common way of installing things, such as using Yarn, NuGet, or Homebrew. However, consider the possibility that whoever is reading your README is a novice and would like more guidance. Listing specific steps helps remove ambiguity and gets people to using your project as quickly as possible. If it only runs in a specific context like a particular programming language version or operating system or has dependencies that have to be installed manually, also add a Requirements subsection. + +## Usage +Use examples liberally, and show the expected output if you can. It's helpful to have inline the smallest example of usage that you can demonstrate, while providing links to more sophisticated examples if they are too long to reasonably include in the README. + +## Support +Tell people where they can go to for help. It can be any combination of an issue tracker, a chat room, an email address, etc. + +## Roadmap +If you have ideas for releases in the future, it is a good idea to list them in the README. + +## Contributing +State if you are open to contributions and what your requirements are for accepting them. + +For people who want to make changes to your project, it's helpful to have some documentation on how to get started. Perhaps there is a script that they should run or some environment variables that they need to set. Make these steps explicit. These instructions could also be useful to your future self. + +You can also document commands to lint the code or run tests. These steps help to ensure high code quality and reduce the likelihood that the changes inadvertently break something. Having instructions for running tests is especially helpful if it requires external setup, such as starting a Selenium server for testing in a browser. + +## Authors and acknowledgment +Show your appreciation to those who have contributed to the project. + +## License +For open source projects, say how it is licensed. + +## Project status +If you have run out of energy or time for your project, put a note at the top of the README saying that development has slowed down or stopped completely. Someone may choose to fork your project or volunteer to step in as a maintainer or owner, allowing your project to keep going. You can also make an explicit request for maintainers. diff --git a/pom.xml b/pom.xml index 19b54589af834b2491e499d5cbb7289bbf56427d..696bc1121d19b9221ac16505b7b37ac56657c8b0 100644 --- a/pom.xml +++ b/pom.xml @@ -30,6 +30,7 @@ <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> + <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> diff --git a/src/main/java/fr/atlantique/imt/inf211/jobmngt/config/WebConfig.java b/src/main/java/fr/atlantique/imt/inf211/jobmngt/config/WebConfig.java new file mode 100644 index 0000000000000000000000000000000000000000..dd15dddd98e8433720b0f57a99ff5918451ab51e --- /dev/null +++ b/src/main/java/fr/atlantique/imt/inf211/jobmngt/config/WebConfig.java @@ -0,0 +1,22 @@ +package fr.atlantique.imt.inf211.jobmngt.config; + +import org.springframework.context.annotation.Configuration; +import org.springframework.format.FormatterRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +import fr.atlantique.imt.inf211.jobmngt.converter.QualificationLevelConverter; + +@Configuration +public class WebConfig implements WebMvcConfigurer { + + private final QualificationLevelConverter qualificationLevelConverter; + + public WebConfig(QualificationLevelConverter qualificationLevelConverter) { + this.qualificationLevelConverter = qualificationLevelConverter; + } + + @Override + public void addFormatters(FormatterRegistry registry) { + registry.addConverter(qualificationLevelConverter); + } +} 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 new file mode 100644 index 0000000000000000000000000000000000000000..8ff51acdd8059b2244ae277e03f272d4278a41e7 --- /dev/null +++ b/src/main/java/fr/atlantique/imt/inf211/jobmngt/controller/CompanyController.java @@ -0,0 +1,125 @@ +package fr.atlantique.imt.inf211.jobmngt.controller; + +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.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.service.CompanyService; + +@Controller +public class CompanyController { + + @Autowired + private CompanyService companyService; + + public CompanyController(CompanyService companyService) { + this.companyService = companyService; + } + + // Affiche le formulaire d'inscription + @GetMapping("/companies/create") + public String showCreateForm(Model model) { + 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) { + model.addAttribute("companies", companyService.getAllCompanies()); + return "company/companyList"; + } + + // Affiche les détails d'une entreprise + @GetMapping("/companies/view/{id}") + public String viewCompany(@PathVariable("id") int id, Model model, RedirectAttributes redirectAttributes) { + Optional<Company> companyOpt = companyService.findById(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"; + } + } + + // Enregistre une entreprise avec vérification des doublons et message de succès + @PostMapping("/companies/create") + public String registerCompany(Company company, RedirectAttributes redirectAttributes, Model model) { + Optional<Company> existingCompany = companyService.findByMail(company.getMail()); + + if (existingCompany.isPresent()) { + model.addAttribute("errorMessage", "❌ Une entreprise avec cet e-mail existe déjà !"); + model.addAttribute("company", company); + return "company/companyForm"; // 🔹 Rester sur le formulaire en cas d'erreur + } + + try { + companyService.saveCompany(company); + redirectAttributes.addFlashAttribute("successMessage", "✅ L'entreprise a été ajoutée avec succès !"); + return "redirect:/companies"; + } 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 + } + } + + // Affiche le formulaire de modification d'une entreprise + @GetMapping("/companies/{id}/edit") + public String showEditForm(@PathVariable("id") int id, Model model, RedirectAttributes redirectAttributes) { + Optional<Company> companyOpt = companyService.findById(id); + + if (companyOpt.isPresent()) { + model.addAttribute("company", companyOpt.get()); + return "company/companyEdit"; + } else { + redirectAttributes.addFlashAttribute("errorMessage", "❌ L'entreprise avec ID " + id + " n'existe pas !"); + return "redirect:/companies"; + } + } + + // Met à jour les informations d'une entreprise avec message de succès + @PostMapping("/companies/update") + 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(); + } catch (Exception e) { + redirectAttributes.addFlashAttribute("errorMessage", "❌ Erreur lors de la mise à jour !"); + return "redirect:/companies/" + company.getId() + "/edit"; + } + } + + // Supprime une entreprise + @GetMapping("/companies/delete/{id}") + public String deleteCompany(@PathVariable("id") int id, RedirectAttributes redirectAttributes) { + try { + companyService.deleteCompany(id); + redirectAttributes.addFlashAttribute("successMessage", "✅ Entreprise supprimée avec succès !"); + } catch (Exception e) { + redirectAttributes.addFlashAttribute("errorMessage", "❌ Erreur lors de la suppression !"); + } + return "redirect:/companies"; + } +} + + + + + + + + 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 new file mode 100644 index 0000000000000000000000000000000000000000..984da34404e631795bfc17f761f2baa8c3d9283b --- /dev/null +++ b/src/main/java/fr/atlantique/imt/inf211/jobmngt/controller/JobOfferController.java @@ -0,0 +1,156 @@ +package fr.atlantique.imt.inf211.jobmngt.controller; + +import java.util.Date; +import java.util.List; +import java.util.Optional; +import java.util.Set; +import java.util.stream.Collectors; + +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.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.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; + +@Controller +@RequestMapping("/jobs") +public class JobOfferController { + + private final JobOfferService jobOfferService; + private final CompanyService companyService; + private final QualificationLevelService qualificationLevelService; + private final SectorService sectorService; + + + @Autowired + public JobOfferController(JobOfferService jobOfferService, + CompanyService companyService, + QualificationLevelService qualificationLevelService, + SectorService sectorService) { + this.jobOfferService = jobOfferService; + this.companyService = companyService; + this.qualificationLevelService = qualificationLevelService; + this.sectorService = sectorService; + } + + // Affiche la liste des offres d'emploi avec log + @GetMapping + 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") 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"; + } + } + + // Affiche le formulaire de création avec sélection des secteurs + @GetMapping("/create") + 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.getAllQualificationLevels()); + model.addAttribute("sectors", sectorService.listOfSectors()); + + return "jobOffer/jobOfferForm"; + } + + // 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"; + } +} + + +// 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()) { + 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 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 8c49ea086278f82b3a71eb52256d93c1ee74823b..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 @@ -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.QualificationLevelService; @@ -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/controller/TestApplicationDaoController.java b/src/main/java/fr/atlantique/imt/inf211/jobmngt/controller/TestApplicationDaoController.java deleted file mode 100644 index 8e9dfa8c42fc71c520130a0ec55bf7836be817a4..0000000000000000000000000000000000000000 --- a/src/main/java/fr/atlantique/imt/inf211/jobmngt/controller/TestApplicationDaoController.java +++ /dev/null @@ -1,125 +0,0 @@ -package fr.atlantique.imt.inf211.jobmngt.controller; - -import java.util.ArrayList; -import java.util.Date; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; -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.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; -import org.springframework.web.server.ResponseStatusException; - -import fr.atlantique.imt.inf211.jobmngt.dao.ApplicationDao; -import fr.atlantique.imt.inf211.jobmngt.dao.CandidateDao; -import fr.atlantique.imt.inf211.jobmngt.dao.QualificationLevelDao; -import fr.atlantique.imt.inf211.jobmngt.dao.SectorDao; -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; - -@RestController -@RequestMapping("/api/applications") -public class TestApplicationDaoController { - - @Autowired - private ApplicationDao applicationDao; - - @Autowired - private CandidateDao candidateDao; - - @Autowired - private QualificationLevelDao qualificationLevelDao; - - @Autowired - private SectorDao sectorDao; - - /** - * Récupérer toutes les candidatures existantes. - */ - @GetMapping("") -public List<Application> getAllApplications() { - return applicationDao.findAll("appdate", "ASC"); // Exemple de tri par date en ordre croissant -} - - - /** - * Créer une nouvelle candidature. - */ - @PostMapping(value = "", produces = MediaType.APPLICATION_JSON_VALUE) - public Application newApplication(@RequestBody Map<String, Object> payload) { - - // Vérifier la présence du candidat - int candidateId = (int) payload.get("candidateId"); - Candidate candidate = candidateDao.findById(candidateId); - if (candidate == null) { - throw new ResponseStatusException(HttpStatus.NOT_FOUND, "Candidat introuvable !"); - } - - // Vérifier le niveau de qualification - int qualificationLevelId = (int) payload.get("qualificationLevelId"); - QualificationLevel qualificationLevel = qualificationLevelDao.findById(qualificationLevelId); - if (qualificationLevel == null) { - throw new ResponseStatusException(HttpStatus.NOT_FOUND, "Niveau de qualification introuvable !"); - } - - // Création de l'application - Application application = new Application(); - application.setCv((String) payload.get("cv")); - application.setAppdate(new Date()); - application.setCandidate(candidate); - application.setQualificationlevel(qualificationLevel); - - // Gestion des secteurs (ajout de vérification) - Set<Sector> sectors = new HashSet<>(); - if (payload.containsKey("sectors")) { - for (Map<String, Object> sectorData : (List<Map<String, Object>>) payload.get("sectors")) { - int sectorId = (int) sectorData.get("id"); - Sector sector = sectorDao.findById(sectorId); - if (sector != null) { - sectors.add(sector); - } - } - } - application.setSectors(new ArrayList<>(sectors)); - - // Persistance de la candidature - applicationDao.persist(application); - return application; - } - - /** - * Récupérer les candidatures par secteur et niveau de qualification. - */ - @GetMapping("/sector/{sector}/qualification/{qualification}") - public List<Application> findBySectorAndQualification(@PathVariable String sector, @PathVariable String qualification) { - return applicationDao.findBySectorAndQualification(sector, qualification); - } -} - - - - - - - - - - - - - - - - - - diff --git a/src/main/java/fr/atlantique/imt/inf211/jobmngt/controller/TestCandidateDaoController.java b/src/main/java/fr/atlantique/imt/inf211/jobmngt/controller/TestCandidateDaoController.java deleted file mode 100644 index f090a6b06d791596c2b5a401b7258cd57415972f..0000000000000000000000000000000000000000 --- a/src/main/java/fr/atlantique/imt/inf211/jobmngt/controller/TestCandidateDaoController.java +++ /dev/null @@ -1,78 +0,0 @@ -package fr.atlantique.imt.inf211.jobmngt.controller; - -import java.util.List; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.MediaType; -import org.springframework.web.bind.annotation.DeleteMapping; -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.PutMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -import fr.atlantique.imt.inf211.jobmngt.dao.CandidateDao; -import fr.atlantique.imt.inf211.jobmngt.entity.Candidate; - -@RestController -@RequestMapping("/api/candidates") -public class TestCandidateDaoController { - - @Autowired - private CandidateDao candidateDao; - - /** - * Lister tous les candidats existants - */ - @GetMapping("") - public List<Candidate> all() { - return candidateDao.findAll(); - } - - /** - * Créer un nouveau candidat - */ - @PostMapping(value = "", produces = MediaType.APPLICATION_JSON_VALUE) - public Candidate newCandidate(@RequestBody Candidate candidate) { - candidateDao.persist(candidate); - return candidate; - } - - /** - * Récupérer les informations d'un candidat par son ID - */ - @GetMapping("/{id}") - public Candidate one(@PathVariable int id) { - return candidateDao.findById(id); - } - - /** - * Modifier les informations d'un candidat - */ - @PutMapping("/{id}") - public Candidate replaceCandidate(@RequestBody Candidate newCandidate, @PathVariable int id) { - Candidate candidate = candidateDao.findById(id); - if (candidate != null) { - candidate.setFirstname(newCandidate.getFirstname()); - candidate.setLastname(newCandidate.getLastname()); - candidate.setMail(newCandidate.getMail()); // Hérité de AppUser - candidate.setPassword(newCandidate.getPassword()); // Hérité de AppUser - candidate.setCity(newCandidate.getCity()); // Hérité de AppUser - return candidateDao.merge(candidate); - } - return null; - } - - /** - * Supprimer un candidat par ID - */ - @DeleteMapping("/{id}") - public void deleteCandidate(@PathVariable int id) { - Candidate candidate = candidateDao.findById(id); - if (candidate != null) { - candidateDao.remove(candidate); - } - } -} diff --git a/src/main/java/fr/atlantique/imt/inf211/jobmngt/controller/TestCompanyDaoController.java b/src/main/java/fr/atlantique/imt/inf211/jobmngt/controller/TestCompanyDaoController.java deleted file mode 100644 index 6d68b7ff625acb139d8e0f9c07bbd360e4d140ba..0000000000000000000000000000000000000000 --- a/src/main/java/fr/atlantique/imt/inf211/jobmngt/controller/TestCompanyDaoController.java +++ /dev/null @@ -1,92 +0,0 @@ -package fr.atlantique.imt.inf211.jobmngt.controller; - -import java.util.List; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; -import org.springframework.web.bind.annotation.DeleteMapping; -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.PutMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; -import org.springframework.web.server.ResponseStatusException; - -import fr.atlantique.imt.inf211.jobmngt.dao.CompanyDao; -import fr.atlantique.imt.inf211.jobmngt.entity.Company; - -@RestController -@RequestMapping("/api/companies") -public class TestCompanyDaoController { - - @Autowired - private CompanyDao companyDao; - - /** - * Lister toutes les entreprises existantes - */ - @GetMapping("") - public List<Company> all() { - return companyDao.findAll(); - } - - /** - * Créer une nouvelle entreprise - */ - @PostMapping(value = "", produces = MediaType.APPLICATION_JSON_VALUE) - public Company newCompany(@RequestBody Company company) { - if (company.getMail() == null || company.getPassword() == null || company.getCity() == null) { - throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "Les champs 'mail', 'password' et 'city' sont obligatoires !"); - } - companyDao.persist(company); - return company; - } - - /** - * Récupérer les informations d'une entreprise par ID - */ - @GetMapping("/{id}") - public Company one(@PathVariable int id) { - Company company = companyDao.findById(id); - if (company == null) { - throw new ResponseStatusException(HttpStatus.NOT_FOUND, "Entreprise non trouvée"); - } - return company; - } - - /** - * Modifier les informations d'une entreprise - */ - @PutMapping("/{id}") - public Company replaceCompany(@RequestBody Company newCompany, @PathVariable int id) { - Company company = companyDao.findById(id); - if (company != null) { - company.setDenomination(newCompany.getDenomination()); - company.setDescription(newCompany.getDescription()); - - // Hérité de AppUser - company.setMail(newCompany.getMail()); - company.setPassword(newCompany.getPassword()); - company.setCity(newCompany.getCity()); - - return companyDao.merge(company); - } - throw new ResponseStatusException(HttpStatus.NOT_FOUND, "Entreprise non trouvée"); - } - - /** - * Supprimer une entreprise par ID - */ - @DeleteMapping("/{id}") - public void deleteCompany(@PathVariable int id) { - Company company = companyDao.findById(id); - if (company != null) { - companyDao.remove(company); - } else { - throw new ResponseStatusException(HttpStatus.NOT_FOUND, "Entreprise non trouvée"); - } - } -} diff --git a/src/main/java/fr/atlantique/imt/inf211/jobmngt/controller/TestJobOfferDaoController.java b/src/main/java/fr/atlantique/imt/inf211/jobmngt/controller/TestJobOfferDaoController.java deleted file mode 100644 index 2a330d880a50fff74b6ec3d3ce6df049ee67c1d2..0000000000000000000000000000000000000000 --- a/src/main/java/fr/atlantique/imt/inf211/jobmngt/controller/TestJobOfferDaoController.java +++ /dev/null @@ -1,122 +0,0 @@ -package fr.atlantique.imt.inf211.jobmngt.controller; - -import java.util.Date; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; -import org.springframework.web.bind.annotation.DeleteMapping; -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.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; -import org.springframework.web.server.ResponseStatusException; - -import fr.atlantique.imt.inf211.jobmngt.dao.CompanyDao; -import fr.atlantique.imt.inf211.jobmngt.dao.JobOfferDao; -import fr.atlantique.imt.inf211.jobmngt.dao.QualificationLevelDao; -import fr.atlantique.imt.inf211.jobmngt.dao.SectorDao; -import fr.atlantique.imt.inf211.jobmngt.entity.Company; -import fr.atlantique.imt.inf211.jobmngt.entity.JobOffer; -import fr.atlantique.imt.inf211.jobmngt.entity.QualificationLevel; -import fr.atlantique.imt.inf211.jobmngt.entity.Sector; - -@RestController -@RequestMapping("/api/joboffers") -public class TestJobOfferDaoController { - - @Autowired - private JobOfferDao jobOfferDao; - - @Autowired - private CompanyDao companyDao; - - @Autowired - private QualificationLevelDao qualificationLevelDao; - - @Autowired - private SectorDao sectorDao; - - /** - * 🔍 Récupérer toutes les offres d'emploi. - */ - @GetMapping("") - public List<JobOffer> getAllJobOffers() { - return jobOfferDao.findAll(); - } - - - /** - * Récupérer les offres d'emploi en fonction d'un secteur et d'un niveau de qualification. -// */ - @GetMapping("/sector/{sector}/qualification/{qualification}") - public List<JobOffer> findBySectorAndQualification(@PathVariable String sector, @PathVariable String qualification) { - return jobOfferDao.findBySectorAndQualification(sector, qualification); - } - - /** - * 🔍 Récupérer une offre d'emploi par ID. - */ - @GetMapping("/{id}") - public JobOffer getJobOfferById(@PathVariable int id) { - JobOffer jobOffer = jobOfferDao.findById(id) - .orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND, "Offre d'emploi introuvable !")); - - if (jobOffer == null) { - throw new ResponseStatusException(HttpStatus.NOT_FOUND, "Offre d'emploi introuvable !"); - } - return jobOffer; - } - - /** - * ✨ Créer une nouvelle offre d'emploi. - */ - @PostMapping(value = "", produces = MediaType.APPLICATION_JSON_VALUE) - public JobOffer newJobOffer(@RequestBody Map<String, Object> payload) { - // Vérification et récupération des données - int companyId = (int) payload.get("companyId"); - Company company = companyDao.findById(companyId); - if (company == null) throw new ResponseStatusException(HttpStatus.NOT_FOUND, "Entreprise introuvable !"); - - int qualificationLevelId = (int) payload.get("qualificationLevelId"); - QualificationLevel qualificationLevel = qualificationLevelDao.findById(qualificationLevelId); - if (qualificationLevel == null) throw new ResponseStatusException(HttpStatus.NOT_FOUND, "Niveau de qualification introuvable !"); - - JobOffer jobOffer = new JobOffer(); - jobOffer.setCompany(company); - jobOffer.setQualificationLevel(qualificationLevel); - jobOffer.setTitle((String) payload.get("title")); - jobOffer.setTaskDescription((String) payload.get("taskDescription")); - jobOffer.setPublicationDate(new Date()); - - // Gestion des secteurs - Set<Sector> sectors = new HashSet<>(); - for (Map<String, Object> sectorData : (List<Map<String, Object>>) payload.get("sectors")) { - int sectorId = (int) sectorData.get("id"); - Sector sector = sectorDao.findById(sectorId); - if (sector == null) throw new ResponseStatusException(HttpStatus.NOT_FOUND, "Secteur introuvable avec ID: " + sectorId); - sectors.add(sector); - } - jobOffer.setSectors(sectors); - - return jobOfferDao.save(jobOffer); - } - - @DeleteMapping("/{id}") - public void deleteJobOffer(@PathVariable int id) { - if (!jobOfferDao.existsById(id)) { - throw new ResponseStatusException(HttpStatus.NOT_FOUND, "Offre d'emploi introuvable !"); - } - jobOfferDao.deleteById(id); - } - - -} - - diff --git a/src/main/java/fr/atlantique/imt/inf211/jobmngt/converter/CompanyConverter.java b/src/main/java/fr/atlantique/imt/inf211/jobmngt/converter/CompanyConverter.java new file mode 100644 index 0000000000000000000000000000000000000000..88bd2361a1b804d647913289cb96761e63ce02dc --- /dev/null +++ b/src/main/java/fr/atlantique/imt/inf211/jobmngt/converter/CompanyConverter.java @@ -0,0 +1,25 @@ +package fr.atlantique.imt.inf211.jobmngt.converter; + +import org.springframework.core.convert.converter.Converter; +import org.springframework.stereotype.Component; + +import fr.atlantique.imt.inf211.jobmngt.entity.Company; +import fr.atlantique.imt.inf211.jobmngt.service.CompanyService; + +@Component // Indique que c'est un bean Spring +public class CompanyConverter implements Converter<String, Company> { + + private final CompanyService companyService; + + public CompanyConverter(CompanyService companyService) { + this.companyService = companyService; + } + + @Override + public Company convert(String source) { + if (source == null || source.isEmpty()) { + return null; + } + return companyService.findById(Integer.parseInt(source)).orElse(null); + } +} 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 new file mode 100644 index 0000000000000000000000000000000000000000..e7d649ea0543556d83a1e9bf5f9750a1b4b5e938 --- /dev/null +++ b/src/main/java/fr/atlantique/imt/inf211/jobmngt/converter/QualificationLevelConverter.java @@ -0,0 +1,30 @@ +package fr.atlantique.imt.inf211.jobmngt.converter; + +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> { + + private final QualificationLevelService qualificationLevelService; + + public QualificationLevelConverter(QualificationLevelService qualificationLevelService) { + this.qualificationLevelService = qualificationLevelService; + } + + @Override + public QualificationLevel convert(String id) { + try { + 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; // 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 b379dde71fc7f27e0b4f6cea8ef1919325b71713..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,49 +42,16 @@ public class ApplicationDao { } @Transactional(readOnly = true) - public Application findById(int id) { - return 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); - return query.getResultList(); - } +public Optional<Application> findById(int id) { + return Optional.ofNullable(entityManager.find(Application.class, id)); +} - /** - * 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); - + 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(); } - @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(); -} } @@ -94,3 +61,4 @@ public List<Application> findAll() { + 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 249fdc801426b03593f93e97d0319d04730a467e..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/CompanyDao.java b/src/main/java/fr/atlantique/imt/inf211/jobmngt/dao/CompanyDao.java index 998fdcca51930e2299d6fbb524ebfc75274a522e..8fb1c6b30e4fb7803dcbc9f57ef400bbd7a51bee 100644 --- a/src/main/java/fr/atlantique/imt/inf211/jobmngt/dao/CompanyDao.java +++ b/src/main/java/fr/atlantique/imt/inf211/jobmngt/dao/CompanyDao.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; @@ -45,12 +46,86 @@ public class CompanyDao { return entityManager.createQuery("SELECT c FROM Company c", Company.class).getResultList(); } - @Transactional(readOnly = true) + public Optional<Company> findById(int id) { + return Optional.ofNullable(entityManager.find(Company.class, id)); + } + + @Transactional +public void remove(int id) { + Company company = findById(id).orElseThrow(() -> + new RuntimeException("Impossible de supprimer : l'entreprise avec ID " + id + " n'existe pas.")); + entityManager.remove(company); +} - public Company findById(int id) { - logger.log(Level.INFO, "Getting Company instance with id: " + id); - return entityManager.find(Company.class, id); + @Transactional(readOnly = true) + public Optional<Company> findByMail(String mail) { + List<Company> result = entityManager.createQuery( + "SELECT c FROM Company c WHERE c.mail = :mail", Company.class) + .setParameter("mail", mail) + .getResultList(); + return result.isEmpty() ? Optional.empty() : Optional.of(result.get(0)); + } + + public void save(Company company) { + // TODO Auto-generated method stub + throw new UnsupportedOperationException("Unimplemented method 'save'"); } } + + + + + + +// package fr.atlantique.imt.inf211.jobmngt.dao; + +// import java.util.List; +// import java.util.Optional; + +// import org.springframework.stereotype.Repository; +// import org.springframework.transaction.annotation.Transactional; + +// import fr.atlantique.imt.inf211.jobmngt.entity.Company; +// import jakarta.persistence.EntityManager; +// import jakarta.persistence.PersistenceContext; + +// @Repository +// public class CompanyDao { + +// @PersistenceContext +// private EntityManager entityManager; + +// @Transactional +// public Company save(Company company) { +// if (company.getId() == 0) { +// entityManager.persist(company); +// return company; +// } else { +// return entityManager.merge(company); +// } +// } + +// @Transactional +// public void remove(int id) { +// Company company = findById(id).orElseThrow(() -> +// new RuntimeException("Impossible de supprimer l'entreprise avec ID " + id)); +// entityManager.remove(company); +// } + +// @Transactional(readOnly = true) +// public List<Company> findAll() { +// return entityManager.createQuery("SELECT c FROM Company c", Company.class).getResultList(); +// } + +// @Transactional(readOnly = true) +// public Optional<Company> findById(int id) { +// return Optional.ofNullable(entityManager.find(Company.class, id)); +// } +// } + + + + + 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 f6f786a6eaf3d7dbf990cbd568546fe2a3430c42..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 @@ -39,9 +39,9 @@ public class SectorDao { } @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) @@ -51,13 +51,18 @@ 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 méthode : Récupérer les secteurs ayant un label donné. */ @@ -72,4 +77,18 @@ public class SectorDao { return query.getResultList(); } + + @Transactional(readOnly = true) +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(); +} + + } 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 2838c90dae951c415c8cfe1557df68780722efbb..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 @@ -4,8 +4,11 @@ import java.util.Date; import java.util.HashSet; import java.util.Set; +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; @@ -24,21 +27,21 @@ 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 int id; + 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 = false) + @JoinColumn(name = "qualiflevelid", nullable = true) // nullable = true pour éviter les erreurs si null private QualificationLevel qualificationLevel; @Column(name="title", nullable = false, length = 50) @@ -48,29 +51,33 @@ public class JobOffer implements java.io.Serializable { private String taskDescription; @Temporal(TemporalType.DATE) - @Column(name="publicationdate") + + @DateTimeFormat(pattern = "yyyy-MM-dd") + + + private Date publicationDate; - @ManyToMany(fetch = FetchType.LAZY) + @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(int 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(int 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; @@ -82,8 +89,8 @@ public class JobOffer implements java.io.Serializable { this.offerMessages = offerMessages; } - public int getId() { return id; } - public void setId(int 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; } @@ -106,5 +113,3 @@ public class JobOffer implements java.io.Serializable { 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 c498d20925155c6e2bb6528bedafa118fab1458d..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 @@ -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 c4d731fd20a2a9df596b05282fc6a7c27568f2f8..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 @@ -4,6 +4,7 @@ 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 java.util.List; import java.util.Optional; @@ -28,9 +29,18 @@ 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 @@ -39,15 +49,26 @@ public class CandidateServiceImpl implements CandidateService { } @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 new file mode 100644 index 0000000000000000000000000000000000000000..5dee21b833ee923beb3ab20c9be871ce0de353c8 --- /dev/null +++ b/src/main/java/fr/atlantique/imt/inf211/jobmngt/service/CompanyService.java @@ -0,0 +1,15 @@ +package fr.atlantique.imt.inf211.jobmngt.service; + +import java.util.List; +import java.util.Optional; + +import fr.atlantique.imt.inf211.jobmngt.entity.Company; + +public interface CompanyService { + void saveCompany(Company company); + List<Company> getAllCompanies(); + 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(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 new file mode 100644 index 0000000000000000000000000000000000000000..0857f4fbc1632e07c4b0108386de3e889ed894e9 --- /dev/null +++ b/src/main/java/fr/atlantique/imt/inf211/jobmngt/service/CompanyServiceImpl.java @@ -0,0 +1,60 @@ +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 fr.atlantique.imt.inf211.jobmngt.dao.CompanyDao; +import fr.atlantique.imt.inf211.jobmngt.entity.Company; + +@Service +public class CompanyServiceImpl implements CompanyService { + + @Autowired + private CompanyDao companyDao; + + @Override + public void saveCompany(Company company) { + companyDao.save(company); + } + + @Override + public List<Company> getAllCompanies() { + return companyDao.findAll(); + } + + @Override + public Optional findById(int id) { + return Optional.of(companyDao.findById(id)); + } + + @Override + public Optional<Company> findByMail(String mail) { + return companyDao.findByMail(mail); // Vérifier si l'entreprise existe déjà + } + + @Override + public void deleteCompany(int id) { + companyDao.remove(id); + } + + + + @Override +public void updateCompany(Company company) { + Optional<Company> existingCompanyOpt = companyDao.findById(company.getId()); + + if (existingCompanyOpt.isPresent()) { + Company existingCompany = existingCompanyOpt.get(); + existingCompany.setDenomination(company.getDenomination()); + existingCompany.setDescription(company.getDescription()); + existingCompany.setCity(company.getCity()); + companyDao.save(existingCompany); + } else { + throw new RuntimeException("L'entreprise avec ID " + company.getId() + " n'existe pas."); + } +} + +} diff --git a/src/main/java/fr/atlantique/imt/inf211/jobmngt/service/JobOfferService.java b/src/main/java/fr/atlantique/imt/inf211/jobmngt/service/JobOfferService.java new file mode 100644 index 0000000000000000000000000000000000000000..94003a3ca8927ddb6e22bb18510101ba64f1496c --- /dev/null +++ b/src/main/java/fr/atlantique/imt/inf211/jobmngt/service/JobOfferService.java @@ -0,0 +1,14 @@ +package fr.atlantique.imt.inf211.jobmngt.service; + +import java.util.List; +import java.util.Optional; + +import fr.atlantique.imt.inf211.jobmngt.entity.JobOffer; + +public interface JobOfferService { + List<JobOffer> getAllJobOffers(); + Optional<JobOffer> findById(int id); + void saveJobOffer(JobOffer jobOffer); + void updateJobOffer(JobOffer jobOffer); + void deleteJobOffer(int id); +} 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 new file mode 100644 index 0000000000000000000000000000000000000000..c67c11884ad3b07988feae3a1818f603908627d9 --- /dev/null +++ b/src/main/java/fr/atlantique/imt/inf211/jobmngt/service/JobOfferServiceImpl.java @@ -0,0 +1,58 @@ +package fr.atlantique.imt.inf211.jobmngt.service; + +import java.util.Date; +import java.util.List; +import java.util.Optional; + +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.JobOffer; + +@Service +public class JobOfferServiceImpl implements JobOfferService { + + private final JobOfferDao jobOfferDao; + + @Autowired + public JobOfferServiceImpl(JobOfferDao jobOfferDao) { + this.jobOfferDao = jobOfferDao; + } + + @Override + public List<JobOffer> getAllJobOffers() { + return jobOfferDao.findAll(); + } + + @Override + public Optional<JobOffer> findById(int id) { + return jobOfferDao.findById(id); + } + + @Override +public void saveJobOffer(JobOffer jobOffer) { + try { + if (jobOffer.getPublicationDate() == null) { + 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(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 0dfd60258fe7e0e492fd9b92c7215583547561a2..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 @@ -1,13 +1,11 @@ package fr.atlantique.imt.inf211.jobmngt.service; -import fr.atlantique.imt.inf211.jobmngt.entity.QualificationLevel; import java.util.List; +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 5f84949aa00184b3aba0dfeb8d6307e2b33260c0..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 @@ -1,26 +1,28 @@ package fr.atlantique.imt.inf211.jobmngt.service; -import fr.atlantique.imt.inf211.jobmngt.dao.QualificationLevelDao; -import fr.atlantique.imt.inf211.jobmngt.entity.QualificationLevel; +import java.util.List; +import java.util.Optional; -import org.springframework.stereotype.Component; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; -import java.util.List; +import fr.atlantique.imt.inf211.jobmngt.dao.QualificationLevelDao; +import fr.atlantique.imt.inf211.jobmngt.entity.QualificationLevel; -@Component +@Service public class QualificationLevelServiceImpl implements QualificationLevelService { @Autowired - QualificationLevelDao qualificationLevelDao; - - public List<QualificationLevel> listOfQualificationLevels() { - return qualificationLevelDao.findAll("id", "ASC"); - } + private QualificationLevelDao qualificationLevelDao; @Override - public long countQualificationLevel() { - return qualificationLevelDao.count(); + public List<QualificationLevel> getAllQualificationLevels() { + return qualificationLevelDao.findAll("id", "ASC"); // Ajout des paramètres manquants } + + @Override +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 3cb4dda6d34838c8e93d6ad42e84b2687c973d4e..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 @@ -1,13 +1,14 @@ package fr.atlantique.imt.inf211.jobmngt.service; -import fr.atlantique.imt.inf211.jobmngt.entity.Sector; import java.util.List; +import java.util.Optional; +import fr.atlantique.imt.inf211.jobmngt.entity.Sector; public interface SectorService { - - public List<Sector> listOfSectors(); - - public long countSectors(); - + 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 0529f408a6eb3397e69fdd399134c4cf9c35ab16..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 @@ -1,26 +1,44 @@ package fr.atlantique.imt.inf211.jobmngt.service; -import fr.atlantique.imt.inf211.jobmngt.dao.SectorDao; -import fr.atlantique.imt.inf211.jobmngt.entity.Sector; +import java.util.List; +import java.util.Optional; -import org.springframework.stereotype.Component; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; -import java.util.List; +import fr.atlantique.imt.inf211.jobmngt.dao.SectorDao; +import fr.atlantique.imt.inf211.jobmngt.entity.Sector; -@Component +@Service public class SectorServiceImpl implements SectorService { @Autowired SectorDao sectorDao; - public List<Sector> listOfSectors() { - return sectorDao.findAll("id", "ASC"); + @Override + public List<Sector> getAllSectors() { + return sectorDao.findAll(null, null); + } + + + public List<Sector> getSectorsByIds(List<Integer> sectorIds) { + return sectorDao.findAllByIds(sectorIds); } @Override - public long countSectors() { - return sectorDao.count(); + public Optional<Sector> findById(int id) { + return Optional.ofNullable(sectorDao.findById(id)); } + @Override + public Optional<Sector> findById(long id) { + // TODO Auto-generated method stub + throw new UnsupportedOperationException("Unimplemented method 'findById'"); + } + + @Override + 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 976facc3d19bacb9daedc4b7ce32585cbddc8fb5..36532658f8e5cad9ec42eda3dd4815dcf37db6ef 100644 --- a/src/main/resources/templates/baseTemplate/nav.html +++ b/src/main/resources/templates/baseTemplate/nav.html @@ -41,16 +41,12 @@ <a class="nav-link" th:href="@{/companies}">Companies</a> </li> <li class="nav-item"> - <a class="nav-link" href="/">Jobs</a> + <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> - </li> --> <li class="nav-item"> - <!-- Correction du lien vers la liste des candidatures --> <a class="nav-link" th:href="@{/applications/list}">Applications</a> </li> <li class="nav-item"> @@ -59,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/company/companyEdit.html b/src/main/resources/templates/company/companyEdit.html new file mode 100644 index 0000000000000000000000000000000000000000..82ea247f8dfe4eba39fd8cfb5b8d39b3175ab559 --- /dev/null +++ b/src/main/resources/templates/company/companyEdit.html @@ -0,0 +1,50 @@ +<!DOCTYPE html> +<html xmlns:th="http://www.thymeleaf.org" th:replace="~{/company/companyBase :: article(~{::article})}"> +<article> + <header> + <h2>Modifier l'entreprise</h2> + </header> + + <!-- Message d'erreur ou de succès --> + <div th:if="${successMessage}" class="alert alert-success"> + <strong>Succès :</strong> <span th:text="${successMessage}"></span> + </div> + + <div th:if="${errorMessage}" class="alert alert-danger"> + <strong>Erreur :</strong> <span th:text="${errorMessage}"></span> + </div> + + <form th:action="@{/companies/update}" method="post"> + <!-- ID (caché) --> + <input type="hidden" name="id" th:value="${company.id}" /> + + <!-- Email (readonly) --> + <fieldset class="mb-3"> + <label for="emailid" class="form-label">Email</label>: + <input type="email" id="emailid" class="form-control" name="mail" th:value="${company.mail}" readonly /> + </fieldset> + + <!-- Dénomination --> + <fieldset class="mb-3"> + <label for="nameid" class="form-label">Nom</label>: + <input type="text" id="nameid" class="form-control" name="denomination" th:value="${company.denomination}" required /> + </fieldset> + + <!-- Description --> + <fieldset class="mb-3"> + <label for="descid" class="form-label">Description</label>: + <input type="text" id="descid" class="form-control" name="description" th:value="${company.description}" required /> + </fieldset> + + <!-- Ville --> + <fieldset class="mb-3"> + <label for="cityid" class="form-label">Ville</label>: + <input type="text" id="cityid" class="form-control" name="city" th:value="${company.city}" required /> + </fieldset> + + <!-- Boutons --> + <button type="submit" class="btn btn-success">💾 Enregistrer</button> + <a th:href="@{/companies/view/{id}(id=${company.id})}" class="btn btn-danger">❌ Annuler</a> + </form> +</article> +</html> diff --git a/src/main/resources/templates/company/companyForm.html b/src/main/resources/templates/company/companyForm.html index 28880fcd98c82e3663144c28a9332222a99eca5a..654a4de0ed6f76e2051ee65b576482c59b13fc6b 100644 --- a/src/main/resources/templates/company/companyForm.html +++ b/src/main/resources/templates/company/companyForm.html @@ -58,4 +58,4 @@ </aside> </article> -</html> \ No newline at end of file +</html> diff --git a/src/main/resources/templates/company/companyList.html b/src/main/resources/templates/company/companyList.html index 9de4bcf77aa4afb0f2f85a3ea39b80d2fa2e815a..c82ab232e2a81cd1dcab7991e6fa39a697d32f1b 100644 --- a/src/main/resources/templates/company/companyList.html +++ b/src/main/resources/templates/company/companyList.html @@ -42,4 +42,4 @@ </footer> </article> -</html> \ No newline at end of file +</html> diff --git a/src/main/resources/templates/company/companyView.html b/src/main/resources/templates/company/companyView.html index 569220f9fb7065da3710399a2f2a7088d3cc099d..56783a8d3289f7951f601ce9e0238f6f79aeb734 100644 --- a/src/main/resources/templates/company/companyView.html +++ b/src/main/resources/templates/company/companyView.html @@ -55,4 +55,4 @@ </footer> </article> -</html> \ No newline at end of file +</html> diff --git a/src/main/resources/templates/index.html b/src/main/resources/templates/index.html index 93ed90ed16717d5477ac5a0ca4bbad3c725e89e9..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,7 +27,8 @@ </a> </article> - <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;"> @@ -46,8 +47,48 @@ </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> -</html> \ No newline at end of file +</html> diff --git a/src/main/resources/templates/jobOffer/jobOfferForm.html b/src/main/resources/templates/jobOffer/jobOfferForm.html new file mode 100644 index 0000000000000000000000000000000000000000..0ca49b5302a9d081cc88bbf048edc0db161e2a9e --- /dev/null +++ b/src/main/resources/templates/jobOffer/jobOfferForm.html @@ -0,0 +1,73 @@ +<!DOCTYPE html> +<html xmlns:th="http://www.thymeleaf.org"> +<head> + <title>Créer une offre d'emploi</title> + <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css"> +</head> +<body> + +<div class="container mt-4"> + <h2 class="text-center mb-4">Créer une offre d'emploi</h2> + + <form th:action="@{/jobs/save}" th:object="${jobOffer}" method="post"> + + <div class="mb-3"> + <label class="form-label">Titre :</label> + <input type="text" class="form-control" th:field="*{title}" required> + </div> + + <div class="mb-3"> + <label class="form-label">Description :</label> + <textarea class="form-control" rows="3" th:field="*{taskDescription}" required></textarea> + </div> + + <div class="mb-3"> + <label class="form-label">Date de publication :</label> + <input type="date" class="form-control" th:field="*{publicationDate}" required> + </div> + + <div class="mb-3"> + <label class="form-label">Entreprise :</label> + <select class="form-select" th:field="*{company}"> + <option value="">-- Sélectionner une entreprise --</option> + <option th:each="company : ${companies}" + th:value="${company.id}" + th:text="${company.denomination}" + th:selected="${company.id == jobOffer.company?.id}"></option> + </option> + </select> + + </div> + + <div class="mb-3"> + <label class="form-label">Niveau de qualification :</label> + <select class="form-select" th:field="*{qualificationLevel}"> + <option value="">Sélectionner un niveau de qualification</option> + <option th:each="level : ${qualificationLevels}" + th:value="${level.id}" + th:text="${level.label}" + th:selected="${level.id == jobOffer.qualificationLevel?.id}"> + </option> + </select> + + </div> + + <div class="mb-3"> + <label class="form-label">Secteurs d'activité :</label> + <select class="form-select" multiple th:name="sectorIds" required> + <option th:each="sector : ${sectors}" th:value="${sector.id}" th:text="${sector.label}"></option> + </select> + <small class="form-text text-muted">Maintenez "Ctrl" (ou "Cmd" sur Mac) pour sélectionner plusieurs secteurs.</small> + </div> + + <div class="text-center"> + <button type="submit" class="btn btn-success">Créer</button> + <a href="/jobs" class="btn btn-secondary">Retour</a> + </div> + + </form> +</div> + +<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script> +</body> +</html> diff --git a/src/main/resources/templates/jobOffer/jobOfferList.html b/src/main/resources/templates/jobOffer/jobOfferList.html new file mode 100644 index 0000000000000000000000000000000000000000..32242906d221c6211bc72f39b85bc3ca185ce344 --- /dev/null +++ b/src/main/resources/templates/jobOffer/jobOfferList.html @@ -0,0 +1,53 @@ +<!DOCTYPE html> +<html xmlns:th="http://www.thymeleaf.org"> +<head> + <title>Liste des Offres d'Emploi</title> + <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css"> +</head> +<body> + +<div class="container mt-4"> + <h2 class="text-center mb-4">Liste des Offres d'Emploi</h2> + + <div th:if="${successMessage}" class="alert alert-success"> + <p th:text="${successMessage}"></p> + </div> + <div th:if="${errorMessage}" class="alert alert-danger"> + <p th:text="${errorMessage}"></p> + </div> + + <table class="table table-striped table-bordered table-hover"> + <thead class="table-dark"> + <tr> + <th>ID</th> + <th>Titre</th> + <th>Entreprise</th> + <th>Secteurs</th> + <th>Actions</th> + </tr> + </thead> + <tbody> + <tr th:each="job : ${jobOffers}"> + <td th:text="${job.id}"></td> + <td th:text="${job.title}"></td> + <td th:text="${job.company.denomination}"></td> + <td> + <ul class="list-unstyled"> + <li th:each="sector : ${job.sectors}" th:text="${sector.label}"></li> + </ul> + </td> + <td> + <a th:href="@{'/jobs/view/' + ${job.id}}" class="btn btn-primary btn-sm">Voir</a> + <a th:href="@{'/jobs/' + ${job.id} + '/edit'}" class="btn btn-warning btn-sm">Modifier</a> + <a th:href="@{'/jobs/delete/' + ${job.id}}" class="btn btn-danger btn-sm">Supprimer</a> + </td> + </tr> + </tbody> + </table> + + <a href="/jobs/create" class="btn btn-success">Créer une nouvelle offre</a> +</div> + +<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script> +</body> +</html> diff --git a/src/main/resources/templates/jobOffer/jobOfferView.html b/src/main/resources/templates/jobOffer/jobOfferView.html new file mode 100644 index 0000000000000000000000000000000000000000..569e07007ec87f66d470379e306b7aaeda2d6525 --- /dev/null +++ b/src/main/resources/templates/jobOffer/jobOfferView.html @@ -0,0 +1,16 @@ +<!DOCTYPE html> +<html xmlns:th="http://www.thymeleaf.org"> +<head> + <title>Détails de l'offre</title> +</head> +<body> + <h2>Détails de l'offre</h2> + + <p><strong>ID :</strong> <span th:text="${jobOffer.id}"></span></p> + <p><strong>Titre :</strong> <span th:text="${jobOffer.title}"></span></p> + <p><strong>Description :</strong> <span th:text="${jobOffer.taskDescription}"></span></p> + <p><strong>Date :</strong> <span th:text="${jobOffer.publicationDate}"></span></p> + + <a href="/jobs">Retour</a> +</body> +</html> diff --git a/src/main/resources/templates/login.html b/src/main/resources/templates/login.html index 335c746bf8b76fbf1a14010841ec96998e705c7d..fbaa5e7d82095b9735edaf37a77c33436b1ff78e 100644 --- a/src/main/resources/templates/login.html +++ b/src/main/resources/templates/login.html @@ -5,24 +5,14 @@ <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 avec gestion de la session --> <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> </header> - <!-- Ajout de la gestion de session (affichage du mail de l'utilisateur s'il est connecté) --> - <div class="p-3 text-end"> - <span th:if="${session.user != null}"> - Welcome, <strong th:text="${session.user.mail}"></strong> - | <a th:href="@{/logout}" class="text-danger">Logout</a> - </span> - </div> - - <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" /> @@ -36,8 +26,10 @@ <input type="submit" value="Sign in" class="w-100 mb-2 btn btn-lg rounded-3 btn-primary" /> </form> - <!-- Message d'erreur si la connexion échoue --> - <p th:if="${error}" class="text-danger" 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"> diff --git a/target/classes/fr/atlantique/imt/inf211/jobmngt/config/WebConfig.class b/target/classes/fr/atlantique/imt/inf211/jobmngt/config/WebConfig.class new file mode 100644 index 0000000000000000000000000000000000000000..50d5c3e4b986652913b1a08586ee99d4b13ff9fb Binary files /dev/null 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 e436bc7dca043ba8fc1ff27d0b5c8bc5dc03f233..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 579957c653e3aa7eab385453e60b4041dde48fdd..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 new file mode 100644 index 0000000000000000000000000000000000000000..d1170384285d05a36a5981b3d1e94267dbdd2c68 Binary files /dev/null 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 new file mode 100644 index 0000000000000000000000000000000000000000..9a669740b433576d8024308d6bdad897138692e2 Binary files /dev/null and b/target/classes/fr/atlantique/imt/inf211/jobmngt/controller/JobOfferController.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 98cf3b272d023db55d6abbd8ff8b653c15631e83..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 f49fea088c92f617ccf9219442953394520f1905..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/controller/TestApplicationDaoController.class b/target/classes/fr/atlantique/imt/inf211/jobmngt/controller/TestApplicationDaoController.class deleted file mode 100644 index 55f4edd1d63c3a3fff908f8cdbd86d838c6098b3..0000000000000000000000000000000000000000 Binary files a/target/classes/fr/atlantique/imt/inf211/jobmngt/controller/TestApplicationDaoController.class and /dev/null differ diff --git a/target/classes/fr/atlantique/imt/inf211/jobmngt/controller/TestCandidateDaoController.class b/target/classes/fr/atlantique/imt/inf211/jobmngt/controller/TestCandidateDaoController.class deleted file mode 100644 index 4ca7e48df762c43255ef536566476274db75a8fb..0000000000000000000000000000000000000000 Binary files a/target/classes/fr/atlantique/imt/inf211/jobmngt/controller/TestCandidateDaoController.class and /dev/null differ diff --git a/target/classes/fr/atlantique/imt/inf211/jobmngt/controller/TestCompanyDaoController.class b/target/classes/fr/atlantique/imt/inf211/jobmngt/controller/TestCompanyDaoController.class deleted file mode 100644 index c1e513b3356c1f869aa61853b93a5dc1f6c0a331..0000000000000000000000000000000000000000 Binary files a/target/classes/fr/atlantique/imt/inf211/jobmngt/controller/TestCompanyDaoController.class and /dev/null differ diff --git a/target/classes/fr/atlantique/imt/inf211/jobmngt/controller/TestJobOfferDaoController.class b/target/classes/fr/atlantique/imt/inf211/jobmngt/controller/TestJobOfferDaoController.class deleted file mode 100644 index 0f7f231d71b0380957d6fa28e13e6cbbe1384fba..0000000000000000000000000000000000000000 Binary files a/target/classes/fr/atlantique/imt/inf211/jobmngt/controller/TestJobOfferDaoController.class and /dev/null 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 new file mode 100644 index 0000000000000000000000000000000000000000..63f6a7a42c4a8879294bfd611192931bdfdc3e42 Binary files /dev/null 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 new file mode 100644 index 0000000000000000000000000000000000000000..4e3504981e3513a7882bcb924f0fa95e66fd0fd2 Binary files /dev/null and b/target/classes/fr/atlantique/imt/inf211/jobmngt/converter/QualificationLevelConverter.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 c5c2e0b87938cb25bf348a5e06f72124db05bfdf..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/CandidateDao.class b/target/classes/fr/atlantique/imt/inf211/jobmngt/dao/CandidateDao.class index 26dd2232e49722cb6f51ad44c63f3570263091e9..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 e8cbbb27465da1b471bda57e2301e8e156758de8..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/SectorDao.class b/target/classes/fr/atlantique/imt/inf211/jobmngt/dao/SectorDao.class index 8fa07a9b22d47bb7aa418cb98955b2c104eef2f9..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/Application.class b/target/classes/fr/atlantique/imt/inf211/jobmngt/entity/Application.class index a1798658fa1cd8eafa8efd9d54d46ff187903e09..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/JobOffer.class b/target/classes/fr/atlantique/imt/inf211/jobmngt/entity/JobOffer.class index 87b903d8c428748e32760c95c83768ab3ae17cdf..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/service/ApplicationService.class b/target/classes/fr/atlantique/imt/inf211/jobmngt/service/ApplicationService.class index f6f19b603c614181203001c8186f8c52ebb5948d..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 bb1147bab3d2cc1892c35fc0c6dd92a77f103947..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 b8bf7550a4f4a126cfc33beb4f2ddd18b1404a4d..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 new file mode 100644 index 0000000000000000000000000000000000000000..531c366e00e39c8d642c1344b34582c97fe73e08 Binary files /dev/null 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 new file mode 100644 index 0000000000000000000000000000000000000000..7603576a2573c5fa12706c591dff3ff3da7d3ff9 Binary files /dev/null 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 new file mode 100644 index 0000000000000000000000000000000000000000..331abe9a8037f5ae8fb6f5bf213ae75d3cd11c95 Binary files /dev/null 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 new file mode 100644 index 0000000000000000000000000000000000000000..0e2b451e33427573d29944f7307137fa13bd7dc1 Binary files /dev/null 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 2c5ce98a7a693c293937f1c574f85fa442417283..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 c885e0a74bd1b5eaa3b07234d30f4578f8ad8550..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 257c96b1678e1acf90696b59b022e0fd6999d3c9..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 4d066b21b90cb81b0171f088ab548a005f29fb95..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 976facc3d19bacb9daedc4b7ce32585cbddc8fb5..36532658f8e5cad9ec42eda3dd4815dcf37db6ef 100644 --- a/target/classes/templates/baseTemplate/nav.html +++ b/target/classes/templates/baseTemplate/nav.html @@ -41,16 +41,12 @@ <a class="nav-link" th:href="@{/companies}">Companies</a> </li> <li class="nav-item"> - <a class="nav-link" href="/">Jobs</a> + <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> - </li> --> <li class="nav-item"> - <!-- Correction du lien vers la liste des candidatures --> <a class="nav-link" th:href="@{/applications/list}">Applications</a> </li> <li class="nav-item"> @@ -59,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/company/companyEdit.html b/target/classes/templates/company/companyEdit.html new file mode 100644 index 0000000000000000000000000000000000000000..82ea247f8dfe4eba39fd8cfb5b8d39b3175ab559 --- /dev/null +++ b/target/classes/templates/company/companyEdit.html @@ -0,0 +1,50 @@ +<!DOCTYPE html> +<html xmlns:th="http://www.thymeleaf.org" th:replace="~{/company/companyBase :: article(~{::article})}"> +<article> + <header> + <h2>Modifier l'entreprise</h2> + </header> + + <!-- Message d'erreur ou de succès --> + <div th:if="${successMessage}" class="alert alert-success"> + <strong>Succès :</strong> <span th:text="${successMessage}"></span> + </div> + + <div th:if="${errorMessage}" class="alert alert-danger"> + <strong>Erreur :</strong> <span th:text="${errorMessage}"></span> + </div> + + <form th:action="@{/companies/update}" method="post"> + <!-- ID (caché) --> + <input type="hidden" name="id" th:value="${company.id}" /> + + <!-- Email (readonly) --> + <fieldset class="mb-3"> + <label for="emailid" class="form-label">Email</label>: + <input type="email" id="emailid" class="form-control" name="mail" th:value="${company.mail}" readonly /> + </fieldset> + + <!-- Dénomination --> + <fieldset class="mb-3"> + <label for="nameid" class="form-label">Nom</label>: + <input type="text" id="nameid" class="form-control" name="denomination" th:value="${company.denomination}" required /> + </fieldset> + + <!-- Description --> + <fieldset class="mb-3"> + <label for="descid" class="form-label">Description</label>: + <input type="text" id="descid" class="form-control" name="description" th:value="${company.description}" required /> + </fieldset> + + <!-- Ville --> + <fieldset class="mb-3"> + <label for="cityid" class="form-label">Ville</label>: + <input type="text" id="cityid" class="form-control" name="city" th:value="${company.city}" required /> + </fieldset> + + <!-- Boutons --> + <button type="submit" class="btn btn-success">💾 Enregistrer</button> + <a th:href="@{/companies/view/{id}(id=${company.id})}" class="btn btn-danger">❌ Annuler</a> + </form> +</article> +</html> diff --git a/target/classes/templates/company/companyForm.html b/target/classes/templates/company/companyForm.html index 28880fcd98c82e3663144c28a9332222a99eca5a..654a4de0ed6f76e2051ee65b576482c59b13fc6b 100644 --- a/target/classes/templates/company/companyForm.html +++ b/target/classes/templates/company/companyForm.html @@ -58,4 +58,4 @@ </aside> </article> -</html> \ No newline at end of file +</html> diff --git a/target/classes/templates/company/companyList.html b/target/classes/templates/company/companyList.html index 9de4bcf77aa4afb0f2f85a3ea39b80d2fa2e815a..c82ab232e2a81cd1dcab7991e6fa39a697d32f1b 100644 --- a/target/classes/templates/company/companyList.html +++ b/target/classes/templates/company/companyList.html @@ -42,4 +42,4 @@ </footer> </article> -</html> \ No newline at end of file +</html> diff --git a/target/classes/templates/company/companyView.html b/target/classes/templates/company/companyView.html index 569220f9fb7065da3710399a2f2a7088d3cc099d..56783a8d3289f7951f601ce9e0238f6f79aeb734 100644 --- a/target/classes/templates/company/companyView.html +++ b/target/classes/templates/company/companyView.html @@ -55,4 +55,4 @@ </footer> </article> -</html> \ No newline at end of file +</html> diff --git a/target/classes/templates/index.html b/target/classes/templates/index.html index 93ed90ed16717d5477ac5a0ca4bbad3c725e89e9..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,7 +27,8 @@ </a> </article> - <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;"> @@ -46,8 +47,48 @@ </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> -</html> \ No newline at end of file +</html> diff --git a/target/classes/templates/jobOffer/jobOfferForm.html b/target/classes/templates/jobOffer/jobOfferForm.html new file mode 100644 index 0000000000000000000000000000000000000000..0ca49b5302a9d081cc88bbf048edc0db161e2a9e --- /dev/null +++ b/target/classes/templates/jobOffer/jobOfferForm.html @@ -0,0 +1,73 @@ +<!DOCTYPE html> +<html xmlns:th="http://www.thymeleaf.org"> +<head> + <title>Créer une offre d'emploi</title> + <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css"> +</head> +<body> + +<div class="container mt-4"> + <h2 class="text-center mb-4">Créer une offre d'emploi</h2> + + <form th:action="@{/jobs/save}" th:object="${jobOffer}" method="post"> + + <div class="mb-3"> + <label class="form-label">Titre :</label> + <input type="text" class="form-control" th:field="*{title}" required> + </div> + + <div class="mb-3"> + <label class="form-label">Description :</label> + <textarea class="form-control" rows="3" th:field="*{taskDescription}" required></textarea> + </div> + + <div class="mb-3"> + <label class="form-label">Date de publication :</label> + <input type="date" class="form-control" th:field="*{publicationDate}" required> + </div> + + <div class="mb-3"> + <label class="form-label">Entreprise :</label> + <select class="form-select" th:field="*{company}"> + <option value="">-- Sélectionner une entreprise --</option> + <option th:each="company : ${companies}" + th:value="${company.id}" + th:text="${company.denomination}" + th:selected="${company.id == jobOffer.company?.id}"></option> + </option> + </select> + + </div> + + <div class="mb-3"> + <label class="form-label">Niveau de qualification :</label> + <select class="form-select" th:field="*{qualificationLevel}"> + <option value="">Sélectionner un niveau de qualification</option> + <option th:each="level : ${qualificationLevels}" + th:value="${level.id}" + th:text="${level.label}" + th:selected="${level.id == jobOffer.qualificationLevel?.id}"> + </option> + </select> + + </div> + + <div class="mb-3"> + <label class="form-label">Secteurs d'activité :</label> + <select class="form-select" multiple th:name="sectorIds" required> + <option th:each="sector : ${sectors}" th:value="${sector.id}" th:text="${sector.label}"></option> + </select> + <small class="form-text text-muted">Maintenez "Ctrl" (ou "Cmd" sur Mac) pour sélectionner plusieurs secteurs.</small> + </div> + + <div class="text-center"> + <button type="submit" class="btn btn-success">Créer</button> + <a href="/jobs" class="btn btn-secondary">Retour</a> + </div> + + </form> +</div> + +<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script> +</body> +</html> diff --git a/target/classes/templates/jobOffer/jobOfferList.html b/target/classes/templates/jobOffer/jobOfferList.html new file mode 100644 index 0000000000000000000000000000000000000000..32242906d221c6211bc72f39b85bc3ca185ce344 --- /dev/null +++ b/target/classes/templates/jobOffer/jobOfferList.html @@ -0,0 +1,53 @@ +<!DOCTYPE html> +<html xmlns:th="http://www.thymeleaf.org"> +<head> + <title>Liste des Offres d'Emploi</title> + <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css"> +</head> +<body> + +<div class="container mt-4"> + <h2 class="text-center mb-4">Liste des Offres d'Emploi</h2> + + <div th:if="${successMessage}" class="alert alert-success"> + <p th:text="${successMessage}"></p> + </div> + <div th:if="${errorMessage}" class="alert alert-danger"> + <p th:text="${errorMessage}"></p> + </div> + + <table class="table table-striped table-bordered table-hover"> + <thead class="table-dark"> + <tr> + <th>ID</th> + <th>Titre</th> + <th>Entreprise</th> + <th>Secteurs</th> + <th>Actions</th> + </tr> + </thead> + <tbody> + <tr th:each="job : ${jobOffers}"> + <td th:text="${job.id}"></td> + <td th:text="${job.title}"></td> + <td th:text="${job.company.denomination}"></td> + <td> + <ul class="list-unstyled"> + <li th:each="sector : ${job.sectors}" th:text="${sector.label}"></li> + </ul> + </td> + <td> + <a th:href="@{'/jobs/view/' + ${job.id}}" class="btn btn-primary btn-sm">Voir</a> + <a th:href="@{'/jobs/' + ${job.id} + '/edit'}" class="btn btn-warning btn-sm">Modifier</a> + <a th:href="@{'/jobs/delete/' + ${job.id}}" class="btn btn-danger btn-sm">Supprimer</a> + </td> + </tr> + </tbody> + </table> + + <a href="/jobs/create" class="btn btn-success">Créer une nouvelle offre</a> +</div> + +<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script> +</body> +</html> diff --git a/target/classes/templates/jobOffer/jobOfferView.html b/target/classes/templates/jobOffer/jobOfferView.html new file mode 100644 index 0000000000000000000000000000000000000000..569e07007ec87f66d470379e306b7aaeda2d6525 --- /dev/null +++ b/target/classes/templates/jobOffer/jobOfferView.html @@ -0,0 +1,16 @@ +<!DOCTYPE html> +<html xmlns:th="http://www.thymeleaf.org"> +<head> + <title>Détails de l'offre</title> +</head> +<body> + <h2>Détails de l'offre</h2> + + <p><strong>ID :</strong> <span th:text="${jobOffer.id}"></span></p> + <p><strong>Titre :</strong> <span th:text="${jobOffer.title}"></span></p> + <p><strong>Description :</strong> <span th:text="${jobOffer.taskDescription}"></span></p> + <p><strong>Date :</strong> <span th:text="${jobOffer.publicationDate}"></span></p> + + <a href="/jobs">Retour</a> +</body> +</html> diff --git a/target/classes/templates/login.html b/target/classes/templates/login.html index 335c746bf8b76fbf1a14010841ec96998e705c7d..fbaa5e7d82095b9735edaf37a77c33436b1ff78e 100644 --- a/target/classes/templates/login.html +++ b/target/classes/templates/login.html @@ -5,24 +5,14 @@ <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 avec gestion de la session --> <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> </header> - <!-- Ajout de la gestion de session (affichage du mail de l'utilisateur s'il est connecté) --> - <div class="p-3 text-end"> - <span th:if="${session.user != null}"> - Welcome, <strong th:text="${session.user.mail}"></strong> - | <a th:href="@{/logout}" class="text-danger">Logout</a> - </span> - </div> - - <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" /> @@ -36,8 +26,10 @@ <input type="submit" value="Sign in" class="w-100 mb-2 btn btn-lg rounded-3 btn-primary" /> </form> - <!-- Message d'erreur si la connexion échoue --> - <p th:if="${error}" class="text-danger" 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"> 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 cefd12dd95983569d114f861fd6c023ffd033df2..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,36 +1,44 @@ -fr\atlantique\imt\inf211\jobmngt\controller\TestCompanyDaoController.class -fr\atlantique\imt\inf211\jobmngt\dao\ApplicationDao.class -fr\atlantique\imt\inf211\jobmngt\controller\TestJobOfferDaoController.class +fr\atlantique\imt\inf211\jobmngt\controller\CompanyController.class fr\atlantique\imt\inf211\jobmngt\dao\OfferMessageDao.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\controller\TestCandidateDaoController.class fr\atlantique\imt\inf211\jobmngt\dao\SectorDao.class fr\atlantique\imt\inf211\jobmngt\entity\ApplicationMessage.class -fr\atlantique\imt\inf211\jobmngt\controller\TestApplicationDaoController.class fr\atlantique\imt\inf211\jobmngt\entity\Application.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\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\CandidateServiceImpl.class +fr\atlantique\imt\inf211\jobmngt\service\ApplicationService.class fr\atlantique\imt\inf211\jobmngt\controller\CandidateController.class -fr\atlantique\imt\inf211\jobmngt\service\SectorServiceImpl.class -fr\atlantique\imt\inf211\jobmngt\controller\QualificationLevelController.class +fr\atlantique\imt\inf211\jobmngt\converter\CompanyConverter.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 19cd16bfe2768ef781000793e8efc900f679b2a2..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,38 +1,44 @@ -C:\Users\LENOVO\INF210\Docker\DockerExo\Docker_environment\JobmngmntVersionAFP\src\main\java\fr\atlantique\imt\inf211\jobmngt\entity\AppUser.java -C:\Users\LENOVO\INF210\Docker\DockerExo\Docker_environment\JobmngmntVersionAFP\src\main\java\fr\atlantique\imt\inf211\jobmngt\entity\Sector.java -C:\Users\LENOVO\INF210\Docker\DockerExo\Docker_environment\JobmngmntVersionAFP\src\main\java\fr\atlantique\imt\inf211\jobmngt\service\SectorServiceImpl.java -C:\Users\LENOVO\INF210\Docker\DockerExo\Docker_environment\JobmngmntVersionAFP\src\main\java\fr\atlantique\imt\inf211\jobmngt\service\AppUserService.java -C:\Users\LENOVO\INF210\Docker\DockerExo\Docker_environment\JobmngmntVersionAFP\src\main\java\fr\atlantique\imt\inf211\jobmngt\controller\LoginController.java -C:\Users\LENOVO\INF210\Docker\DockerExo\Docker_environment\JobmngmntVersionAFP\src\main\java\fr\atlantique\imt\inf211\jobmngt\controller\TestJobOfferDaoController.java -C:\Users\LENOVO\INF210\Docker\DockerExo\Docker_environment\JobmngmntVersionAFP\src\main\java\fr\atlantique\imt\inf211\jobmngt\JobmngtApplication.java -C:\Users\LENOVO\INF210\Docker\DockerExo\Docker_environment\JobmngmntVersionAFP\src\main\java\fr\atlantique\imt\inf211\jobmngt\entity\ApplicationMessage.java -C:\Users\LENOVO\INF210\Docker\DockerExo\Docker_environment\JobmngmntVersionAFP\src\main\java\fr\atlantique\imt\inf211\jobmngt\dao\CandidateDao.java -C:\Users\LENOVO\INF210\Docker\DockerExo\Docker_environment\JobmngmntVersionAFP\src\main\java\fr\atlantique\imt\inf211\jobmngt\dao\OfferMessageDao.java -C:\Users\LENOVO\INF210\Docker\DockerExo\Docker_environment\JobmngmntVersionAFP\src\main\java\fr\atlantique\imt\inf211\jobmngt\controller\TestCandidateDaoController.java -C:\Users\LENOVO\INF210\Docker\DockerExo\Docker_environment\JobmngmntVersionAFP\src\main\java\fr\atlantique\imt\inf211\jobmngt\entity\Application.java -C:\Users\LENOVO\INF210\Docker\DockerExo\Docker_environment\JobmngmntVersionAFP\src\main\java\fr\atlantique\imt\inf211\jobmngt\entity\Company.java -C:\Users\LENOVO\INF210\Docker\DockerExo\Docker_environment\JobmngmntVersionAFP\src\main\java\fr\atlantique\imt\inf211\jobmngt\dao\SectorDao.java -C:\Users\LENOVO\INF210\Docker\DockerExo\Docker_environment\JobmngmntVersionAFP\src\main\java\fr\atlantique\imt\inf211\jobmngt\service\ApplicationService.java -C:\Users\LENOVO\INF210\Docker\DockerExo\Docker_environment\JobmngmntVersionAFP\src\main\java\fr\atlantique\imt\inf211\jobmngt\service\QualificationLevelService.java -C:\Users\LENOVO\INF210\Docker\DockerExo\Docker_environment\JobmngmntVersionAFP\src\main\java\fr\atlantique\imt\inf211\jobmngt\dao\QualificationLevelDao.java -C:\Users\LENOVO\INF210\Docker\DockerExo\Docker_environment\JobmngmntVersionAFP\src\main\java\fr\atlantique\imt\inf211\jobmngt\service\SectorService.java -C:\Users\LENOVO\INF210\Docker\DockerExo\Docker_environment\JobmngmntVersionAFP\src\main\java\fr\atlantique\imt\inf211\jobmngt\controller\TestApplicationDaoController.java -C:\Users\LENOVO\INF210\Docker\DockerExo\Docker_environment\JobmngmntVersionAFP\src\main\java\fr\atlantique\imt\inf211\jobmngt\controller\PagesController.java -C:\Users\LENOVO\INF210\Docker\DockerExo\Docker_environment\JobmngmntVersionAFP\src\main\java\fr\atlantique\imt\inf211\jobmngt\dao\ApplicationDao.java -C:\Users\LENOVO\INF210\Docker\DockerExo\Docker_environment\JobmngmntVersionAFP\src\main\java\fr\atlantique\imt\inf211\jobmngt\controller\QualificationLevelController.java -C:\Users\LENOVO\INF210\Docker\DockerExo\Docker_environment\JobmngmntVersionAFP\src\main\java\fr\atlantique\imt\inf211\jobmngt\controller\ApplicationController.java -C:\Users\LENOVO\INF210\Docker\DockerExo\Docker_environment\JobmngmntVersionAFP\src\main\java\fr\atlantique\imt\inf211\jobmngt\entity\Candidate.java -C:\Users\LENOVO\INF210\Docker\DockerExo\Docker_environment\JobmngmntVersionAFP\src\main\java\fr\atlantique\imt\inf211\jobmngt\controller\CandidateController.java -C:\Users\LENOVO\INF210\Docker\DockerExo\Docker_environment\JobmngmntVersionAFP\src\main\java\fr\atlantique\imt\inf211\jobmngt\controller\SectorController.java -C:\Users\LENOVO\INF210\Docker\DockerExo\Docker_environment\JobmngmntVersionAFP\src\main\java\fr\atlantique\imt\inf211\jobmngt\entity\JobOffer.java -C:\Users\LENOVO\INF210\Docker\DockerExo\Docker_environment\JobmngmntVersionAFP\src\main\java\fr\atlantique\imt\inf211\jobmngt\dao\ApplicationMessageDao.java -C:\Users\LENOVO\INF210\Docker\DockerExo\Docker_environment\JobmngmntVersionAFP\src\main\java\fr\atlantique\imt\inf211\jobmngt\dao\JobOfferDao.java -C:\Users\LENOVO\INF210\Docker\DockerExo\Docker_environment\JobmngmntVersionAFP\src\main\java\fr\atlantique\imt\inf211\jobmngt\dao\CompanyDao.java -C:\Users\LENOVO\INF210\Docker\DockerExo\Docker_environment\JobmngmntVersionAFP\src\main\java\fr\atlantique\imt\inf211\jobmngt\controller\TestCompanyDaoController.java -C:\Users\LENOVO\INF210\Docker\DockerExo\Docker_environment\JobmngmntVersionAFP\src\main\java\fr\atlantique\imt\inf211\jobmngt\dao\AppUserDao.java -C:\Users\LENOVO\INF210\Docker\DockerExo\Docker_environment\JobmngmntVersionAFP\src\main\java\fr\atlantique\imt\inf211\jobmngt\service\AppUserServiceImpl.java -C:\Users\LENOVO\INF210\Docker\DockerExo\Docker_environment\JobmngmntVersionAFP\src\main\java\fr\atlantique\imt\inf211\jobmngt\entity\OfferMessage.java -C:\Users\LENOVO\INF210\Docker\DockerExo\Docker_environment\JobmngmntVersionAFP\src\main\java\fr\atlantique\imt\inf211\jobmngt\entity\QualificationLevel.java -C:\Users\LENOVO\INF210\Docker\DockerExo\Docker_environment\JobmngmntVersionAFP\src\main\java\fr\atlantique\imt\inf211\jobmngt\service\CandidateService.java -C:\Users\LENOVO\INF210\Docker\DockerExo\Docker_environment\JobmngmntVersionAFP\src\main\java\fr\atlantique\imt\inf211\jobmngt\service\CandidateServiceImpl.java -C:\Users\LENOVO\INF210\Docker\DockerExo\Docker_environment\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\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