Improve Study Planner task visibility and delayed goal rescheduling#16
Improve Study Planner task visibility and delayed goal rescheduling#16
Conversation
There was a problem hiding this comment.
Pull request overview
This PR enhances the Study Planner with two main features: improved task visibility on calendar dates (showing tasks with linked goals even when they wouldn't otherwise surface based on deadline logic), and a new "Re-plan" feature that lets users manually reschedule delayed study goals to appear on today's date as a one-shot operation. Additionally, it simplifies the missed recurring occurrence detection to only look back one day (yesterday), marks overdue non-recurring tasks as DELAYED on startup, and auto-transitions tasks from OPEN to IN_PROGRESS when a goal is created for them.
Changes:
- Added
replanned_for_datecolumn tostudy_goalstable to support one-shot manual rescheduling of delayed goals, with corresponding entity, query, and service layer changes. - Enhanced
getTasksForDateto include IN_PROGRESS/DELAYED tasks that have a goal planned for the queried date (even if their deadline doesn't match), and simplified missed recurring occurrence detection to check only yesterday. - Added startup DELAYED-marking for overdue tasks and OPEN→IN_PROGRESS auto-transition when a study goal is created for a task.
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
src/main/resources/schema.sql |
Adds replanned_for_date migration via ALTER TABLE for existing databases |
src/main/java/.../StudyPlannerPanel.java |
Adds "Re-plan a Delayed Goal" UI section with ComboBox and button |
src/main/java/.../StudySyncUI.java |
Calls markDelayedTasks() on app startup |
src/main/java/.../TaskService.java |
Adds once-per-day guard to markDelayedTasks, goal-based task inclusion in getTasksForDate, and simplifies missed occurrence detection to yesterday-only |
src/main/java/.../StudyService.java |
Adds OPEN→IN_PROGRESS auto-transition, getDelayedGoalsForReplanning(), replanGoalForToday(), and skips replanned goals in delay processing |
src/main/java/.../StudyGoal.java |
Adds replannedForDate field, updated constructors, row mapper, save SQL, and all queries to handle replanned goals; adds findDelayedAndNotReplanned() |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
… after processing
Each tab in the calendar Day Details dialog returned a plain VBox, so content was clipped when it exceeded the tab height. Wrap every tab's content in a ScrollPane with fitToWidth so users can scroll through long lists of goals, sessions, and tasks.
The re-plan ComboBox used only a StringConverter, which can leave popup list cells blank in JavaFX. Replace with explicit setCellFactory and setButtonCell so each delayed goal renders its task title, description, and delay duration correctly.
Previously achieved goals simply vanished from the UI. Now they appear in a collapsible 'Completed (N)' section below the active goals, with strikethrough text and a green-tinted background. Users can un-check a completed goal to move it back to active. Applies to both task-linked and unlinked goal panels.
Track expanded task IDs in a Set so that when updateTasksDisplay() rebuilds the task list (e.g. after checking/unchecking a goal), cards that were previously expanded remain open with their goals panel visible.
POSTPONED non-recurring tasks were included alongside DELAYED tasks in the daily planner. Remove POSTPONED from the isPending filter in getTasksForDate() so only OPEN, IN_PROGRESS, and DELAYED tasks appear. CANCELLED was already excluded. Goal-linking (getActiveTasks) already returns only OPEN/IN_PROGRESS, so no change needed there.
Add a toolbar with Sort (Status, Priority, Deadline, Title) and Group (None, Status, Category) dropdowns above the task list. Sorting and grouping are applied on each display refresh, with group headers rendered as labeled separators when grouping is active.
The early return when tasks were empty prevented the unlinked goals section (and re-plan section) from rendering. Convert the early return into an if/else so the 'No tasks' message still shows but the rest of the display continues to render regardless.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 7 out of 7 changed files in this pull request and generated 16 comments.
Comments suppressed due to low confidence (1)
src/main/java/com/studysync/domain/service/TaskService.java:197
markDelayedTasks()filters overdue tasks but doesn’t exclude recurring tasks. SinceapplyBusinessRules()intentionally won’t mark recurring tasks as DELAYED, recurring tasks can still be included, unnecessarily saved, and counted as “updated”. Add a!task.isRecurring()filter (or only persist tasks whose status actually changed).
List<Task> delayedTasks = Task.findAll().stream()
.filter(task -> task.getStatus() != TaskStatus.COMPLETED &&
task.getStatus() != TaskStatus.CANCELLED &&
task.getDeadline() != null &&
task.getDeadline().isBefore(today) &&
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
src/main/java/com/studysync/presentation/ui/components/StudyPlannerPanel.java
Outdated
Show resolved
Hide resolved
src/main/java/com/studysync/presentation/ui/components/StudyPlannerPanel.java
Outdated
Show resolved
Hide resolved
Avoid repeated Task.findById calls during ComboBox cell rendering by preloading task titles once in buildReplanSection and formatting from cached data.
All four replanned_for_date query clauses (findByDate, findByDateIncludingDelayed, findByTaskIdForDate, findUnlinkedForDate) filtered with achieved = FALSE, causing completed replanned goals to vanish from their replanned date. Remove the achieved constraint so replanned goals remain visible in the Completed section after being checked off.
It now correctly excludes POSTPONED tasks, explaining the new approach correctly. Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Task.findAll() was already called at the top of the method, so the per-goal Task.findById lookups in the goal-linking pass were redundant DB round-trips. Build a Map<String, Task> from the initial findAll result and use it for O(1) lookups instead.
Inject DateTimeService and replace all 9 occurrences of LocalDate.now() so that StudyService uses the same date source as the UI. Prevents mismatches around midnight or in tests where DateTimeService may provide a different date.
The missed-occurrence block was inside the else branch of the tasks.isEmpty() check, so it never ran on task-free days. Move it outside the conditional so carry-forward items render regardless. Also fix indentation of the else body.
Wrap the check-then-set of lastDelayedTasksProcessedDate in TaskService.markDelayedTasks() and lastDelayProcessingDate in StudyService.ensureDelayedGoalsProcessedToday() with synchronized blocks so concurrent callers cannot both pass the guard.
Remove Optional, Arrays, and StringConverter imports that are no longer referenced.
The Goals tab refresh path in createGoalsTab called parentTab.setContent() without scrollWrap, losing scrollability after adding a goal.
In StudyService.addStudyGoal, check the boolean returned by Task.updateStatus and log a warning on failure instead of unconditionally logging success. Remove unused linkedTask and parentPanel parameters from buildCompletedGoalsSection and update both call sites.
) Study Planner: task visibility, delayed goal rescheduling & UI improvements Closes #18, #19, #20 Features: - Add one-shot delayed goal rescheduling to Study Planner (re-plan a delayed goal for today) - Show completed goals in a collapsible section instead of hiding them - Preserve task card expand state across goal edits - Add sort (Status/Priority/Deadline/Title) and group (None/Status/Category) controls to Today's Tasks Bug fixes: - Make Day Details dialog tabs scrollable (wrap each tab in ScrollPane) - Fix re-plan ComboBox rendering blank items (use explicit cell factories) - Exclude POSTPONED tasks from daily Study Planner view - Always show unlinked goals and missed occurrences even when no tasks are scheduled - Include achieved replanned goals on their replanned date - Wrap Goals tab content in ScrollPane on refresh path - Use DateTimeService instead of LocalDate.now() in StudyService for date consistency - Make once-per-day delay-processing guards thread-safe - Check Task.updateStatus return value and log on failure - Align study planner task visibility with goal scheduling rules - Add replanned_for_date to CREATE TABLE and fix guard assignment ordering Performance: - Cache task titles for delayed-goal ComboBox rendering (avoid DB calls in cell render) - Eliminate N+1 Task.findById calls in getTasksForDate (reuse existing findAll result) Cleanup: - Remove unused imports (Optional, Arrays, StringConverter) - Use short names for ArrayList and Set in TaskService - Remove unnecessary fully-qualified TaskStatus references - Remove unused parameters from buildCompletedGoalsSection --- Co-authored-by: geokoko <geokoko@users.noreply.github.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Study Planner — Task Visibility, Delayed Goal Rescheduling & UI Improvements
New features:
Users can now manually reschedule a delayed, unachieved study goal to appear on today's date as a one-shot operation via a new "Re-plan" section (backed by a replanned_for_date column on study_goals). Achieved goals no longer disappear; they show in a collapsible "Completed (N)" section with strikethrough styling and can be un-checked to reactivate. A sort/group toolbar above Today's Tasks lets users sort by Status, Priority, Deadline, or Title, and group by Status or Category.
Bug fixes:
Calendar View Day Details tabs are now wrapped in a ScrollPane so content is scrollable when it overflows (#20). The re-plan ComboBox now renders items correctly by using explicit cell factories instead of a StringConverter-only approach (#19). Unlinked goals are now always visible even on days with no scheduled tasks.
Behaviour changes:
POSTPONED tasks are excluded from the daily planner alongside CANCELLED ones. Expanded task goal panels survive UI rebuilds. IN_PROGRESS and DELAYED tasks with a study goal planned for a date surface in the planner even if their deadline wouldn't otherwise bring them up. Overdue non-recurring tasks are marked DELAYED on startup, and creating a study goal for an OPEN task automatically moves it to IN_PROGRESS.