From 605957c9980634e222188283695533ce9342a59a Mon Sep 17 00:00:00 2001 From: Iva Georgieva <georgievaiva59@gmail.com> Date: Sun, 5 Jan 2025 16:58:25 +0100 Subject: [PATCH 1/7] Added StudentController, specifications --- .../web/controller/InternshipController.java | 2 + .../internships/service/ProfessorService.java | 11 +++ .../service/impl/ProfessorServiceImpl.java | 30 +++++++ .../FieldFilterSpecification.java | 71 +++++++++++++++ .../web/controller/StudentController.java | 90 +++++++++++++++++++ 5 files changed, 204 insertions(+) create mode 100644 backend/src/main/java/mk/ukim/finki/wp/internships/model/web/controller/InternshipController.java create mode 100644 backend/src/main/java/mk/ukim/finki/wp/internships/service/ProfessorService.java create mode 100644 backend/src/main/java/mk/ukim/finki/wp/internships/service/impl/ProfessorServiceImpl.java create mode 100644 backend/src/main/java/mk/ukim/finki/wp/internships/service/impl/specifications/FieldFilterSpecification.java create mode 100644 backend/src/main/java/mk/ukim/finki/wp/internships/web/controller/StudentController.java diff --git a/backend/src/main/java/mk/ukim/finki/wp/internships/model/web/controller/InternshipController.java b/backend/src/main/java/mk/ukim/finki/wp/internships/model/web/controller/InternshipController.java new file mode 100644 index 0000000..0bf56e5 --- /dev/null +++ b/backend/src/main/java/mk/ukim/finki/wp/internships/model/web/controller/InternshipController.java @@ -0,0 +1,2 @@ +@Controller +@RequestMapping diff --git a/backend/src/main/java/mk/ukim/finki/wp/internships/service/ProfessorService.java b/backend/src/main/java/mk/ukim/finki/wp/internships/service/ProfessorService.java new file mode 100644 index 0000000..8846289 --- /dev/null +++ b/backend/src/main/java/mk/ukim/finki/wp/internships/service/ProfessorService.java @@ -0,0 +1,11 @@ +package mk.ukim.finki.wp.internships.service; + +import mk.ukim.finki.wp.internships.model.Professor; +import mk.ukim.finki.wp.internships.model.Student; + +import java.util.List; + +public interface ProfessorService { + Professor getProfessorByUserId(String userId); + List<Professor> listAll(); +} diff --git a/backend/src/main/java/mk/ukim/finki/wp/internships/service/impl/ProfessorServiceImpl.java b/backend/src/main/java/mk/ukim/finki/wp/internships/service/impl/ProfessorServiceImpl.java new file mode 100644 index 0000000..f8d5128 --- /dev/null +++ b/backend/src/main/java/mk/ukim/finki/wp/internships/service/impl/ProfessorServiceImpl.java @@ -0,0 +1,30 @@ +package mk.ukim.finki.wp.internships.service.impl; + +import lombok.AllArgsConstructor; +import mk.ukim.finki.wp.internships.exception.EntityNotFoundException; +import mk.ukim.finki.wp.internships.model.Professor; +import mk.ukim.finki.wp.internships.model.User; +import mk.ukim.finki.wp.internships.repository.ProfessorRepository; +import mk.ukim.finki.wp.internships.repository.UserRepository; +import mk.ukim.finki.wp.internships.service.ProfessorService; +import org.springframework.stereotype.Service; + +import java.util.List; + +@Service +@AllArgsConstructor +public class ProfessorServiceImpl implements ProfessorService { + private final UserRepository userRepository; + private final ProfessorRepository professorRepository; + @Override + public Professor getProfessorByUserId(String userId) { + User user = userRepository.findById(userId).orElseThrow(() -> new EntityNotFoundException(userId)); + return professorRepository.findByEmail(user.getEmail()); + } + + @Override + public List<Professor> listAll() { + return professorRepository.findAll(); + } +} + diff --git a/backend/src/main/java/mk/ukim/finki/wp/internships/service/impl/specifications/FieldFilterSpecification.java b/backend/src/main/java/mk/ukim/finki/wp/internships/service/impl/specifications/FieldFilterSpecification.java new file mode 100644 index 0000000..df3738f --- /dev/null +++ b/backend/src/main/java/mk/ukim/finki/wp/internships/service/impl/specifications/FieldFilterSpecification.java @@ -0,0 +1,71 @@ +package mk.ukim.finki.wp.internships.service.impl.specifications; + +import jakarta.persistence.criteria.Path; +import jakarta.persistence.criteria.Root; +import org.springframework.data.jpa.domain.Specification; + + +public class FieldFilterSpecification { + + public static <T> Specification<T> filterEquals(Class<T> clazz, String field, String value) { + if (value == null || value.isEmpty()) { + return null; + } + return (root, query, criteriaBuilder) -> + criteriaBuilder.equal(fieldToPath(field, root), value); + } + + public static <T, V extends Comparable> Specification<T> greaterThen(Class<T> clazz, String field, V value) { + if (value == null) { + return null; + } + return (root, query, criteriaBuilder) -> criteriaBuilder.greaterThan(fieldToPath(field, root), value); + } + + public static <T, V> Specification<T> filterEqualsV(Class<T> clazz, String field, V value) { + if (value == null) { + return null; + } + return (root, query, criteriaBuilder) -> + criteriaBuilder.equal(fieldToPath(field, root), value); + } + + public static <T, V extends Comparable> Specification<T> greaterThan(Class<T> clazz, String field, V value) { + if (value == null) { + return null; + } + return (root, query, criteriaBuilder) -> + criteriaBuilder.greaterThan(fieldToPath(field, root), value); + } + + + public static <T> Specification<T> filterEquals(Class<T> clazz, String field, Long value) { + if (value == null) { + return null; + } + return (root, query, criteriaBuilder) -> + criteriaBuilder.equal(fieldToPath(field, root), value); + } + + + public static <T> Specification<T> filterContainsText(Class<T> clazz, String field, String value) { + if (value == null || value.isEmpty()) { + return null; + } + return (root, query, criteriaBuilder) -> + criteriaBuilder.like( + criteriaBuilder.lower(fieldToPath(field, root)), + "%" + value.toLowerCase() + "%" + ); + } + + private static <T> Path fieldToPath(String field, Root<T> root) { + String[] parts = field.split("\\."); + Path res = root; + for (String p : parts) { + res = res.get(p); + } + return res; + } +} + diff --git a/backend/src/main/java/mk/ukim/finki/wp/internships/web/controller/StudentController.java b/backend/src/main/java/mk/ukim/finki/wp/internships/web/controller/StudentController.java new file mode 100644 index 0000000..8a52e8b --- /dev/null +++ b/backend/src/main/java/mk/ukim/finki/wp/internships/web/controller/StudentController.java @@ -0,0 +1,90 @@ +package mk.ukim.finki.wp.internships.web.controller; +import mk.ukim.finki.wp.internships.model.Student; +import mk.ukim.finki.wp.internships.model.internships.Internship; +import mk.ukim.finki.wp.internships.model.internships.InternshipStatus; +import mk.ukim.finki.wp.internships.model.internships.InternshipWeek; +import mk.ukim.finki.wp.internships.repository.ProfessorRepository; +import mk.ukim.finki.wp.internships.service.InternshipService; +import mk.ukim.finki.wp.internships.service.InternshipWeekService; +import mk.ukim.finki.wp.internships.service.ProfessorService; +import mk.ukim.finki.wp.internships.service.StudentService; +import org.springframework.data.domain.Page; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.*; + +import java.util.Comparator; +import java.util.List; + +@Controller +@RequestMapping("/student-internships") +public class StudentController { + private final InternshipService internshipService; + private final ProfessorService professorService; + private final InternshipWeekService internshipWeekService; + private final StudentService studentService; + + public StudentController(InternshipService internshipService, ProfessorService professorService, InternshipWeekService internshipWeekService, StudentService studentService) { + this.internshipService = internshipService; + this.professorService = professorService; + this.internshipWeekService = internshipWeekService; + this.studentService = studentService; + } + + @GetMapping + public String showList(@RequestParam (required = false) InternshipStatus status, + @RequestParam (required = false) String professorName, + @RequestParam(defaultValue = "1") Integer pageNum, + @RequestParam(defaultValue = "10") Integer results, + Model model) { + + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + //String studentIndex = authentication.getName(); + String studentIndex = "213051"; + Student student = studentService.getStudentByIndex(studentIndex); + + Page<Internship> internshipsPage = internshipService.list(pageNum, results, status, professorName, student); + + model.addAttribute("statusSelected", status); + model.addAttribute("statuses", InternshipStatus.values()); + // model.addAttribute("professors", professorService.listAll()); + model.addAttribute("professorNameSelected", professorName); + model.addAttribute("student",student); + model.addAttribute("page", internshipsPage); + + return "student/index"; + } + + @GetMapping("/add") + public String showAdd(Model model) { + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + String studentIndex = authentication.getName(); + Student student = studentService.getStudentByIndex(studentIndex); + + model.addAttribute("student", student); + return "student/create"; + } + + + @GetMapping("/edit/{id}") + public String showEdit(@PathVariable Long id, Model model) { + Internship internship = this.internshipService.findById(id); + model.addAttribute("internshipWeeks",internship.getJournal()); + return "student/journal-form"; + } + + + @PostMapping("/delete/{id}") + public String delete(@PathVariable Long id) { + this.internshipService.delete(id); + return "redirect:/student-internships"; + } + + + + + +} + -- GitLab From e2804b6bb26b5613f872938108b6ac229a74bbfb Mon Sep 17 00:00:00 2001 From: Iva Georgieva <georgievaiva59@gmail.com> Date: Sun, 12 Jan 2025 15:10:25 +0100 Subject: [PATCH 2/7] Fixed details.html page --- .../model/internships/Internship.java | 10 + .../model/internships/InternshipWeek.java | 4 +- .../service/InternshipService.java | 5 + .../service/impl/InternshipServiceImpl.java | 40 +++ .../web/controller/StudentController.java | 82 +++++- .../resources/templates/student/create.html | 57 +++- .../resources/templates/student/details.html | 274 +++++------------- .../resources/templates/student/index.html | 228 ++++++--------- .../templates/student/journal-form.html | 2 +- 9 files changed, 337 insertions(+), 365 deletions(-) diff --git a/backend/src/main/java/mk/ukim/finki/wp/internships/model/internships/Internship.java b/backend/src/main/java/mk/ukim/finki/wp/internships/model/internships/Internship.java index 6331cef..972b027 100644 --- a/backend/src/main/java/mk/ukim/finki/wp/internships/model/internships/Internship.java +++ b/backend/src/main/java/mk/ukim/finki/wp/internships/model/internships/Internship.java @@ -8,6 +8,7 @@ import mk.ukim.finki.wp.internships.model.Company; import mk.ukim.finki.wp.internships.model.Professor; import mk.ukim.finki.wp.internships.model.Student; +import java.util.ArrayList; import java.util.List; @Entity @@ -43,4 +44,13 @@ public class Internship { public Internship(Student student) { this.student = student; } + + public Internship(Student student, Professor professor, Company company, String description) { + this.student = student; + this.coordinator = professor; + this.company = company; + this.status = InternshipStatus.SUBMITTED; + this.journal = new ArrayList<>(); + this.description = description; + } } diff --git a/backend/src/main/java/mk/ukim/finki/wp/internships/model/internships/InternshipWeek.java b/backend/src/main/java/mk/ukim/finki/wp/internships/model/internships/InternshipWeek.java index 9b3e921..a6406ac 100644 --- a/backend/src/main/java/mk/ukim/finki/wp/internships/model/internships/InternshipWeek.java +++ b/backend/src/main/java/mk/ukim/finki/wp/internships/model/internships/InternshipWeek.java @@ -14,7 +14,7 @@ import java.time.LocalDate; public class InternshipWeek { @Id - @Column(name = "id") + //@Column(name = "id") @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @@ -23,7 +23,7 @@ public class InternshipWeek { private LocalDate endDate; @ManyToOne - @JoinColumn(name="internship_id") + //@JoinColumn(name="internship_id") private Internship internship; private String description; diff --git a/backend/src/main/java/mk/ukim/finki/wp/internships/service/InternshipService.java b/backend/src/main/java/mk/ukim/finki/wp/internships/service/InternshipService.java index 8fc51f2..b194b5f 100644 --- a/backend/src/main/java/mk/ukim/finki/wp/internships/service/InternshipService.java +++ b/backend/src/main/java/mk/ukim/finki/wp/internships/service/InternshipService.java @@ -1,6 +1,7 @@ package mk.ukim.finki.wp.internships.service; import mk.ukim.finki.wp.internships.model.Professor; +import mk.ukim.finki.wp.internships.model.Student; import mk.ukim.finki.wp.internships.model.internships.Internship; import mk.ukim.finki.wp.internships.model.internships.InternshipStatus; import org.springframework.data.domain.Page; @@ -19,6 +20,10 @@ public interface InternshipService { Internship updateStatus(Long id, InternshipStatus status); + Page<Internship> list(int page, int size, InternshipStatus status, String professorName, Student student); + Page<Internship> list(int page, int size, Professor professor, InternshipStatus status, String studentIndex); Page<Internship> list(int page, int size, InternshipStatus status, String studentName, String companyId); + + void save(String studentIndex, String companyId, String description); } diff --git a/backend/src/main/java/mk/ukim/finki/wp/internships/service/impl/InternshipServiceImpl.java b/backend/src/main/java/mk/ukim/finki/wp/internships/service/impl/InternshipServiceImpl.java index 2833a59..082b720 100644 --- a/backend/src/main/java/mk/ukim/finki/wp/internships/service/impl/InternshipServiceImpl.java +++ b/backend/src/main/java/mk/ukim/finki/wp/internships/service/impl/InternshipServiceImpl.java @@ -1,11 +1,17 @@ package mk.ukim.finki.wp.internships.service.impl; import lombok.AllArgsConstructor; +import mk.ukim.finki.wp.internships.exception.CompanyNotFoundException; import mk.ukim.finki.wp.internships.exception.EntityNotFoundException; import mk.ukim.finki.wp.internships.exception.InternshipNotFoundException; +import mk.ukim.finki.wp.internships.model.Company; import mk.ukim.finki.wp.internships.model.Professor; +import mk.ukim.finki.wp.internships.model.Student; import mk.ukim.finki.wp.internships.model.internships.Internship; import mk.ukim.finki.wp.internships.model.internships.InternshipStatus; +import mk.ukim.finki.wp.internships.model.internships.InternshipWeek; +import mk.ukim.finki.wp.internships.repository.CompanyRepository; +import mk.ukim.finki.wp.internships.repository.ProfessorRepository; import mk.ukim.finki.wp.internships.repository.StudentRepository; import mk.ukim.finki.wp.internships.repository.internships.InternshipRepository; import mk.ukim.finki.wp.internships.repository.internships.InternshipWeekRepository; @@ -15,6 +21,7 @@ import org.springframework.data.domain.PageRequest; import org.springframework.data.jpa.domain.Specification; import org.springframework.stereotype.Service; +import java.util.ArrayList; import java.util.List; import static mk.ukim.finki.wp.internships.service.impl.specifications.FieldFilterSpecification.filterContainsText; @@ -27,6 +34,8 @@ public class InternshipServiceImpl implements InternshipService { private final InternshipRepository internshipRepository; private final StudentRepository studentRepository; private final InternshipWeekRepository weekRepository; + private final CompanyRepository companyRepository; + private final ProfessorRepository professorRepository; @Override public List<Internship> getAllByCoordinatorId(String coordinatorId) { @@ -58,6 +67,16 @@ public class InternshipServiceImpl implements InternshipService { return internshipRepository.save(internship); } + @Override + public Page<Internship> list(int page, int size, InternshipStatus status, String professorName, Student student) { + Specification<Internship> spec = where(filterEqualsV(Internship.class, "student", student)); + + spec = spec.and(filterEqualsV(Internship.class, "status", status)) + .and(filterContainsText(Internship.class, "coordinator.name", professorName)); + + return internshipRepository.findAll(spec, PageRequest.of(page - 1, size)); + } + @Override public Page<Internship> list(int page, int size, Professor professor, InternshipStatus status, String studentIndex) { Specification<Internship> spec = where(filterEqualsV(Internship.class, "coordinator", professor)); @@ -82,4 +101,25 @@ public class InternshipServiceImpl implements InternshipService { return internshipRepository.findAll(spec, PageRequest.of(page - 1, size)); } + @Override + public void save(String studentIndex, String companyId, String description) { + Company company = companyRepository.findById(companyId) + .orElseThrow(() -> new IllegalArgumentException("Invalid company ID.")); + Student student = studentRepository.findByIndex(studentIndex); + if (student == null) { + throw new IllegalArgumentException("Invalid student index."); + } + + // TODO: COORDINATOR LOGIC + + Professor coordinator = professorRepository.findByEmail("danco.davcev@finki.ukim.mk"); + if (coordinator == null) { + throw new IllegalArgumentException("Coordinator not found."); + } + + Internship internship = new Internship(student, coordinator, company, description); + internshipRepository.save(internship); + } + + } diff --git a/backend/src/main/java/mk/ukim/finki/wp/internships/web/controller/StudentController.java b/backend/src/main/java/mk/ukim/finki/wp/internships/web/controller/StudentController.java index 8a52e8b..d07381b 100644 --- a/backend/src/main/java/mk/ukim/finki/wp/internships/web/controller/StudentController.java +++ b/backend/src/main/java/mk/ukim/finki/wp/internships/web/controller/StudentController.java @@ -1,13 +1,11 @@ package mk.ukim.finki.wp.internships.web.controller; +import mk.ukim.finki.wp.internships.model.Professor; import mk.ukim.finki.wp.internships.model.Student; import mk.ukim.finki.wp.internships.model.internships.Internship; import mk.ukim.finki.wp.internships.model.internships.InternshipStatus; import mk.ukim.finki.wp.internships.model.internships.InternshipWeek; import mk.ukim.finki.wp.internships.repository.ProfessorRepository; -import mk.ukim.finki.wp.internships.service.InternshipService; -import mk.ukim.finki.wp.internships.service.InternshipWeekService; -import mk.ukim.finki.wp.internships.service.ProfessorService; -import mk.ukim.finki.wp.internships.service.StudentService; +import mk.ukim.finki.wp.internships.service.*; import org.springframework.data.domain.Page; import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; @@ -25,12 +23,15 @@ public class StudentController { private final ProfessorService professorService; private final InternshipWeekService internshipWeekService; private final StudentService studentService; + private final CompanyService companyService; - public StudentController(InternshipService internshipService, ProfessorService professorService, InternshipWeekService internshipWeekService, StudentService studentService) { + public StudentController(InternshipService internshipService, ProfessorService professorService, InternshipWeekService internshipWeekService, + StudentService studentService, CompanyService companyService) { this.internshipService = internshipService; this.professorService = professorService; this.internshipWeekService = internshipWeekService; this.studentService = studentService; + this.companyService = companyService; } @GetMapping @@ -49,29 +50,92 @@ public class StudentController { model.addAttribute("statusSelected", status); model.addAttribute("statuses", InternshipStatus.values()); - // model.addAttribute("professors", professorService.listAll()); - model.addAttribute("professorNameSelected", professorName); + model.addAttribute("professorName", professorName); model.addAttribute("student",student); model.addAttribute("page", internshipsPage); return "student/index"; } + @GetMapping("/{internshipId}") + public String showDetails (@PathVariable Long internshipId, + Model model) { + + // Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + //String studentIndex = authentication.getName(); + Student student = this.studentService.getStudentByIndex("213051"); + + Internship internship = this.internshipService.findById(internshipId); + Professor professor = internship.getCoordinator(); + List<InternshipWeek> journal = internship.getJournal(); + journal.sort(Comparator.comparing(InternshipWeek::getStartDate)); + + model.addAttribute("professor", professor); + model.addAttribute("internship", internship); + model.addAttribute("student", student); + model.addAttribute("journal", journal); + + return "student/details"; + } + + @PostMapping("/{internshipId}/save") + public String addWeekComment(@PathVariable Long internshipId, + @PathVariable Long weekId, + @RequestParam String coordinatorComment, + Model model) { + + + return "redirect:/student-internships/" + internshipId; + } + + @GetMapping("/add") public String showAdd(Model model) { Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); - String studentIndex = authentication.getName(); + //String studentIndex = authentication.getName(); + String studentIndex = "213051"; Student student = studentService.getStudentByIndex(studentIndex); model.addAttribute("student", student); + model.addAttribute("companies", companyService.getAllCompanies()); + return "student/create"; } + @PostMapping("/create") + public String create( + @RequestParam String companyId, + @RequestParam String description, + Model model) { + try { + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + //String studentIndex = authentication.getName(); + String studentIndex = "213051"; + this.internshipService.save(studentIndex,companyId,description); + return "redirect:/student-internships"; + } catch (Exception e) { + model.addAttribute("error", true); + return "student/create"; + } + } + @GetMapping("/edit/{id}") public String showEdit(@PathVariable Long id, Model model) { + // Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + //String studentIndex = authentication.getName(); + Student student = this.studentService.getStudentByIndex("213051"); + Internship internship = this.internshipService.findById(id); - model.addAttribute("internshipWeeks",internship.getJournal()); + Professor professor = internship.getCoordinator(); + List<InternshipWeek> journal = internship.getJournal(); + journal.sort(Comparator.comparing(InternshipWeek::getStartDate)); + + model.addAttribute("professor", professor); + model.addAttribute("internship", internship); + model.addAttribute("student", student); + model.addAttribute("journal", journal); + return "student/journal-form"; } diff --git a/backend/src/main/resources/templates/student/create.html b/backend/src/main/resources/templates/student/create.html index 7b79ad5..8682d73 100644 --- a/backend/src/main/resources/templates/student/create.html +++ b/backend/src/main/resources/templates/student/create.html @@ -1,19 +1,44 @@ -<form method="post" th:action="@{'/internships/create'}"> - <input name="studentId" type="hidden" th:value="${student.getIndex()}"> +<!DOCTYPE html> +<html xmlns:th="http://www.thymeleaf.org" + xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" + layout:decorate="~{layout}"> +<head> + <title>Додавање пракÑа</title> +</head> +<body> +<div class="container mt-4" layout:fragment="content"> + <h1 style="width: 100%; flex-basis: 12.5%; padding: 5px; font-weight: 100; font-size: 2.25rem; margin-bottom: 5px; margin-top: 5px;" + th:text="'Додавање пракÑа за Ñтудент ' + ${student.getName()}"></h1> - <div> - <label for="postingId">Internship Posting</label> - <br> - <select name="postingId" id="postingId"> - <option th:each="posting : ${postings}" - th:value="${posting.getId()}" - th:text="${posting.getPosition() + ' @ ' + posting.getCompany().getName()}"> - </select> - </div> + <form th:action="@{'/student-internships/create'}" + th:method="post" enctype="multipart/form-data" + class="my-4 form-control"> - <br> + <div class="form-group mb-3"> + <label for="companyId">Company:</label> + <select class="form-control" id="companyId" name="companyId" required> + <option value="" disabled selected></option> + <option th:each="company : ${companies}" + th:value="${company.id}" th:text="${company.name}"> + </option> + </select> + </div> + + <div class="form-group mb-3"> + <label for="description">Description:</label> + <input type="text" + id="description" + name="description" + class="form-control" + required> + </div> + + <button id="submit" type="submit" class="btn btn-primary">Save</button> + <button type="button" class="btn btn-secondary" onclick="window.history.back();">Cancel</button> + </form> + +</div> + +</body> +</html> - <div> - <button type="submit">Add Internship</button> - </div> -</form> diff --git a/backend/src/main/resources/templates/student/details.html b/backend/src/main/resources/templates/student/details.html index 8eeed46..669a87d 100644 --- a/backend/src/main/resources/templates/student/details.html +++ b/backend/src/main/resources/templates/student/details.html @@ -1,221 +1,105 @@ <!DOCTYPE html> +<html lang="en" + xmlns:th="http://www.thymeleaf.org" + xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" + xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity6" + layout:decorate="~{layout}"> <head> <link href="https://cdn.jsdelivr.net/npm/tailwindcss@2.2.19/dist/tailwind.min.css" rel="stylesheet"> -<style> - textarea { - resize: none; - background-color: #f8f8f8; - } - - textarea:focus{ - outline: #2A93D1 solid 2px; - - } - - .cardWeek:hover{ - outline: #2A93D1 solid 2px; - transition: outline-width 100ms; - } + <meta charset="UTF-8"> + <title>Дневник</title> + <style> + .cardWeek:hover { + outline: #1a3f8a solid 2px; + transition: outline-width 100ms; + } - .cardWeek:nth-child(4):nth-child(8):nth-child(12){ - margin-right: 0; - } + @media (min-width: 700px) { + .responsive-flex { + flex-direction: row; + } - .cardWeek{ - margin-right: 3%; - } + .responsive-basis { + flex-basis: 33.3333%; + } - input[type="date"] { - appearance: none; - -webkit-appearance: none; - -moz-appearance: none; - background-color: #ffffff; - border: 1px solid #dddddd; - border-radius: 0.375rem; - padding: 0.5rem 0.75rem; - font-size: 1rem; - color: #495057; - box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); - transition: border-color 0.3s, box-shadow 0.3s; - } + .fontsize { + font-size: 3.5rem; + } + } - /* Change border color and shadow on focus */ - input[type="date"]:focus { - border-color: #80bdff; - outline: none; - box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25); - } + @media (max-width: 1000px) { + .responsive-flex { + flex-direction: column; + } - /* Custom styles for the calendar icon */ - input[type="date"]::-webkit-calendar-picker-indicator { - color: #495057; - cursor: pointer; - } + .responsive-basis { + flex-basis: 25%; + } - /* Ensure input doesn't grow beyond its default size */ - input[type="date"] { - max-width: 100%; - box-sizing: border-box; - } - @media (min-width: 700px) { - .responsive-flex { - flex-direction: row; - } - .responsive-basis { - flex-basis: 33.3333%; + .fontsize { + font-size: 2rem; + } } - .fontsize { - font-size: 3.5rem; - } - } - @media (max-width: 1000px) { - .responsive-flex { - flex-direction: column; - } - .responsive-basis { - flex-basis: 25%; - } - .fontsize { - font-size: 2rem; - } - } -</style> + </style> </head> -<body> - -<div className="Navbar" - class="h-[7vh] py-2 flex justify-between px-2 lg:px-16 shadow-xl w-full overflow-hidden"> - <div class="flex flex-col justify-center"> - <a href="/internships/"> - <img style="height: 5vh;" th:src="@{/io.svg}"/> - </a> - </div> - <div class="flex"> - <div class="flex flex-col justify-center"> - <div class="flex rounded-xl border-2 border-black h-[6vh] text-[12px] md:text-md"> - <div class="flex p-1"> - <h1 class="font-bold mx-0 md:mx-2 w-fit my-auto" th:text="${student.getName() + ' ' + student.getLastName()}"></h1> - <h1 className="mx-0 md:mx-2 w-fit my-auto" th:text="${' (' + student.getIndex() + ')'}"></h1> - </div> - </div> - </div> - <div class="flex flex-col justify-center ml-2 md:ml-4" > - <img class="bg-red-600 h-[5.5vh] w-[5.5vh] rounded-lg " style="height: 5.5vh; width: 5.5vh; padding: 14px" th:src="@{/logout.svg}"/> - </div> +<body layout:fragment="content" class="bg-gray-100"> + +<div class="container mx-auto bg-white shadow-lg rounded-lg p-6" + th:with="InternshipStatus=${T(mk.ukim.finki.wp.internships.model.internships.InternshipStatus)}"> + <h1 style="width: 100%; text-align: center; font-weight: 100; font-size: 2.25rem; margin-bottom: 2rem; margin-top: 1rem;">Дневник</h1> + <h1 style="width: 100%; text-align: center; font-weight: 100; font-size: 1.25rem; margin-bottom: 1rem; margin-top: 1rem;" + th:text="'Студент: ' + ${student.getName()} + ' ' + ${student.getLastName()} + ' - ' + ${student.getIndex()}"></h1> + <h1 style="width: 100%; text-align: center; font-weight: 100; font-size: 1.25rem; margin-bottom: 1rem; margin-top: 1rem;" + th:text="'ОпиÑ: ' + ${internship.description}"></h1> + <h1 style="width: 100%; text-align: center; font-weight: 100; font-size: 1.25rem; margin-bottom: 1rem; margin-top: 1rem;" + th:text="'СтатуÑ: ' + ${internship.getStatus()}"></h1> + + <div th:if="${journal == null or journal.isEmpty()}"> + <p class="text-center text-lg text-gray-500">Студентот Ñеуште нема додадено белешка во дневникот</p> </div> -</div> -<div style="width: 100%; display: flex; height: max-content;" class="responsive-flex" th:with="InternshipStatus=${T(mk.ukim.finki.wp.internships.model.internships.InternshipStatus)}"> - <div style="flex: 1; display: flex; flex-direction: column; justify-content: flex-start; padding: 16px;box-shadow: 0px 4px 6px rgba(0, 0, 0, 0.1);" class="responsive-basis "> - <h1 style="width: 100%; flex-basis: 12.5%; padding: 5px; text-align: center; font-weight: 100; font-size: 2.25rem; margin-bottom: 5px; margin-top: 5px;">Дневник</h1> - - <div style="flex-basis: 66.6667%; width: 100%; padding: 16px; box-shadow: 0 10px 15px rgba(0, 0, 0, 0.1), 0 4px 6px rgba(0, 0, 0, 0.1); border-radius: 12px; display: flex; flex-direction: column; justify-content: space-between;"> - <form method="post" th:action="@{/internship-weeks/save}" > - <div> - <input type="hidden" name="id" th:value="${week?.getId()}" th:disabled="${internship.getStatus() == T(mk.ukim.finki.wp.internships.model.internships.InternshipStatus).DEPOSITED}"> - <input name="internshipId" type="hidden" th:value="${internship.getId()}" th:disabled="${internship.getStatus() == T(mk.ukim.finki.wp.internships.model.internships.InternshipStatus).DEPOSITED}"> - <input name="index" type="hidden" th:value="${student.getIndex()}" th:disabled="${internship.getStatus() == T(mk.ukim.finki.wp.internships.model.internships.InternshipStatus).DEPOSITED}"> - <h1 style="color: #212121; font-weight: bold; font-size: 1.5rem;" th:text="${week != null ? 'Ðедела' : 'No Week'}" th:disabled="${internship.getStatus() == T(mk.ukim.finki.wp.internships.model.internships.InternshipStatus).DEPOSITED}"></h1> - <h4 style="font-size: 0.875rem; color: gray;" th:text="${week != null ? week?.getStartDate()?.getDayOfMonth()+ '-' + week?.getEndDate()?.getDayOfMonth()+ ' ' + week?.getEndDate()?.getMonth(): ''}" th:disabled="${internship.getStatus() == T(mk.ukim.finki.wp.internships.model.internships.InternshipStatus).DEPOSITED}"></h4> - <label for="startDate" style="margin: 2px">Start Date:</label> - <input id="startDate" style="margin: 2px" type="date" name="startDate" th:value="${week?.getStartDate()}" th:disabled="${internship.getStatus() != T(mk.ukim.finki.wp.internships.model.internships.InternshipStatus).ONGOING}"> - <br> - <label for="startDate" style="margin: 2px">End Date:</label> - <input id="endDate" style="margin: 2px" type="date" name="endDate" th:value="${week?.getEndDate()}" th:disabled="${internship.getStatus() != T(mk.ukim.finki.wp.internships.model.internships.InternshipStatus).ONGOING}"> - </div> - <textarea placeholder="ВнеÑете дневник за неделата." name="description" style="height: 30vh; padding: 0.5rem; width: 100%; margin-top: 1rem; margin-bottom: 1rem; border-radius: 0.75rem;" th:text="${week != null ? week.getDescription() : ''}" th:disabled="${internship.getStatus() == T(mk.ukim.finki.wp.internships.model.internships.InternshipStatus).DEPOSITED}"></textarea> - <div style="color: white; display: flex; justify-content: center; align-content: center; margin: auto"> - - <button type="submit" style="background-color: #2A93D1; padding: 0.5rem 1rem; border-radius: 0.75rem;" th:disabled="${internship.getStatus() == T(mk.ukim.finki.wp.internships.model.internships.InternshipStatus).DEPOSITED}"> - Зачувај - </button> - - </div> - </form> - <form method="post" th:action="@{'/internship-weeks/' + ${week?.getId()} + '/delete/'+ ${student.getIndex()}}" th:if="${internship.getStatus() == InternshipStatus.ONGOING}"> - <div style="display: flex; justify-content: center; align-content: center; margin: 5px"> - <button type="submit" style="background-color: red; color: white; padding: 0.5rem 1rem; border-radius: 0.75rem; margin-right: 0.5rem; margin-left: 0.5rem" th:disabled="${internship.getStatus() == T(mk.ukim.finki.wp.internships.model.internships.InternshipStatus).DEPOSITED}"> - Избриши - </button> - </div> - </form> - </div> - <div style="display: flex; flex-direction: row" > - <div style="display: flex; justify-content: center; flex-direction: row"> - <h1 style="width: 100%; flex-basis: 12.5%; padding: 5px; text-align: center; font-weight: bold; font-size: 1rem; margin-bottom: 5px; margin-top: 5px;" >Supervisor:</h1> - - <h1 style="width: 100%; flex-basis: 12.5%; padding: 5px; text-align: center; font-weight: 100; font-size: 1rem; margin-bottom: 5px; margin-top: 5px;" th:text="${internship.getSupervisor() == null} ? 'TBD' : ${internship.getSupervisor().getFullName()}"></h1> - </div> - <div style="display: flex; justify-content: center; flex-direction: row"> - <h1 style="width: 100%; flex-basis: 12.5%; padding: 5px; text-align: center; font-weight: bold; font-size: 1rem; margin-bottom: 5px; margin-top: 5px;" >Profesor:</h1> - - <h1 style="width: 100%; flex-basis: 12.5%; padding: 5px; text-align: center; font-weight: 100; font-size: 1rem; margin-bottom: 5px; margin-top: 5px;" th:text="${internship.getCoordinator() == null} ? 'TBD' : ${internship.getCoordinator().getName()}"></h1> - </div> - </div> - - - <div style="display: flex; justify-content: center; flex-direction: row"> - <form method="post" th:if="${internship.getStatus() == InternshipStatus.ONGOING}" th:action="@{'/student/' + ${internship.getId()} + '/approve/'+${student.getIndex()}}"> - <input type="hidden" name="internshipId" th:value="${internship.getId()}"> - <input type="hidden" name="index" th:value="${student.getIndex()}"> - <button type="submit" style="background-color: #2A93D1; color: white; padding: 0.5rem 1rem; border-radius: 0.75rem;" th:disabled="${internship.getStatus() == T(mk.ukim.finki.wp.internships.model.internships.InternshipStatus).DEPOSITED}"> - Approve - </button> - </form> - <form method="post" th:if="${internship.getStatus() == InternshipStatus.PENDING_COMPANY_REVIEW}" th:action="@{'/student/' + ${internship.getId()} + '/revoke-approval/'+${student.getIndex()}}"> - <input type="hidden" name="internshipId" th:value="${internship.getId()}"> - <input type="hidden" name="index" th:value="${student.getIndex()}"> - <button type="submit" style="background-color: red; color: white; padding: 0.5rem 1rem; border-radius: 0.75rem; margin-right: 0.5rem; margin-left: 0.5rem" > - Revoke Approval - </button> - </form> - - <form th:if="${internship.getStatus() == InternshipStatus.ONGOING}" method="post" th:action="${'/internships/' + internship.getId() + '/delete'}"> - <button type="submit" style="background-color: red; color: white; padding: 0.5rem 1rem; border-radius: 0.75rem; margin-right: 0.5rem; margin-left: 0.5rem" th:disabled="${internship.getStatus() == T(mk.ukim.finki.wp.internships.model.internships.InternshipStatus).DEPOSITED}"> - Delete - </button> - </form> - </div> - - - </div> - <div style="width: 100%; height: max-content; max-width: none; flex-basis: 75%; margin-left: auto; margin-right: auto;" class="lg:w-fit md:basis-2/3 lg:basis-3/4 p-8 w-full lg:w-fit mx-auto grid grid-cols-1 lg:grid-cols-4 gap-4" > - <form th:each="week, iter : ${internship.getJournal()}" th:action="@{'/internship-weeks/' + ${week.getId()} + '/edit/'+ ${student.getIndex()}}" method="get" style="display: contents;"> - <div style="display: flex; flex-direction: column; box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.1); border-radius: 20px; padding: 16px; height: 30vh; min-height: auto;" class="lg:h-auto flex flex-col shadowCard rounded-xl p-4 shadow-xl h-[30vh] lg:h-auto cardWeek" onclick="this.closest('form').submit();" > + <div style="width: 100%; height: max-content; max-width: none; flex-basis: 75%; margin-left: auto; margin-right: auto;" class="lg:w-fit md:basis-2/3 lg:basis-3/4 p-8 w-full lg:w-fit mx-auto grid grid-cols-1 lg:grid-cols-2 gap-4"> + <div + th:each="week, iter : ${journal}" + style="display: flex; flex-direction: column; box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.1); border-radius: 20px; padding: 16px; min-height: auto;" + class="lg:h-auto flex flex-col shadowCard rounded-xl p-4 shadow-xl h-[30vh] lg:h-auto cardWeek"> <div style="display: flex; justify-content: space-between;" class="flex justify-between"> - <div th:style="${internship.getStatus() == T(mk.ukim.finki.wp.internships.model.internships.InternshipStatus).DEPOSITED} ? -'border-radius: 50%; background-color: #73E860; padding: 1rem; display: flex; justify-content: center; width: 3.5vw; height: 3.5vw;' : -'border-radius: 50%; background-color: #ccc; padding: 1rem; display: flex; justify-content: center; width: 3.5vw; height: 3.5vw;'" + <div style="border-radius: 50%; background-color: #1a3f8a; padding: 1rem; display: flex; justify-content: center; width: 1.5vw; height: 1.5vw;" class="rounded-full bg-gray p-4 flex justify-center"> <div style="display: flex; flex-direction: column; justify-content: center;" class="flex flex-col justify-center"> <h1 style="color: #f8f8f8; font-weight: bold; width: fit-content; height: fit-content;" th:text="${iter.index + 1}"></h1> </div> </div> <div style="display: flex; flex-direction: column; justify-content: center;"> - <h1 style="width: fit-content; font-weight: bold; color: #333;" th:text="${week.getStartDate().getDayOfMonth()+ '-' + week.getEndDate().getDayOfMonth()+ ' ' + week.getEndDate().getMonth()}"></h1> - </div> - </div> - <textarea style="border-radius: 0.75rem; margin-top: 1rem; height: 100%; padding: 0.5rem; font-size: 0.875rem;" disabled class="textarea" th:text="${week.getDescription()}"></textarea> - </div> - <button type="submit" style="display: none"></button> - </form> - <form th:action="@{/internship-weeks/create}" th:if="${internship.getStatus() == InternshipStatus.ONGOING}"> - - <div style="display: flex; flex-direction: column; box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.1); border-radius: 20px; padding: 16px; height: 30vh; min-height: auto;" class="lg:h-auto flex flex-col shadowCard rounded-xl p-4 shadow-xl lg:h-auto cardWeek" > - <div style="display: flex; justify-content: center; align-content: center; margin:auto" class="flex justify-between"> - <div style="border-radius: 50%; background-color: #2A93D1; padding: 1rem; display: flex; justify-content: center; width: 6vw; height: 6vw;" class="rounded-full bg-gray p-4 flex justify-center"> - <div style="display: flex; flex-direction: column; justify-content: center; text-align: center; " class="text-center" > - <input type="hidden" name="internshipId" th:value="${internship.getId()}"> - <input type="hidden" name="index" th:value="${student.getIndex()}"> - <button type="submit" style=" color: #f8f8f8; font-weight: bold; justify-content: center; margin-bottom: 7px; height: fit-content;" class="fontsize">+</button> - </div> + <h1 + style="width: fit-content; font-weight: bold; color: #333;" + th:text="${week.getStartDate().getDayOfMonth() + '-' + week.getEndDate().getDayOfMonth() + ' ' + week.getEndDate().getMonth()}"></h1> </div> </div> + <label for="description" style="color: #333; font-weight: bold; width: fit-content; height: fit-content; margin-top: 1rem;">Description</label> + <div + id="description" + style="border-radius: 0.75rem; margin-top: 0.5rem; height: 100%; padding: 0.5rem; font-size: 0.875rem; background-color: #e9f2f8" + class="textarea" + th:text="${week.getDescription()}"></div> + + <label for="companyComment" th:if="${week.getCompanyComment()!=null && !week.getCompanyComment().isEmpty()}" style="color: #333; font-weight: bold; width: fit-content; height: fit-content; margin-top: 1rem;">Company comment</label> + <div + id="companyComment" + style="border-radius: 0.75rem; margin-top: 0.5rem; height: 100%; padding: 0.5rem; font-size: 0.875rem; background-color: #f3f4f6" + th:if="${week.getCompanyComment()!=null && !week.getCompanyComment().isEmpty()}" + th:text="${week.getCompanyComment()}"></div> + + <label for="coordinatorComment" th:if="${week.getCoordinatorComment()!=null && !week.getCoordinatorComment().isEmpty()}" style="color: #333; font-weight: bold; width: fit-content; height: fit-content; margin-top: 1rem;">Coordinator comment</label> + <div + id="coordinatorComment" + style="border-radius: 0.75rem; margin-top: 0.5rem; height: 100%; padding: 0.5rem; font-size: 0.875rem; background-color: #f3f4f6" + th:if="${week.getCoordinatorComment()!=null && !week.getCoordinatorComment().isEmpty()}" + th:text="${week.getCoordinatorComment()}"></div> </div> - </form> - - </div> </div> -</body> \ No newline at end of file +</body> +</html> diff --git a/backend/src/main/resources/templates/student/index.html b/backend/src/main/resources/templates/student/index.html index d801dd6..2fab313 100644 --- a/backend/src/main/resources/templates/student/index.html +++ b/backend/src/main/resources/templates/student/index.html @@ -1,159 +1,103 @@ <!DOCTYPE html> +<html xmlns:th="http://www.thymeleaf.org" + xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" + xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity6" + layout:decorate="~{layout}"> <head> + <meta charset="UTF-8"> <link href="https://cdn.jsdelivr.net/npm/tailwindcss@2.2.19/dist/tailwind.min.css" rel="stylesheet"> - - <style> - - .bgLogoBlur { - backdrop-filter: blur(80px); - } - .shadowCard { - box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1), 0 1px 3px rgba(0, 0, 0, 0.08); - } - - - div.circles > img { - margin-right : 5.5%; - margin-bottom : 3%; - } - - div.circles > img:nth-child(6){ - margin-right: 0; - } - div.circles > img:nth-child(12){ - margin-right: 0; - } - @media (min-width: 700px) { - .responsive-flex { - flex-direction: row; - } - - } - @media (max-width: 700px) { - .responsive-flex { - flex-direction: column; - } - - } - </style> + <title>ПракÑи по Ñтудент</title> </head> -<body> -<div className="Navbar" - class="h-[7vh] py-2 flex justify-between px-2 lg:px-16 shadow-xl w-full overflow-hidden"> - <div class="flex flex-col justify-center"> - <a href="/internships/"> - <img style="height: 5vh;" th:src="@{/io.svg}"/> - </a> - </div> - <div class="flex"> - <div class="flex flex-col justify-center"> - <div class="flex rounded-xl border-2 border-black h-[6vh] text-[12px] md:text-md"> - <div class="flex p-1"> - <h1 class="font-bold mx-0 md:mx-2 w-fit my-auto" th:text="${student.getName() + ' ' + student.getLastName()}"></h1> - <h1 className="mx-0 md:mx-2 w-fit my-auto" th:text="${' (' + student.getIndex() + ')'}"></h1> - </div> - </div> +<body layout:fragment="content"> +<div class="container"> + <h1 style="width: 100%; flex-basis: 12.5%; padding: 5px; font-weight: 100; font-size: 2.25rem; margin-bottom: 5px; margin-top: 5px;" + th:text="'ПракÑи за Ñтудент ' + ${student.getName()}"></h1> + + <div class="row mb-2"> + <div class="col-2"> + <a class="btn btn-primary" + th:href="@{/student-internships/add}">Add Internship</a> </div> - <form method="post" th:action="@{'/logout'}"> - <div class="flex flex-col justify-center ml-2 md:ml-4" onclick="this.closest('form').submit();"> - <img class="bg-red-600 h-[5.5vh] w-[5.5vh] rounded-lg " style="height: 5.5vh; width: 5.5vh; padding: 14px" th:src="@{/logout.svg}"/> - </div> - </form> + <div class="col-8"></div> </div> -</div> -<div class="p-4" style="display: flex; justify-content: start"> - <form method="get" th:action="@{'/internships/create'}"> - <button style="background-color: #2A93D1" class=" px-8 py-4 rounded-xl text-white font-bold text-lg lg:text-xl">Add new internship</button> - </form> -</div> -<div class="flex flex-col justify-center " style="height: 88vh" th:each="internship : ${internships}"> - <div style="box-shadow: 0px 8px 16px rgba(0, 0, 0, 0.2); /* shadow-2xl */ - border-radius: 0.75rem; /* 12px rounded-xl */ - width: fit-content; /* w-fit */ - margin: 0 auto; /* mx-auto */ - display: flex;"> - </div> - <div class="flex flex-col lg:flex-row shadowCard w-full lg:w-8/12 mx-auto mt-8" style="border-radius: 40px; box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1), 0 1px 3px rgba(0, 0, 0, 0.08);"> - <div style="flex-basis: 25%; - border-top-left-radius: 40px; - border-bottom-left-radius: 40px; - display: flex; - justify-content: center; - background-image: url('/image1.png'); - background-size: cover; - background-position: center; - overflow: hidden;"> - - <div class="flex flex-col justify-center h-full w-full bgLogoBlur"> - <div class="flex justify-center"> - <img class=" m-8 lg:m-0 w-2/12 lg:w-6/12 h-auto" style="border-radius: 30px" th:src="@{/image1.png}"/> - </div> - </div> - </div> - <div class="basis-3/4 flex-col p-8" style="display:flex; flex-basis: 75%"> - <div class="flex justify-between"> - <div class="flex flex-col"> - <h1 class="font-bold text-xl lg:text-4xl" th:text="${internship.getPosting().getPosition()}"></h1> - <h3 class="text-md lg:text-2xl font-thin" th:text="${internship.getPosting().getCompany().getName()}"></h3> - </div> - <div class="flex justify-center"> - <div style="display: flex; flex-direction: column; justify-content: center;"> - <h1 style="background-color: #333; /* Define your off-black color here */ - color: white; - width: fit-content; - padding: 0.5rem; /* 8px */ - padding-left: 1rem; /* 16px */ - padding-right: 1rem; /* 16px */ - font-size: 1.125rem; /* 18px */ - font-weight: bold; - height: fit-content; - border-radius: 0.75rem; /* 12px */" th:text="${internship.getJournal().size()}"> - - </h1> - </div> - <div style="display: flex; flex-direction: column; justify-content: center;"> - <h1 style="color: #333; /* Define your off-black color here */ - width: fit-content; - padding-left: 0.5rem; /* 8px */ - padding-right: 0.5rem; /* 8px */ - font-size: 1rem; /* 16px */ - font-weight: bold; - height: fit-content;" th:text="${'од '+internship.getPosting().getPlannedWeeks()+ ' недели'}"> - - </h1> - </div> - </div> + + <form th:action="@{/student-internships}" method="get" class="py-3"> + <div class="row align-items-center"> + <div class="col-md-3"> + + <select class="form-control" id="status" name="status"> + <option value="" selected>All Statuses</option> + <option th:each="status : ${statuses}" + th:value="${status}" + th:text="${status}" + th:selected="${status == statusSelected}"> + </option> + </select> </div> - <div class='flex mt-4 flex-wrap circles' > - <span class="m-2 circles" th:each="week : ${internship.getJournal()}"> - <img class="rounded-full md:p-4" - th:style="${internship.getStatus() == T(mk.ukim.finki.wp.internships.model.internships.InternshipStatus).DEPOSITED} ? -'background-color: #73E860; border-radius: 50%; width: 80px; padding: 10px;' : -'background-color: #bfbfbf; border-radius: 50%; width: 80px; padding: 10px;'" th:src="@{/check.svg}"/> - </span> + <div class="col-md-3"> + <input type="text" class="form-control" id="professorName" name="professorName" + th:value="${professorName}" placeholder="Search by professor name/last name"> </div> - <div class="flex lg:flex-row justify-between rounded-xl shadow-xl shadowCard mt-4"> - <div class="flex justify-evenly w-full p-4 lg:p-0"> - <div class="flex flex-col justify-center"> - <div class="rounded-full bg-red-600" style="width: 20px; height: 20px"></div> - </div> - <div className="flex flex-col justify-center" style="align-content: center" > - <h1 class="ml-4 text-sm lg:text-2xl" th:text="${internship.getStatus()}"></h1> - </div> - </div> - <form method="get" th:action="${'/internships/' + internship.getId()+ '/'+student.getIndex()+'/'}"> - <button style="background-color: #2A93D1" class=" responsive-flex px-8 py-4 rounded-xl text-white font-bold text-lg lg:text-2xl">Дневник</button> - </form> + <div class="col-md-3"> + <button type="submit" class="btn btn-primary">Filter</button> </div> + </div> - </div> -</div> + </form> + + <div class="row"> + <table class="table table-striped table-hover"> + <thead> + <tr> + <th>ПрофеÑор</th> + <th>ОпиÑ</th> + <th>СтатуÑ</th> + <th>Опции</th> + </tr> + </thead> + <tbody> + <tr th:if="${page != null}" th:each="internship : ${page.getContent()}"> + <td th:text="${internship.getCoordinator().getName()}" class="col"></td> + <td th:text="${internship.getDescription()}" class="col-5"></td> + <td th:text="${internship.getStatus()}" class="col"></td> + <td th:with="InternshipStatus=${T(mk.ukim.finki.wp.internships.model.internships.InternshipStatus)}"> + + <form style="display: inline" + th:if="${internship.getStatus() == InternshipStatus.SUBMITTED}" + th:method="POST" + th:action="@{'/student-internships/delete/' + ${internship.getId()}}"> + <button class="btn btn-primary rounded-1 mx-1 btn-sm" style="background-color: #2A93D1;">Delete Internship + </button> + </form> + + <form style="display: inline" + th:if="${internship.getStatus() == InternshipStatus.ACCEPTED}" + th:method="GET" + th:action="@{'/student-internships/edit/' + ${internship.getId()}}"> + <button class="btn btn-primary rounded-1 mx-1 btn-sm" style="background-color: #2A93D1;">Edit Journal + </button> + </form> + + <form style="display: inline" + th:if="${internship.getStatus() == InternshipStatus.JOURNAL_SUBMITTED }" + th:method="GET" + th:action="@{'/student-internships/' + ${internship.getId()}}"> + <button class="btn btn-info btn-md">View Journal</button> + </form> + + + </td> + </tr> + </tbody> + </table> + <div th:include="fragments/paging :: pageSection(${page})" class="mt-4"></div> + </div> -<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js"></script> -<script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.9.2/dist/umd/popper.min.js"></script> +</div> </body> +</html> diff --git a/backend/src/main/resources/templates/student/journal-form.html b/backend/src/main/resources/templates/student/journal-form.html index 6f93c15..05b0afd 100644 --- a/backend/src/main/resources/templates/student/journal-form.html +++ b/backend/src/main/resources/templates/student/journal-form.html @@ -1,4 +1,4 @@ -<form method="post" th:action="@{/internship-weeks/save}"> +<form method="post" th:action="@{/student-internships/${internship.getId()}/save}"> <input type="hidden" name="id" th:value="${week?.getId()}"> <input name="internshipId" type="hidden" th:value="${internship.getId()}"> -- GitLab From 2b2d1d63bb1909214dfd279fa448844f44bfd4e4 Mon Sep 17 00:00:00 2001 From: Iva Georgieva <georgievaiva59@gmail.com> Date: Sun, 12 Jan 2025 16:47:20 +0100 Subject: [PATCH 3/7] Added editing a journal. Added createInternshipWeek.html. --- .../internships/InternshipRepository.java | 1 + .../service/InternshipService.java | 4 + .../service/InternshipWeekService.java | 1 - .../service/impl/InternshipServiceImpl.java | 9 ++ .../web/controller/StudentController.java | 47 ++++++- .../resources/templates/student/details.html | 10 ++ .../resources/templates/student/index.html | 22 +-- .../templates/student/journal-form.html | 127 +++++++++++++++--- 8 files changed, 182 insertions(+), 39 deletions(-) diff --git a/backend/src/main/java/mk/ukim/finki/wp/internships/repository/internships/InternshipRepository.java b/backend/src/main/java/mk/ukim/finki/wp/internships/repository/internships/InternshipRepository.java index 3939515..8b83217 100644 --- a/backend/src/main/java/mk/ukim/finki/wp/internships/repository/internships/InternshipRepository.java +++ b/backend/src/main/java/mk/ukim/finki/wp/internships/repository/internships/InternshipRepository.java @@ -2,6 +2,7 @@ package mk.ukim.finki.wp.internships.repository.internships; import mk.ukim.finki.wp.internships.model.internships.Internship; import mk.ukim.finki.wp.internships.model.internships.InternshipStatus; +import mk.ukim.finki.wp.internships.model.internships.InternshipWeek; import mk.ukim.finki.wp.internships.repository.JpaSpecificationRepository; import java.util.List; diff --git a/backend/src/main/java/mk/ukim/finki/wp/internships/service/InternshipService.java b/backend/src/main/java/mk/ukim/finki/wp/internships/service/InternshipService.java index b194b5f..c1803eb 100644 --- a/backend/src/main/java/mk/ukim/finki/wp/internships/service/InternshipService.java +++ b/backend/src/main/java/mk/ukim/finki/wp/internships/service/InternshipService.java @@ -4,8 +4,10 @@ import mk.ukim.finki.wp.internships.model.Professor; import mk.ukim.finki.wp.internships.model.Student; import mk.ukim.finki.wp.internships.model.internships.Internship; import mk.ukim.finki.wp.internships.model.internships.InternshipStatus; +import mk.ukim.finki.wp.internships.model.internships.InternshipWeek; import org.springframework.data.domain.Page; +import java.time.LocalDate; import java.util.List; public interface InternshipService { @@ -20,6 +22,8 @@ public interface InternshipService { Internship updateStatus(Long id, InternshipStatus status); + void updateJournal (Long id, Long weekId, LocalDate startDate, LocalDate endDate, String description); + Page<Internship> list(int page, int size, InternshipStatus status, String professorName, Student student); Page<Internship> list(int page, int size, Professor professor, InternshipStatus status, String studentIndex); diff --git a/backend/src/main/java/mk/ukim/finki/wp/internships/service/InternshipWeekService.java b/backend/src/main/java/mk/ukim/finki/wp/internships/service/InternshipWeekService.java index 6d2b3bb..2d50263 100644 --- a/backend/src/main/java/mk/ukim/finki/wp/internships/service/InternshipWeekService.java +++ b/backend/src/main/java/mk/ukim/finki/wp/internships/service/InternshipWeekService.java @@ -14,7 +14,6 @@ public interface InternshipWeekService { InternshipWeek update(Long id, LocalDate startDate, LocalDate endDate, Long internshipId, String description); InternshipWeek delete(Long id); - InternshipWeek updateCoordinatorComment(Long id, String coordinatorComment); InternshipWeek updateCompanyComment(Long id, String companyComment); } diff --git a/backend/src/main/java/mk/ukim/finki/wp/internships/service/impl/InternshipServiceImpl.java b/backend/src/main/java/mk/ukim/finki/wp/internships/service/impl/InternshipServiceImpl.java index 082b720..4e2c3cc 100644 --- a/backend/src/main/java/mk/ukim/finki/wp/internships/service/impl/InternshipServiceImpl.java +++ b/backend/src/main/java/mk/ukim/finki/wp/internships/service/impl/InternshipServiceImpl.java @@ -21,6 +21,7 @@ import org.springframework.data.domain.PageRequest; import org.springframework.data.jpa.domain.Specification; import org.springframework.stereotype.Service; +import java.time.LocalDate; import java.util.ArrayList; import java.util.List; @@ -67,6 +68,14 @@ public class InternshipServiceImpl implements InternshipService { return internshipRepository.save(internship); } + @Override + public void updateJournal(Long id, Long weekId, LocalDate startDate, LocalDate endDate, String description) { + Internship internship = internshipRepository.findById(id) + .orElseThrow(() -> new EntityNotFoundException("Internship with id " + id + " not found")); + + } + + @Override public Page<Internship> list(int page, int size, InternshipStatus status, String professorName, Student student) { Specification<Internship> spec = where(filterEqualsV(Internship.class, "student", student)); diff --git a/backend/src/main/java/mk/ukim/finki/wp/internships/web/controller/StudentController.java b/backend/src/main/java/mk/ukim/finki/wp/internships/web/controller/StudentController.java index d07381b..55a17cf 100644 --- a/backend/src/main/java/mk/ukim/finki/wp/internships/web/controller/StudentController.java +++ b/backend/src/main/java/mk/ukim/finki/wp/internships/web/controller/StudentController.java @@ -7,12 +7,14 @@ import mk.ukim.finki.wp.internships.model.internships.InternshipWeek; import mk.ukim.finki.wp.internships.repository.ProfessorRepository; import mk.ukim.finki.wp.internships.service.*; import org.springframework.data.domain.Page; +import org.springframework.format.annotation.DateTimeFormat; import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.*; +import java.time.LocalDate; import java.util.Comparator; import java.util.List; @@ -78,14 +80,16 @@ public class StudentController { return "student/details"; } - @PostMapping("/{internshipId}/save") - public String addWeekComment(@PathVariable Long internshipId, + @PostMapping("/{internshipId}/internship-weeks/{weekId}/save") + public String save(@PathVariable Long internshipId, @PathVariable Long weekId, - @RequestParam String coordinatorComment, + @RequestParam LocalDate startDate, + @RequestParam LocalDate endDate, + @RequestParam (required = false) String description, Model model) { - - return "redirect:/student-internships/" + internshipId; + internshipWeekService.update(weekId,startDate,endDate,internshipId,description); + return "redirect:/student-internships/edit/" + internshipId; } @@ -102,6 +106,20 @@ public class StudentController { return "student/create"; } + @GetMapping("/{internshipId}/addWeek") + public String showAddWeek(@PathVariable Long internshipId, Model model) { + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + //String studentIndex = authentication.getName(); + String studentIndex = "213051"; + Student student = studentService.getStudentByIndex(studentIndex); + + model.addAttribute("student", student); + + + return "student/createInternshipWeek"; + } + + @PostMapping("/create") public String create( @RequestParam String companyId, @@ -119,6 +137,25 @@ public class StudentController { } } + @PostMapping("/{internshipId}/createInternshipWeek") + public String create( + @PathVariable Long internshipId, + @DateTimeFormat LocalDate startDate, + @DateTimeFormat LocalDate endDate, + @RequestParam String description, + Model model) { + try { + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + //String studentIndex = authentication.getName(); + String studentIndex = "213051"; + this.internshipWeekService.create(startDate, endDate, internshipId, description); + return "redirect:/student-internships/{internshipId}"; + } catch (Exception e) { + model.addAttribute("error", true); + return "student/createInternshipWeek"; + } + } + @GetMapping("/edit/{id}") public String showEdit(@PathVariable Long id, Model model) { diff --git a/backend/src/main/resources/templates/student/details.html b/backend/src/main/resources/templates/student/details.html index 669a87d..1ee308d 100644 --- a/backend/src/main/resources/templates/student/details.html +++ b/backend/src/main/resources/templates/student/details.html @@ -47,6 +47,10 @@ <div class="container mx-auto bg-white shadow-lg rounded-lg p-6" th:with="InternshipStatus=${T(mk.ukim.finki.wp.internships.model.internships.InternshipStatus)}"> + <div class="text-lg-start mt-6"> + <a th:href="'/student-internships'" + class="bg-blue-500 text-white px-4 py-2 rounded">Сите пракÑи</a> + </div> <h1 style="width: 100%; text-align: center; font-weight: 100; font-size: 2.25rem; margin-bottom: 2rem; margin-top: 1rem;">Дневник</h1> <h1 style="width: 100%; text-align: center; font-weight: 100; font-size: 1.25rem; margin-bottom: 1rem; margin-top: 1rem;" th:text="'Студент: ' + ${student.getName()} + ' ' + ${student.getLastName()} + ' - ' + ${student.getIndex()}"></h1> @@ -99,6 +103,12 @@ th:text="${week.getCoordinatorComment()}"></div> </div> </div> + + <div class="text-center mt-6"> + <a th:href="'/student-internships/edit/' + ${internship.getId()}" + th:if="${internship.getStatus() == InternshipStatus.ACCEPTED}" + class="bg-green-500 text-white px-4 py-2 rounded">Edit Journal</a> + </div> </div> </body> diff --git a/backend/src/main/resources/templates/student/index.html b/backend/src/main/resources/templates/student/index.html index 2fab313..104bf41 100644 --- a/backend/src/main/resources/templates/student/index.html +++ b/backend/src/main/resources/templates/student/index.html @@ -65,6 +65,13 @@ <td th:text="${internship.getStatus()}" class="col"></td> <td th:with="InternshipStatus=${T(mk.ukim.finki.wp.internships.model.internships.InternshipStatus)}"> + <form style="display: inline" + th:if="${internship.getStatus()!=InternshipStatus.REJECTED}" + th:method="GET" + th:action="@{'/student-internships/' + ${internship.getId()}}"> + <button class="btn btn-info btn-md">View Journal</button> + </form> + <form style="display: inline" th:if="${internship.getStatus() == InternshipStatus.SUBMITTED}" th:method="POST" @@ -73,21 +80,6 @@ </button> </form> - <form style="display: inline" - th:if="${internship.getStatus() == InternshipStatus.ACCEPTED}" - th:method="GET" - th:action="@{'/student-internships/edit/' + ${internship.getId()}}"> - <button class="btn btn-primary rounded-1 mx-1 btn-sm" style="background-color: #2A93D1;">Edit Journal - </button> - </form> - - <form style="display: inline" - th:if="${internship.getStatus() == InternshipStatus.JOURNAL_SUBMITTED }" - th:method="GET" - th:action="@{'/student-internships/' + ${internship.getId()}}"> - <button class="btn btn-info btn-md">View Journal</button> - </form> - </td> </tr> diff --git a/backend/src/main/resources/templates/student/journal-form.html b/backend/src/main/resources/templates/student/journal-form.html index 05b0afd..73d8fc9 100644 --- a/backend/src/main/resources/templates/student/journal-form.html +++ b/backend/src/main/resources/templates/student/journal-form.html @@ -1,18 +1,109 @@ -<form method="post" th:action="@{/student-internships/${internship.getId()}/save}"> - <input type="hidden" name="id" th:value="${week?.getId()}"> - <input name="internshipId" type="hidden" th:value="${internship.getId()}"> - - <label for="startDate">Start Date:</label> - <input id="startDate" type="date" name="startDate" th:value="${week?.getStartDate()}"> - <br> - - <label for="endDate">End Date:</label> - <input id="endDate" type="date" name="endDate" th:value="${week?.getEndDate()}"> - <br> - - <label for="description">Description:</label> - <input id="description" type="text" name="description" th:value="${week?.getDescription()}"> - <br> - <input id="index" type="hidden" name="index" th:value="${student?.getIndex()}"> - <button type="submit">Save</button> -</form> +<!DOCTYPE html> +<html lang="en" + xmlns:th="http://www.thymeleaf.org" + xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" + xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity6" + layout:decorate="~{layout}"> +<head> + <link href="https://cdn.jsdelivr.net/npm/tailwindcss@2.2.19/dist/tailwind.min.css" rel="stylesheet"> + <meta charset="UTF-8"> + <title>Дневник</title> + <style> + .cardWeek:hover { + outline: #1a3f8a solid 2px; + transition: outline-width 100ms; + } + + @media (min-width: 700px) { + .responsive-flex { + flex-direction: row; + } + + .responsive-basis { + flex-basis: 33.3333%; + } + + .fontsize { + font-size: 3.5rem; + } + } + + @media (max-width: 1000px) { + .responsive-flex { + flex-direction: column; + } + + .responsive-basis { + flex-basis: 25%; + } + + .fontsize { + font-size: 2rem; + } + } + </style> +</head> +<body layout:fragment="content" class="bg-gray-100"> + +<div class="container mx-auto bg-white shadow-lg rounded-lg p-6" + th:with="InternshipStatus=${T(mk.ukim.finki.wp.internships.model.internships.InternshipStatus)}"> + <h1 style="width: 100%; text-align: center; font-weight: 100; font-size: 2.25rem; margin-bottom: 2rem; margin-top: 1rem;">Дневник</h1> + <h1 style="width: 100%; text-align: center; font-weight: 100; font-size: 1.25rem; margin-bottom: 1rem; margin-top: 1rem;" + th:text="'Студент: ' + ${student.getName()} + ' ' + ${student.getLastName()} + ' - ' + ${student.getIndex()}"></h1> + <h1 style="width: 100%; text-align: center; font-weight: 100; font-size: 1.25rem; margin-bottom: 1rem; margin-top: 1rem;" + th:text="'ОпиÑ: ' + ${internship.description}"></h1> + <h1 style="width: 100%; text-align: center; font-weight: 100; font-size: 1.25rem; margin-bottom: 1rem; margin-top: 1rem;" + th:text="'СтатуÑ: ' + ${internship.getStatus()}"></h1> + + <div th:if="${journal == null or journal.isEmpty()}"> + <p class="text-center text-lg text-gray-500">Студентот Ñеуште нема додадено белешка во дневникот</p> + </div> + + <div style="width: 100%; height: max-content; max-width: none; flex-basis: 75%; margin-left: auto; margin-right: auto;" class="lg:w-fit md:basis-2/3 lg:basis-3/4 p-8 w-full lg:w-fit mx-auto grid grid-cols-1 lg:grid-cols-2 gap-4"> + <form + th:each="week : ${journal}" + th:action="'/student-internships/'+${internship.getId()}+'/internship-weeks/'+${week.getId()}+'/save'" + method="post" + style="display: contents;"> + <div style="display: flex; flex-direction: column; box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.1); border-radius: 20px; padding: 16px; min-height: auto;" + class="lg:h-auto flex flex-col shadowCard rounded-xl p-4 shadow-xl h-[30vh] lg:h-auto cardWeek"> + <div style="display: flex; flex-direction: column; justify-content: space-between;"> + <label for="startDate" style="color: #333; font-weight: bold; margin-bottom: 0.5rem;">Start Date</label> + <input type="date" id="startDate" name="startDate" th:value="${week.getStartDate()}" + style="border-radius: 0.5rem; border: 1px solid #ccc; padding: 0.5rem;"> + </div> + <div style="display: flex; flex-direction: column; justify-content: space-between; margin-top: 1rem;"> + <label for="endDate" style="color: #333; font-weight: bold; margin-bottom: 0.5rem;">End Date</label> + <input type="date" id="endDate" name="endDate" th:value="${week.getEndDate()}" + style="border-radius: 0.5rem; border: 1px solid #ccc; padding: 0.5rem;"> + </div> + <div style="display: flex; flex-direction: column; justify-content: space-between; margin-top: 1rem;"> + <label for="description" style="color: #333; font-weight: bold; margin-bottom: 0.5rem;">Description</label> + <textarea id="description" name="description" + style="border-radius: 0.5rem; border: 1px solid #ccc; padding: 0.5rem; height: 100%;" + th:text="${week.getDescription()}"></textarea> + </div> + <div style="margin-top: 1rem;"> + <label for="companyComment" style="color: #333; font-weight: bold; margin-bottom: 0.5rem;" th:if="${week.getCompanyComment()}">Company Comment</label> + <div id="companyComment" + style="border-radius: 0.75rem; background-color: #f3f4f6; padding: 0.5rem; font-size: 0.875rem;" + th:if="${week.getCompanyComment()}" th:text="${week.getCompanyComment()}"></div> + </div> + <div style="margin-top: 1rem;"> + <label for="coordinatorComment" style="color: #333; font-weight: bold; margin-bottom: 0.5rem;" th:if="${week.getCoordinatorComment()}">Coordinator Comment</label> + <div id="coordinatorComment" + style="border-radius: 0.75rem; background-color: #f3f4f6; padding: 0.5rem; font-size: 0.875rem;" + th:if="${week.getCoordinatorComment()}" th:text="${week.getCoordinatorComment()}"></div> + </div> + <button type="submit" class="bg-blue-500 text-white px-4 py-2 rounded mt-4">Save</button> + </div> + </form> + </div> + <div class="text-center mt-6"> + <a th:href="'/student-internships/' + ${internship.getId()} + '/addWeek'" + class="bg-green-500 text-white px-4 py-2 rounded">Add Week</a> + </div> +</div> + +</body> +</html> -- GitLab From 553eb09661ce998d48502c5aa6afc0259a3fad8a Mon Sep 17 00:00:00 2001 From: Iva Georgieva <georgievaiva59@gmail.com> Date: Sun, 12 Jan 2025 16:48:49 +0100 Subject: [PATCH 4/7] Added editing a journal. Added createInternshipWeek.html. --- .../student/createInternshipWeek.html | 45 +++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 backend/src/main/resources/templates/student/createInternshipWeek.html diff --git a/backend/src/main/resources/templates/student/createInternshipWeek.html b/backend/src/main/resources/templates/student/createInternshipWeek.html new file mode 100644 index 0000000..fa6f1e1 --- /dev/null +++ b/backend/src/main/resources/templates/student/createInternshipWeek.html @@ -0,0 +1,45 @@ +<!DOCTYPE html> +<html xmlns:th="http://www.thymeleaf.org" + xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" + layout:decorate="~{layout}"> +<head> + <title>Додавање недела во дневник</title> +</head> +<body> +<div class="container mt-4" layout:fragment="content"> + <h1 style="width: 100%; flex-basis: 12.5%; padding: 5px; font-weight: 100; font-size: 2.25rem; margin-bottom: 5px; margin-top: 5px;" + th:text="'Додавање Ñедмица во дневникот за Ñтудент ' + ${student.getName()}"></h1> + + <form th:action="@{'/student-internships/'+${internshipId}+'/createInternshipWeek'}" + th:method="post" enctype="multipart/form-data" + class="my-4 form-control"> + + <div style="display: flex; flex-direction: column; justify-content: space-between;"> + <label for="startDate" style="color: #333; font-weight: bold; margin-bottom: 0.5rem;">Start Date</label> + <input type="date" id="startDate" name="startDate" + style="border-radius: 0.5rem; border: 1px solid #ccc; padding: 0.5rem;"> + </div> + <div style="display: flex; flex-direction: column; justify-content: space-between; margin-top: 1rem;"> + <label for="endDate" style="color: #333; font-weight: bold; margin-bottom: 0.5rem;">End Date</label> + <input type="date" id="endDate" name="endDate" + style="border-radius: 0.5rem; border: 1px solid #ccc; padding: 0.5rem;"> + </div> + + <div class="form-group mb-3"> + <label for="description">Description:</label> + <input type="text" + id="description" + name="description" + class="form-control" + required> + </div> + + <button id="submit" type="submit" class="btn btn-primary">Save</button> + <button type="button" class="btn btn-secondary" onclick="window.history.back();">Cancel</button> + </form> + +</div> + +</body> +</html> + -- GitLab From f137a99f7cca4f48f5505549f1c50a4747c6cb51 Mon Sep 17 00:00:00 2001 From: Iva Georgieva <georgievaiva59@gmail.com> Date: Sun, 12 Jan 2025 17:00:39 +0100 Subject: [PATCH 5/7] Added submitting a journal. --- .../wp/internships/web/controller/StudentController.java | 6 ++++++ backend/src/main/resources/templates/student/details.html | 8 ++++++++ .../main/resources/templates/student/journal-form.html | 3 +++ 3 files changed, 17 insertions(+) diff --git a/backend/src/main/java/mk/ukim/finki/wp/internships/web/controller/StudentController.java b/backend/src/main/java/mk/ukim/finki/wp/internships/web/controller/StudentController.java index 55a17cf..ef2f999 100644 --- a/backend/src/main/java/mk/ukim/finki/wp/internships/web/controller/StudentController.java +++ b/backend/src/main/java/mk/ukim/finki/wp/internships/web/controller/StudentController.java @@ -183,6 +183,12 @@ public class StudentController { return "redirect:/student-internships"; } + @GetMapping("/submit/{id}") + public String submit(@PathVariable Long id) { + this.internshipService.updateStatus(id, InternshipStatus.JOURNAL_SUBMITTED); + return "redirect:/student-internships"; + } + diff --git a/backend/src/main/resources/templates/student/details.html b/backend/src/main/resources/templates/student/details.html index 1ee308d..2359549 100644 --- a/backend/src/main/resources/templates/student/details.html +++ b/backend/src/main/resources/templates/student/details.html @@ -109,6 +109,14 @@ th:if="${internship.getStatus() == InternshipStatus.ACCEPTED}" class="bg-green-500 text-white px-4 py-2 rounded">Edit Journal</a> </div> + + <div class="text-center mt-6"> + <a th:href="'/student-internships/' + ${internship.getId()} + '/addWeek'" + class="bg-green-500 text-white px-4 py-2 rounded">Add Week</a> + <a th:href="'/student-internships/submit/' + ${internship.getId()}" + th:if="${internship.getStatus() != InternshipStatus.JOURNAL_SUBMITTED}" + class="bg-green-500 text-white px-4 py-2 rounded">Submit journal</a> + </div> </div> </body> diff --git a/backend/src/main/resources/templates/student/journal-form.html b/backend/src/main/resources/templates/student/journal-form.html index 73d8fc9..c81bfd1 100644 --- a/backend/src/main/resources/templates/student/journal-form.html +++ b/backend/src/main/resources/templates/student/journal-form.html @@ -102,6 +102,9 @@ <div class="text-center mt-6"> <a th:href="'/student-internships/' + ${internship.getId()} + '/addWeek'" class="bg-green-500 text-white px-4 py-2 rounded">Add Week</a> + <a th:href="'/student-internships/submit/' + ${internship.getId()}" + th:if="${internship.getStatus() != InternshipStatus.JOURNAL_SUBMITTED}" + class="bg-green-500 text-white px-4 py-2 rounded">Submit journal</a> </div> </div> -- GitLab From 27c79369866704b82e8570cd2e4d25c8d8f7b20f Mon Sep 17 00:00:00 2001 From: Iva Georgieva <georgievaiva59@gmail.com> Date: Sun, 12 Jan 2025 18:44:58 +0100 Subject: [PATCH 6/7] Finalized templates. --- .../web/controller/InternshipController.java | 2 -- .../{controller => }/StudentController.java | 3 +- .../resources/templates/student/create.html | 8 ++--- .../student/createInternshipWeek.html | 12 +++---- .../resources/templates/student/details.html | 27 +++++++------- .../resources/templates/student/index.html | 14 ++++---- .../templates/student/journal-form.html | 35 ++++++++++++------- 7 files changed, 55 insertions(+), 46 deletions(-) delete mode 100644 backend/src/main/java/mk/ukim/finki/wp/internships/model/web/controller/InternshipController.java rename backend/src/main/java/mk/ukim/finki/wp/internships/web/{controller => }/StudentController.java (98%) diff --git a/backend/src/main/java/mk/ukim/finki/wp/internships/model/web/controller/InternshipController.java b/backend/src/main/java/mk/ukim/finki/wp/internships/model/web/controller/InternshipController.java deleted file mode 100644 index 0bf56e5..0000000 --- a/backend/src/main/java/mk/ukim/finki/wp/internships/model/web/controller/InternshipController.java +++ /dev/null @@ -1,2 +0,0 @@ -@Controller -@RequestMapping diff --git a/backend/src/main/java/mk/ukim/finki/wp/internships/web/controller/StudentController.java b/backend/src/main/java/mk/ukim/finki/wp/internships/web/StudentController.java similarity index 98% rename from backend/src/main/java/mk/ukim/finki/wp/internships/web/controller/StudentController.java rename to backend/src/main/java/mk/ukim/finki/wp/internships/web/StudentController.java index ef2f999..da3d650 100644 --- a/backend/src/main/java/mk/ukim/finki/wp/internships/web/controller/StudentController.java +++ b/backend/src/main/java/mk/ukim/finki/wp/internships/web/StudentController.java @@ -1,10 +1,9 @@ -package mk.ukim.finki.wp.internships.web.controller; +package mk.ukim.finki.wp.internships.web; import mk.ukim.finki.wp.internships.model.Professor; import mk.ukim.finki.wp.internships.model.Student; import mk.ukim.finki.wp.internships.model.internships.Internship; import mk.ukim.finki.wp.internships.model.internships.InternshipStatus; import mk.ukim.finki.wp.internships.model.internships.InternshipWeek; -import mk.ukim.finki.wp.internships.repository.ProfessorRepository; import mk.ukim.finki.wp.internships.service.*; import org.springframework.data.domain.Page; import org.springframework.format.annotation.DateTimeFormat; diff --git a/backend/src/main/resources/templates/student/create.html b/backend/src/main/resources/templates/student/create.html index 8682d73..dcb2ab7 100644 --- a/backend/src/main/resources/templates/student/create.html +++ b/backend/src/main/resources/templates/student/create.html @@ -15,7 +15,7 @@ class="my-4 form-control"> <div class="form-group mb-3"> - <label for="companyId">Company:</label> + <label for="companyId">Компанија:</label> <select class="form-control" id="companyId" name="companyId" required> <option value="" disabled selected></option> <option th:each="company : ${companies}" @@ -25,7 +25,7 @@ </div> <div class="form-group mb-3"> - <label for="description">Description:</label> + <label for="description">ОпиÑ:</label> <input type="text" id="description" name="description" @@ -33,8 +33,8 @@ required> </div> - <button id="submit" type="submit" class="btn btn-primary">Save</button> - <button type="button" class="btn btn-secondary" onclick="window.history.back();">Cancel</button> + <button id="submit" type="submit" class="btn btn-primary">Зачувај</button> + <button type="button" class="btn btn-secondary" onclick="window.history.back();">Откажи</button> </form> </div> diff --git a/backend/src/main/resources/templates/student/createInternshipWeek.html b/backend/src/main/resources/templates/student/createInternshipWeek.html index fa6f1e1..0d1ebab 100644 --- a/backend/src/main/resources/templates/student/createInternshipWeek.html +++ b/backend/src/main/resources/templates/student/createInternshipWeek.html @@ -3,7 +3,7 @@ xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorate="~{layout}"> <head> - <title>Додавање недела во дневник</title> + <title>Додавање Ñедмица во дневник</title> </head> <body> <div class="container mt-4" layout:fragment="content"> @@ -15,18 +15,18 @@ class="my-4 form-control"> <div style="display: flex; flex-direction: column; justify-content: space-between;"> - <label for="startDate" style="color: #333; font-weight: bold; margin-bottom: 0.5rem;">Start Date</label> + <label for="startDate" style="color: #333; font-weight: bold; margin-bottom: 0.5rem;">Датум на почеток</label> <input type="date" id="startDate" name="startDate" style="border-radius: 0.5rem; border: 1px solid #ccc; padding: 0.5rem;"> </div> <div style="display: flex; flex-direction: column; justify-content: space-between; margin-top: 1rem;"> - <label for="endDate" style="color: #333; font-weight: bold; margin-bottom: 0.5rem;">End Date</label> + <label for="endDate" style="color: #333; font-weight: bold; margin-bottom: 0.5rem;">Датум на крај</label> <input type="date" id="endDate" name="endDate" style="border-radius: 0.5rem; border: 1px solid #ccc; padding: 0.5rem;"> </div> <div class="form-group mb-3"> - <label for="description">Description:</label> + <label for="description">ОпиÑ:</label> <input type="text" id="description" name="description" @@ -34,8 +34,8 @@ required> </div> - <button id="submit" type="submit" class="btn btn-primary">Save</button> - <button type="button" class="btn btn-secondary" onclick="window.history.back();">Cancel</button> + <button id="submit" type="submit" class="btn btn-primary">Зачувај</button> + <button type="button" class="btn btn-secondary" onclick="window.history.back();">Откажи</button> </form> </div> diff --git a/backend/src/main/resources/templates/student/details.html b/backend/src/main/resources/templates/student/details.html index 2359549..67aa0ec 100644 --- a/backend/src/main/resources/templates/student/details.html +++ b/backend/src/main/resources/templates/student/details.html @@ -54,13 +54,18 @@ <h1 style="width: 100%; text-align: center; font-weight: 100; font-size: 2.25rem; margin-bottom: 2rem; margin-top: 1rem;">Дневник</h1> <h1 style="width: 100%; text-align: center; font-weight: 100; font-size: 1.25rem; margin-bottom: 1rem; margin-top: 1rem;" th:text="'Студент: ' + ${student.getName()} + ' ' + ${student.getLastName()} + ' - ' + ${student.getIndex()}"></h1> + + <h1 style="width: 100%; text-align: center; font-weight: 100; font-size: 1.25rem; margin-bottom: 1rem; margin-top: 1rem;" + th:text="'Компанија: ' + ${internship.getCompany().getName()}"></h1> <h1 style="width: 100%; text-align: center; font-weight: 100; font-size: 1.25rem; margin-bottom: 1rem; margin-top: 1rem;" + th:if="${internship.getDescription()!=null && !internship.getDescription().isEmpty()}" th:text="'ОпиÑ: ' + ${internship.description}"></h1> + <h1 style="width: 100%; text-align: center; font-weight: 100; font-size: 1.25rem; margin-bottom: 1rem; margin-top: 1rem;" th:text="'СтатуÑ: ' + ${internship.getStatus()}"></h1> <div th:if="${journal == null or journal.isEmpty()}"> - <p class="text-center text-lg text-gray-500">Студентот Ñеуште нема додадено белешка во дневникот</p> + <p class="text-center text-lg text-gray-500">Студентот Ñе уште нема додадено белешка во дневникот</p> </div> <div style="width: 100%; height: max-content; max-width: none; flex-basis: 75%; margin-left: auto; margin-right: auto;" class="lg:w-fit md:basis-2/3 lg:basis-3/4 p-8 w-full lg:w-fit mx-auto grid grid-cols-1 lg:grid-cols-2 gap-4"> @@ -81,21 +86,21 @@ th:text="${week.getStartDate().getDayOfMonth() + '-' + week.getEndDate().getDayOfMonth() + ' ' + week.getEndDate().getMonth()}"></h1> </div> </div> - <label for="description" style="color: #333; font-weight: bold; width: fit-content; height: fit-content; margin-top: 1rem;">Description</label> + <label for="description" style="color: #333; font-weight: bold; width: fit-content; height: fit-content; margin-top: 1rem;">ОпиÑ</label> <div id="description" style="border-radius: 0.75rem; margin-top: 0.5rem; height: 100%; padding: 0.5rem; font-size: 0.875rem; background-color: #e9f2f8" class="textarea" - th:text="${week.getDescription()}"></div> + th:text="${week?.getDescription()}"></div> - <label for="companyComment" th:if="${week.getCompanyComment()!=null && !week.getCompanyComment().isEmpty()}" style="color: #333; font-weight: bold; width: fit-content; height: fit-content; margin-top: 1rem;">Company comment</label> + <label for="companyComment" th:if="${week.getCompanyComment()!=null && !week.getCompanyComment().isEmpty()}" style="color: #333; font-weight: bold; width: fit-content; height: fit-content; margin-top: 1rem;">Коментар на компанија</label> <div id="companyComment" style="border-radius: 0.75rem; margin-top: 0.5rem; height: 100%; padding: 0.5rem; font-size: 0.875rem; background-color: #f3f4f6" th:if="${week.getCompanyComment()!=null && !week.getCompanyComment().isEmpty()}" th:text="${week.getCompanyComment()}"></div> - <label for="coordinatorComment" th:if="${week.getCoordinatorComment()!=null && !week.getCoordinatorComment().isEmpty()}" style="color: #333; font-weight: bold; width: fit-content; height: fit-content; margin-top: 1rem;">Coordinator comment</label> + <label for="coordinatorComment" th:if="${week.getCoordinatorComment()!=null && !week.getCoordinatorComment().isEmpty()}" style="color: #333; font-weight: bold; width: fit-content; height: fit-content; margin-top: 1rem;">Коментар на координатор</label> <div id="coordinatorComment" style="border-radius: 0.75rem; margin-top: 0.5rem; height: 100%; padding: 0.5rem; font-size: 0.875rem; background-color: #f3f4f6" @@ -104,18 +109,16 @@ </div> </div> + <div class="text-center mt-6"> <a th:href="'/student-internships/edit/' + ${internship.getId()}" th:if="${internship.getStatus() == InternshipStatus.ACCEPTED}" - class="bg-green-500 text-white px-4 py-2 rounded">Edit Journal</a> - </div> - - <div class="text-center mt-6"> - <a th:href="'/student-internships/' + ${internship.getId()} + '/addWeek'" - class="bg-green-500 text-white px-4 py-2 rounded">Add Week</a> + class="bg-green-500 text-white px-4 py-2 rounded">Уреди дневник</a> <a th:href="'/student-internships/submit/' + ${internship.getId()}" th:if="${internship.getStatus() != InternshipStatus.JOURNAL_SUBMITTED}" - class="bg-green-500 text-white px-4 py-2 rounded">Submit journal</a> + class="bg-green-500 text-white px-4 py-2 rounded" + onclick="return confirm('Дали Ñте Ñигурни дека Ñакате да го потврдите дневникот?')">Потврди дневник</a> + </div> </div> diff --git a/backend/src/main/resources/templates/student/index.html b/backend/src/main/resources/templates/student/index.html index 104bf41..26002d2 100644 --- a/backend/src/main/resources/templates/student/index.html +++ b/backend/src/main/resources/templates/student/index.html @@ -11,12 +11,12 @@ <body layout:fragment="content"> <div class="container"> <h1 style="width: 100%; flex-basis: 12.5%; padding: 5px; font-weight: 100; font-size: 2.25rem; margin-bottom: 5px; margin-top: 5px;" - th:text="'ПракÑи за Ñтудент ' + ${student.getName()}"></h1> + th:text="'ПракÑи за Ñтудентот ' + ${student?.getName()} + ' ' + ${student?.getLastName()} + ', ' + ${student?.getIndex()}"></h1> <div class="row mb-2"> <div class="col-2"> <a class="btn btn-primary" - th:href="@{/student-internships/add}">Add Internship</a> + th:href="@{/student-internships/add}">Додади пракÑа</a> </div> <div class="col-8"></div> </div> @@ -27,7 +27,7 @@ <div class="col-md-3"> <select class="form-control" id="status" name="status"> - <option value="" selected>All Statuses</option> + <option value="" selected>СтатуÑи</option> <option th:each="status : ${statuses}" th:value="${status}" th:text="${status}" @@ -38,11 +38,11 @@ <div class="col-md-3"> <input type="text" class="form-control" id="professorName" name="professorName" - th:value="${professorName}" placeholder="Search by professor name/last name"> + th:value="${professorName}" placeholder="Пребарувај по име/презиме на профеÑор"> </div> <div class="col-md-3"> - <button type="submit" class="btn btn-primary">Filter</button> + <button type="submit" class="btn btn-primary">Филтрирај</button> </div> </div> @@ -69,14 +69,14 @@ th:if="${internship.getStatus()!=InternshipStatus.REJECTED}" th:method="GET" th:action="@{'/student-internships/' + ${internship.getId()}}"> - <button class="btn btn-info btn-md">View Journal</button> + <button class="btn btn-info btn-md">Преглед на дневник</button> </form> <form style="display: inline" th:if="${internship.getStatus() == InternshipStatus.SUBMITTED}" th:method="POST" th:action="@{'/student-internships/delete/' + ${internship.getId()}}"> - <button class="btn btn-primary rounded-1 mx-1 btn-sm" style="background-color: #2A93D1;">Delete Internship + <button class="btn btn-primary rounded-1 mx-1 btn-sm" style="background-color: #2A93D1;">Избриши пракÑа </button> </form> diff --git a/backend/src/main/resources/templates/student/journal-form.html b/backend/src/main/resources/templates/student/journal-form.html index c81bfd1..2421990 100644 --- a/backend/src/main/resources/templates/student/journal-form.html +++ b/backend/src/main/resources/templates/student/journal-form.html @@ -47,16 +47,24 @@ <div class="container mx-auto bg-white shadow-lg rounded-lg p-6" th:with="InternshipStatus=${T(mk.ukim.finki.wp.internships.model.internships.InternshipStatus)}"> + <div class="text-lg-start mt-6"> + <a th:href="'/student-internships/'+${internship.getId()}" + class="bg-blue-500 text-white px-4 py-2 rounded">Ðазад</a> + </div> <h1 style="width: 100%; text-align: center; font-weight: 100; font-size: 2.25rem; margin-bottom: 2rem; margin-top: 1rem;">Дневник</h1> <h1 style="width: 100%; text-align: center; font-weight: 100; font-size: 1.25rem; margin-bottom: 1rem; margin-top: 1rem;" th:text="'Студент: ' + ${student.getName()} + ' ' + ${student.getLastName()} + ' - ' + ${student.getIndex()}"></h1> + + <h1 style="width: 100%; text-align: center; font-weight: 100; font-size: 1.25rem; margin-bottom: 1rem; margin-top: 1rem;" + th:text="'Компанија: ' + ${internship.getCompany().getName()}"></h1> <h1 style="width: 100%; text-align: center; font-weight: 100; font-size: 1.25rem; margin-bottom: 1rem; margin-top: 1rem;" + th:if="${internship.getDescription()!=null && !internship.getDescription().isEmpty()}" th:text="'ОпиÑ: ' + ${internship.description}"></h1> <h1 style="width: 100%; text-align: center; font-weight: 100; font-size: 1.25rem; margin-bottom: 1rem; margin-top: 1rem;" th:text="'СтатуÑ: ' + ${internship.getStatus()}"></h1> <div th:if="${journal == null or journal.isEmpty()}"> - <p class="text-center text-lg text-gray-500">Студентот Ñеуште нема додадено белешка во дневникот</p> + <p class="text-center text-lg text-gray-500">Студентот Ñе уште нема додадено белешка во дневникот</p> </div> <div style="width: 100%; height: max-content; max-width: none; flex-basis: 75%; margin-left: auto; margin-right: auto;" class="lg:w-fit md:basis-2/3 lg:basis-3/4 p-8 w-full lg:w-fit mx-auto grid grid-cols-1 lg:grid-cols-2 gap-4"> @@ -68,43 +76,44 @@ <div style="display: flex; flex-direction: column; box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.1); border-radius: 20px; padding: 16px; min-height: auto;" class="lg:h-auto flex flex-col shadowCard rounded-xl p-4 shadow-xl h-[30vh] lg:h-auto cardWeek"> <div style="display: flex; flex-direction: column; justify-content: space-between;"> - <label for="startDate" style="color: #333; font-weight: bold; margin-bottom: 0.5rem;">Start Date</label> + <label for="startDate" style="color: #333; font-weight: bold; margin-bottom: 0.5rem;">Датум на почеток</label> <input type="date" id="startDate" name="startDate" th:value="${week.getStartDate()}" style="border-radius: 0.5rem; border: 1px solid #ccc; padding: 0.5rem;"> </div> <div style="display: flex; flex-direction: column; justify-content: space-between; margin-top: 1rem;"> - <label for="endDate" style="color: #333; font-weight: bold; margin-bottom: 0.5rem;">End Date</label> - <input type="date" id="endDate" name="endDate" th:value="${week.getEndDate()}" + <label for="endDate" style="color: #333; font-weight: bold; margin-bottom: 0.5rem;">Датум на крај</label> + <input type="date" id="endDate" name="endDate" th:value="${week?.getEndDate()}" style="border-radius: 0.5rem; border: 1px solid #ccc; padding: 0.5rem;"> </div> <div style="display: flex; flex-direction: column; justify-content: space-between; margin-top: 1rem;"> - <label for="description" style="color: #333; font-weight: bold; margin-bottom: 0.5rem;">Description</label> + <label for="description" style="color: #333; font-weight: bold; margin-bottom: 0.5rem;">ОпиÑ</label> <textarea id="description" name="description" style="border-radius: 0.5rem; border: 1px solid #ccc; padding: 0.5rem; height: 100%;" - th:text="${week.getDescription()}"></textarea> + th:text="${week?.getDescription()}"></textarea> </div> <div style="margin-top: 1rem;"> - <label for="companyComment" style="color: #333; font-weight: bold; margin-bottom: 0.5rem;" th:if="${week.getCompanyComment()}">Company Comment</label> + <label for="companyComment" style="color: #333; font-weight: bold; margin-bottom: 0.5rem;" th:if="${week?.getCompanyComment()}">Коментар на компанија</label> <div id="companyComment" style="border-radius: 0.75rem; background-color: #f3f4f6; padding: 0.5rem; font-size: 0.875rem;" - th:if="${week.getCompanyComment()}" th:text="${week.getCompanyComment()}"></div> + th:if="${week?.getCompanyComment()}" th:text="${week?.getCompanyComment()}"></div> </div> <div style="margin-top: 1rem;"> - <label for="coordinatorComment" style="color: #333; font-weight: bold; margin-bottom: 0.5rem;" th:if="${week.getCoordinatorComment()}">Coordinator Comment</label> + <label for="coordinatorComment" style="color: #333; font-weight: bold; margin-bottom: 0.5rem;" th:if="${week?.getCoordinatorComment()}">Коментар на координатор</label> <div id="coordinatorComment" style="border-radius: 0.75rem; background-color: #f3f4f6; padding: 0.5rem; font-size: 0.875rem;" - th:if="${week.getCoordinatorComment()}" th:text="${week.getCoordinatorComment()}"></div> + th:if="${week?.getCoordinatorComment()}" th:text="${week?.getCoordinatorComment()}"></div> </div> - <button type="submit" class="bg-blue-500 text-white px-4 py-2 rounded mt-4">Save</button> + <button type="submit" class="bg-blue-500 text-white px-4 py-2 rounded mt-4">Зачувај</button> </div> </form> </div> <div class="text-center mt-6"> <a th:href="'/student-internships/' + ${internship.getId()} + '/addWeek'" - class="bg-green-500 text-white px-4 py-2 rounded">Add Week</a> + class="bg-green-500 text-white px-4 py-2 rounded">Додади Ñедмица</a> <a th:href="'/student-internships/submit/' + ${internship.getId()}" th:if="${internship.getStatus() != InternshipStatus.JOURNAL_SUBMITTED}" - class="bg-green-500 text-white px-4 py-2 rounded">Submit journal</a> + class="bg-green-500 text-white px-4 py-2 rounded" + onclick="return confirm('Дали Ñте Ñигурни дека Ñакате да го потврдите дневникот?')">Потврди дневник</a> </div> </div> -- GitLab From 06de77a1697996acdd729d623a43bb18a48d237a Mon Sep 17 00:00:00 2001 From: Iva Georgieva <georgievaiva59@gmail.com> Date: Sun, 12 Jan 2025 19:24:11 +0100 Subject: [PATCH 7/7] Added setting coordinator of internship. --- .../model/internships/InternshipWeek.java | 4 +-- .../service/impl/InternshipServiceImpl.java | 11 +++++-- .../wp/internships/web/StudentController.java | 29 ++++++++----------- 3 files changed, 23 insertions(+), 21 deletions(-) diff --git a/backend/src/main/java/mk/ukim/finki/wp/internships/model/internships/InternshipWeek.java b/backend/src/main/java/mk/ukim/finki/wp/internships/model/internships/InternshipWeek.java index a6406ac..9b3e921 100644 --- a/backend/src/main/java/mk/ukim/finki/wp/internships/model/internships/InternshipWeek.java +++ b/backend/src/main/java/mk/ukim/finki/wp/internships/model/internships/InternshipWeek.java @@ -14,7 +14,7 @@ import java.time.LocalDate; public class InternshipWeek { @Id - //@Column(name = "id") + @Column(name = "id") @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @@ -23,7 +23,7 @@ public class InternshipWeek { private LocalDate endDate; @ManyToOne - //@JoinColumn(name="internship_id") + @JoinColumn(name="internship_id") private Internship internship; private String description; diff --git a/backend/src/main/java/mk/ukim/finki/wp/internships/service/impl/InternshipServiceImpl.java b/backend/src/main/java/mk/ukim/finki/wp/internships/service/impl/InternshipServiceImpl.java index 4e2c3cc..8fac84e 100644 --- a/backend/src/main/java/mk/ukim/finki/wp/internships/service/impl/InternshipServiceImpl.java +++ b/backend/src/main/java/mk/ukim/finki/wp/internships/service/impl/InternshipServiceImpl.java @@ -114,14 +114,21 @@ public class InternshipServiceImpl implements InternshipService { public void save(String studentIndex, String companyId, String description) { Company company = companyRepository.findById(companyId) .orElseThrow(() -> new IllegalArgumentException("Invalid company ID.")); + Student student = studentRepository.findByIndex(studentIndex); if (student == null) { throw new IllegalArgumentException("Invalid student index."); } - // TODO: COORDINATOR LOGIC + Professor coordinator = professorRepository.findById("danco.davcev").orElseThrow(() -> new IllegalArgumentException("Invalid professor ID.")); + + if(studentIndex.endsWith("1") || studentIndex.endsWith("2") || studentIndex.endsWith("3")) { + coordinator = professorRepository.findById("vlatko.spasev").orElseThrow(() -> new IllegalArgumentException("Invalid professor ID.")); + } + else if(studentIndex.endsWith("4") || studentIndex.endsWith("5") || studentIndex.endsWith("6")){ + coordinator = professorRepository.findById("vlado.spiridonov").orElseThrow(() -> new IllegalArgumentException("Invalid professor ID.")); + } - Professor coordinator = professorRepository.findByEmail("danco.davcev@finki.ukim.mk"); if (coordinator == null) { throw new IllegalArgumentException("Coordinator not found."); } diff --git a/backend/src/main/java/mk/ukim/finki/wp/internships/web/StudentController.java b/backend/src/main/java/mk/ukim/finki/wp/internships/web/StudentController.java index da3d650..8ed8b39 100644 --- a/backend/src/main/java/mk/ukim/finki/wp/internships/web/StudentController.java +++ b/backend/src/main/java/mk/ukim/finki/wp/internships/web/StudentController.java @@ -43,8 +43,7 @@ public class StudentController { Model model) { Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); - //String studentIndex = authentication.getName(); - String studentIndex = "213051"; + String studentIndex = authentication.getName(); Student student = studentService.getStudentByIndex(studentIndex); Page<Internship> internshipsPage = internshipService.list(pageNum, results, status, professorName, student); @@ -62,9 +61,9 @@ public class StudentController { public String showDetails (@PathVariable Long internshipId, Model model) { - // Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); - //String studentIndex = authentication.getName(); - Student student = this.studentService.getStudentByIndex("213051"); + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + String studentIndex = authentication.getName(); + Student student = this.studentService.getStudentByIndex(studentIndex); Internship internship = this.internshipService.findById(internshipId); Professor professor = internship.getCoordinator(); @@ -94,9 +93,8 @@ public class StudentController { @GetMapping("/add") public String showAdd(Model model) { - Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); - //String studentIndex = authentication.getName(); - String studentIndex = "213051"; + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + String studentIndex = authentication.getName(); Student student = studentService.getStudentByIndex(studentIndex); model.addAttribute("student", student); @@ -108,8 +106,7 @@ public class StudentController { @GetMapping("/{internshipId}/addWeek") public String showAddWeek(@PathVariable Long internshipId, Model model) { Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); - //String studentIndex = authentication.getName(); - String studentIndex = "213051"; + String studentIndex = authentication.getName(); Student student = studentService.getStudentByIndex(studentIndex); model.addAttribute("student", student); @@ -126,8 +123,7 @@ public class StudentController { Model model) { try { Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); - //String studentIndex = authentication.getName(); - String studentIndex = "213051"; + String studentIndex = authentication.getName(); this.internshipService.save(studentIndex,companyId,description); return "redirect:/student-internships"; } catch (Exception e) { @@ -145,8 +141,7 @@ public class StudentController { Model model) { try { Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); - //String studentIndex = authentication.getName(); - String studentIndex = "213051"; + String studentIndex = authentication.getName(); this.internshipWeekService.create(startDate, endDate, internshipId, description); return "redirect:/student-internships/{internshipId}"; } catch (Exception e) { @@ -158,9 +153,9 @@ public class StudentController { @GetMapping("/edit/{id}") public String showEdit(@PathVariable Long id, Model model) { - // Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); - //String studentIndex = authentication.getName(); - Student student = this.studentService.getStudentByIndex("213051"); + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + String studentIndex = authentication.getName(); + Student student = this.studentService.getStudentByIndex(studentIndex); Internship internship = this.internshipService.findById(id); Professor professor = internship.getCoordinator(); -- GitLab