Skip to content

Conversation

@hermannakos
Copy link
Collaborator

Test plan

Setup

  1. Ensure you have a course with:
    • Upcoming assignments with due dates
    • Recent grade changes
    • (Optional) Weighted assignment groups for testing weight display

Testing the Forecast Widget

  1. Navigate to the Dashboard
  2. Verify the Forecast Widget is displayed showing:
    • Upcoming assignments for the current week
    • Recent grade changes
  3. Test week navigation:
    • Tap next/previous week arrows
    • Verify assignments update correctly with debounced loading state
  4. Test assignment interaction:
    • Tap on an assignment
    • Verify it routes to the assignment details
  5. Test grade changes section:
    • Verify recent grade changes are displayed with scores
  6. Test widget configuration:
    • Open widget settings
    • Change background color
    • Verify the widget updates with the selected theme
  7. Test assignment weight display (if course uses weighted groups):
    • Verify weight percentage is shown for assignments in weighted groups
    • Verify weight calculation respects drop rules (drop_lowest, drop_highest, never_drop)

Testing in Different Modes

  • Test in dark mode and light mode
  • Test in landscape orientation
  • Test on tablet layout

refs: MBL-19459
affects: Student

release note: Added Forecast Widget to the dashboard showing upcoming assignments, recent grade changes, and assignment weights for better academic planning.

Checklist

  • Tested in dark/light mode
  • Tested in landscape/tablet layout
  • Unit tests added for all new components
  • Product approval obtained

hermannakos and others added 20 commits December 15, 2025 12:25
Add Canvas API layer components:
- GradeChange model for audit grade change data
- AuditAPI interface for grade change audit endpoints
- Extend UserAPI with suspend methods for missing submissions

Add domain repositories:
- AssignmentRepository for missing assignments with depagination
- PlannerRepository for upcoming planner items with depagination
- AuditRepository for grade change audit data

Add use cases:
- LoadMissingAssignmentsUseCase for missing assignments
- LoadUpcomingAssignmentsUseCase for due assignments
- LoadRecentGradeChangesUseCase with filtering for latest version per assignment

Configure Hilt dependency injection in ApiModule and RepositoryModule.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Implements Phase 1: Widget Data Layer for the Forecast Widget.

Created data models and persistence:
- ForecastWidgetUiState: Defines ForecastSection enum, WeekPeriod, AssignmentItem, and main UI state
- ForecastWidgetDataStore: Persists week offset and selected section (nullable) using DataStore

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Implements Phase 2: ViewModel & State for the Forecast Widget.

Features:
- Week navigation with locale-aware week start day (Sunday for US, Monday for others)
- Section toggle handlers (Missing, Due, Recent Grades)
- Data loading for missing assignments, upcoming assignments, and recent grades
- Combines DataStore flows (week offset, selected section) with data flows
- Week period calculation with proper ISO week number
- Loading, error, and empty state handling
- Refresh capability

Data mapping:
- Missing assignments sorted by due date (oldest first)
- Upcoming assignments filtered by selected week period
- Recent grades from last 7 days sorted by graded date (newest first)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Implements Phase 3: UI Components for the Forecast Widget.

Created Composables:
- WeekNavigationHeader: Blue header with week period display and navigation arrows
- ForecastSegmentedControl: Custom 3-segment control for Missing/Due/Recent Grades
  with count badges and chevron icons that rotate 180° when selected
- AssignmentListItem: Assignment row with course color, icon, name, date, and
  optional grade weight chip
- ForecastWidget: Main widget composable integrating all components with loading,
  error, and empty states

Features:
- Week period navigation (previous/next week)
- Animated section expand/collapse
- Assignment list with dividers
- Shimmer loading states with proper styling
- Error state with retry
- Empty states per section
- Date formatting (Today, Tomorrow, full date)
- Material 3 components with proper theming

String Resources:
- Added 13 new strings to pandares/strings.xml for widget UI
- Includes titles, labels, error messages, and empty state messages

Bug Fixes:
- Fixed ViewModel compilation errors with PlannerItem property access
- Fixed Assignment.dueAt String to Date conversion
- Removed unnecessary safe calls on non-null types

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
… and integrate Forecast Widget

Replace the non-working Audit API (students lack permission) with GraphQL submissionsConnection API for fetching recent graded submissions. Implement pagination/depaging following existing patterns. Add client-side filtering by endTime in LoadRecentGradeChangesUseCase.

Key changes:
- Add RecentGradedSubmissionsQuery.graphql with pagination support
- Add RecentGradedSubmissionsManager with depaging logic
- Create GradedSubmission data model and SubmissionRepository
- Remove AuditAPI and audit repository (replaced with submission repository)
- Add ForecastWidgetRouter for assignment navigation
- Integrate ForecastWidget into DashboardScreen
- Add WIDGET_ID_FORECAST to default widgets list

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Add vertical dividers between segmented control sections
  - Dividers conditionally hidden when adjacent segment is selected
  - Improves visual separation and clarity
- Fix text and icon alignment in segment buttons
  - Center count text while positioning chevron at end
  - Changed from Row to Box layout for proper positioning
- Add week-based filtering for recent grades
  - GraphQL query now includes gradedAt field and gradeHidden filter
  - LoadRecentGradeChangesUseCase filters by start/end time
- Filter planner items to assignments only in upcoming section
  - Excludes calendar events and other non-assignment items
- Add card elevation to Forecast Widget
  - Matches elevation style of other dashboard widgets
- Improve loading state UI
  - Shows real week navigation header during load when available
  - Displays content shimmer when section is selected
- Optimize ViewModel initialization
  - Calculate and expose weekPeriod before data loading
  - Avoid duplicate data loads on initial week offset observe

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
…llWidth flag

