From 6a8253736aa1b972aa192967b59e2eabd89801ff Mon Sep 17 00:00:00 2001 From: amercado9 Date: Sun, 12 Apr 2026 14:53:02 -0500 Subject: [PATCH] SectionsActive Weeks/setup done. --- .../section/SectionController.java | 20 +++ .../projectpulse/section/SectionService.java | 45 ++++++ .../projectpulse/section/SectionWeekInfo.java | 4 + src/frontend/src/apis/section/index.ts | 6 +- src/frontend/src/apis/section/types.ts | 1 + .../src/pages/sections/SectionDetail.vue | 146 +++++++++++++++++- 6 files changed, 214 insertions(+), 8 deletions(-) create mode 100644 src/backend/src/main/java/team/projectpulse/section/SectionWeekInfo.java diff --git a/src/backend/src/main/java/team/projectpulse/section/SectionController.java b/src/backend/src/main/java/team/projectpulse/section/SectionController.java index 030b7f1..96fb1ac 100644 --- a/src/backend/src/main/java/team/projectpulse/section/SectionController.java +++ b/src/backend/src/main/java/team/projectpulse/section/SectionController.java @@ -7,6 +7,7 @@ import org.springframework.web.bind.annotation.*; import team.projectpulse.common.Result; +import java.util.List; import java.util.Map; @RestController @@ -48,4 +49,23 @@ public Result> searchSections( public Result
findById(@PathVariable Long id) { return Result.success(sectionService.findById(id)); } + + /** + * UC-6: Get all computed weeks for a section (Monday–Sunday ranges). + * GET /api/v1/sections/{id}/weeks + */ + @GetMapping("/{id}/weeks") + public Result> getWeeks(@PathVariable Long id) { + return Result.success(sectionService.getWeeks(id)); + } + + /** + * UC-6: Save the admin's chosen active weeks for a section. + * POST /api/v1/sections/{id}/weeks + */ + @PostMapping("/{id}/weeks") + public Result setUpActiveWeeks(@PathVariable Long id, @RequestBody List activeWeeks) { + sectionService.setUpActiveWeeks(id, activeWeeks); + return Result.success("Active weeks updated.", null); + } } diff --git a/src/backend/src/main/java/team/projectpulse/section/SectionService.java b/src/backend/src/main/java/team/projectpulse/section/SectionService.java index c281562..510f92b 100644 --- a/src/backend/src/main/java/team/projectpulse/section/SectionService.java +++ b/src/backend/src/main/java/team/projectpulse/section/SectionService.java @@ -3,6 +3,15 @@ import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.time.DayOfWeek; +import java.time.LocalDate; +import java.time.temporal.TemporalAdjusters; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; @Service public class SectionService { @@ -23,4 +32,40 @@ public Section findById(Long id) { return sectionRepository.findById(id) .orElseThrow(() -> new SectionNotFoundException(id)); } + + /** + * UC-6: Compute all Monday–Sunday weeks between section start/end dates, + * marking each as active if its week number appears in section.activeWeeks. + */ + public List getWeeks(Long sectionId) { + Section section = findById(sectionId); + if (section.getStartDate() == null || section.getEndDate() == null) { + return List.of(); + } + Set activeSet = new HashSet<>( + section.getActiveWeeks() != null ? section.getActiveWeeks() : List.of() + ); + List weeks = new ArrayList<>(); + LocalDate weekStart = section.getStartDate() + .with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY)); + int num = 1; + while (!weekStart.isAfter(section.getEndDate())) { + LocalDate weekEnd = weekStart.with(DayOfWeek.SUNDAY); + String n = String.valueOf(num); + weeks.add(new SectionWeekInfo(n, weekStart.toString(), weekEnd.toString(), activeSet.contains(n))); + weekStart = weekStart.plusWeeks(1); + num++; + } + return weeks; + } + + /** + * UC-6: Replace the section's active weeks with the provided list. + */ + @Transactional + public void setUpActiveWeeks(Long sectionId, List activeWeeks) { + Section section = findById(sectionId); + section.setActiveWeeks(activeWeeks != null ? activeWeeks : List.of()); + sectionRepository.save(section); + } } diff --git a/src/backend/src/main/java/team/projectpulse/section/SectionWeekInfo.java b/src/backend/src/main/java/team/projectpulse/section/SectionWeekInfo.java new file mode 100644 index 0000000..293b166 --- /dev/null +++ b/src/backend/src/main/java/team/projectpulse/section/SectionWeekInfo.java @@ -0,0 +1,4 @@ +package team.projectpulse.section; + +public record SectionWeekInfo(String weekNumber, String monday, String sunday, boolean isActive) { +} diff --git a/src/frontend/src/apis/section/index.ts b/src/frontend/src/apis/section/index.ts index 1d0685b..d388b94 100644 --- a/src/frontend/src/apis/section/index.ts +++ b/src/frontend/src/apis/section/index.ts @@ -2,8 +2,8 @@ import request from '@/utils/request' import type { PaginationParams, Section, SectionSearchCriteria, CreateSectionResponse, FindSectionByIdResponse, SearchSectionByCriteriaResponse, - UpdateSectionResponse, AssignRubricToSectionResponse, SetUpActiveWeeksResponse, - SendEmailInvitationsResponse, InviteOrAddInstructorsResponse, + UpdateSectionResponse, AssignRubricToSectionResponse, GetSectionWeeksResponse, + SetUpActiveWeeksResponse, SendEmailInvitationsResponse, InviteOrAddInstructorsResponse, GetInstructorsResponse, RemoveInstructorResponse } from './types' @@ -16,6 +16,8 @@ export const createSection = (section: Section) => request.post request.put(`${API.SECTIONS}/${section.sectionId}`, section) export const assignRubricToSection = (sectionId: number, rubricId: number) => request.put(`${API.SECTIONS}/${sectionId}/rubrics/${rubricId}`) +export const getSectionWeeks = (sectionId: number) => + request.get(`${API.SECTIONS}/${sectionId}/weeks`) export const setUpActiveWeeks = (sectionId: number, activeWeeks: string[]) => request.post(`${API.SECTIONS}/${sectionId}/weeks`, activeWeeks) export const sendEmailInvitationsToStudents = (courseId: number, sectionId: number, emails: string[]) => diff --git a/src/frontend/src/apis/section/types.ts b/src/frontend/src/apis/section/types.ts index 3d2a71d..05636d1 100644 --- a/src/frontend/src/apis/section/types.ts +++ b/src/frontend/src/apis/section/types.ts @@ -23,6 +23,7 @@ export interface FindSectionByIdResponse { flag: boolean; code: number; message: export interface CreateSectionResponse { flag: boolean; code: number; message: string; data: Section } export interface UpdateSectionResponse { flag: boolean; code: number; message: string; data: Section } export interface AssignRubricToSectionResponse { flag: boolean; code: number; message: string } +export interface GetSectionWeeksResponse { flag: boolean; code: number; message: string; data: WeekInfo[] } export interface SetUpActiveWeeksResponse { flag: boolean; code: number; message: string } export interface SendEmailInvitationsResponse { flag: boolean; code: number; message: string } export interface InviteOrAddInstructorsResponse { diff --git a/src/frontend/src/pages/sections/SectionDetail.vue b/src/frontend/src/pages/sections/SectionDetail.vue index 510f424..45ea5ad 100644 --- a/src/frontend/src/pages/sections/SectionDetail.vue +++ b/src/frontend/src/pages/sections/SectionDetail.vue @@ -130,9 +130,21 @@ - - - Active Weeks + +
+ + Active Weeks +
+ + Set Up +
@@ -180,13 +192,78 @@ Section not found or failed to load. + + + + + + + Set Up Active Weeks + + + + +
+ +
+
+ No weeks available. Ensure the section has start and end dates configured. +
+ + + + + + + Week + Monday + Sunday + + + + + + + + Week {{ week.weekNumber }} + {{ week.monday }} + {{ week.sunday }} + + + +
+ + + + + {{ selectedWeeks.size }} of {{ allWeeks.length }} weeks selected + + + Cancel + + Save + + +
+