- Refactor DashboardScreen from LazyVerticalStaggeredGrid to LazyColumn
- Remove isFullWidth parameter from WidgetMetadata and WidgetMetadataEntity
- Add database migration v2 → v3 to drop isFullWidth column
- Update WidgetDatabase version to 3
- Update EnsureDefaultWidgetsUseCase to remove isFullWidth from default widgets
- Update unit and instrumentation tests to reflect changes
- Widgets now handle their own multi-column layout internally

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Add smooth chevron rotation animation using animateFloatAsState
- Replace AnimatedVisibility with AnimatedContent inside AnimatedVisibility
- Animate height changes smoothly when switching between sections
- Prevent horizontal shrinking during collapse animation
- Use fade transitions for content changes

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Remove week offset from ForecastWidgetDataStore
- Keep week offset only in memory (resets to current week on app launch)
- Simplify navigation by updating offset directly in ViewModel
- Load all data (missing, upcoming, recent grades) on init

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Resolved merge conflict in DashboardScreen.kt by keeping LazyColumn
layout from feature branch and adding ForecastWidget case.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Add course field to Assignment model and include in missing submissions API
- Populate assignment icons using getAssignmentIcon and getIconForPlannerItem
- Populate course names from assignment.course, item.contextName, and submission.courseName
- Compute course colors in UI layer for config change support
- Clean up AssignmentListItem layout spacing and divider styling

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
…idget

- Add click handler to AssignmentListItem that routes to assignment details
- Use getFragmentActivity() extension to get FragmentActivity from context
- Pass assignment ID and course ID to router for navigation

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Add isLoadingItems field to track item loading separately from full widget loading
- Implement 300ms debounce for API calls when navigating between weeks
- Show immediate loading indicator while API calls are debounced
- Handle CancellationException to prevent error state during rapid navigation
- Display single shimmer item for loading state when section is expanded

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
…grade display

- Move Forecast Widget from student app to pandautils for code sharing
- Add ForecastConfig with backgroundColor setting
- Implement theme support using ThemedColor for dark/light mode
- Apply background color to Card, WeekNavigationHeader, and selected section
- Add grade display for Recent Grades section with formatting
- Create ForecastWidgetRouter interface for app-specific routing
- Add router implementations for student, teacher, and parent apps
- Fix color picker functionality in UpdateWidgetSettingUseCase

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
…istence

- Implement weight calculation for missing and upcoming assignments
- Calculate weights based on assignment group weighting with drop rules
- Add AssignmentWeightCalculator to handle complex grading rules
- Add LoadAssignmentGroupsUseCase to fetch assignment groups
- Extend AssignmentRepository to support assignment groups
- Display weight chips in UI matching Figma design
- Handle excused status for graded submissions
- Remove section persistence from ForecastWidget
- Auto-open missing section when assignments exist
- Delete ForecastWidgetDataStore as it's no longer needed

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Fix fully qualified name: import GradingRule instead of using full path
- Remove unused showGradeIndicator field from AssignmentItem
- Fix drop rules to only apply to graded assignments, not ungraded
  - Drop rules now correctly separate graded/ungraded assignments
  - Apply drop rules only to graded assignments using actual scores
  - Ungraded assignments always count in weight calculation
  - Matches Canvas LMS grade calculation behavior

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Rename `UpdateWidgetSettingUseCase` to `UpdateWidgetConfigUseCase` across the codebase
- Update `CustomizeDashboardViewModel` to handle the Forecast widget display name and use the renamed use case
- Add `gradingType` field to `GradedSubmission` model and populate it in `SubmissionRepositoryImpl`
- Update `ForecastSegmentedControl` colors to use themed resources instead of hardcoded `Color.White`
- Remove `WelcomeConfig` references from `ObserveWidgetConfigUseCase`
- Add `widget_weekly_summary` string resource for the Forecast widget title
- Update unit tests to reflect use case renaming

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Add unit tests for AssignmentWeightCalculator with all drop rules scenarios
- Add tests for LoadAssignmentGroupsUseCase and LoadMissingAssignmentsUseCase
- Add tests for LoadRecentGradeChangesUseCase with date filtering
- Add tests for AssignmentRepository operations
- Add tests for ObserveForecastConfigUseCase
- Update UpdateWidgetSettingUseCaseTest and ObserveWidgetConfigUseCaseTest to use WIDGET_ID_FORECAST
- Fix WidgetMetadataRepositoryTest to remove isFullWidth references
- Remove forecast widget implementation documentation

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
@github-actions
Copy link

github-actions bot commented Jan 13, 2026

🧪 Unit Test Results

✅ 📱 Student App

  • Tests: 1241 total, 0 failed, 0 skipped
  • Duration: 0.000s
  • Success Rate: 100%

✅ 🌅 Horizon

  • Tests: 449 total, 0 failed, 0 skipped
  • Duration: 33.315s
  • Success Rate: 100%

✅ 📦 Submodules

  • Tests: 2563 total, 0 failed, 0 skipped
  • Duration: 47.379s
  • Success Rate: 100%

📊 Summary

  • Total Tests: 4253
  • Failed: 0
  • Skipped: 0
  • Status: ✅ All tests passed!

Last updated: Tue, 13 Jan 2026 12:02:58 GMT

@github-actions
Copy link

📊 Code Coverage Report

⚠️ Student

  • PR Coverage: 43.47%
  • Master Coverage: 43.51%
  • Delta: -0.04%

⚠️ Teacher

  • PR Coverage: 25.61%
  • Master Coverage: 25.61%
  • Delta: -0.00%

⚠️ Pandautils

  • PR Coverage: 22.60%
  • Master Coverage: 22.91%
  • Delta: -0.30%

📈 Overall Average

  • PR Coverage: 30.56%
  • Master Coverage: 30.68%
  • Delta: -0.11%

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants