Skip to content

Conversation

@hermannakos
Copy link
Collaborator

@hermannakos hermannakos commented Nov 18, 2025

Implements a new Institutional Announcements Widget for the Student dashboard that displays account notifications with institutional branding.

Implementation Details

New Features

  • Institutional Announcements Widget - Displays up to 5 most recent announcements sorted by date
  • Account Branding - Shows institution logo with fallback to 3-letter abbreviation on brand-colored background
  • Icon Badges - Notification type indicators (warning, error, info, calendar, question) with solid icons
  • Horizontal Paging - Swipe through announcements with page indicators
  • Multi-Column Support - Adapts to tablet layouts with configurable columns
  • Widget Title - "Announcements (x)" format showing count of announcements

Architecture

  • Repository Layer - UserRepository for account data, AccountNotificationRepository for notifications
  • Use Case - LoadInstitutionalAnnouncementsUseCase combines data from both repositories, sorts by date, limits to 5
  • ViewModel - InstitutionalAnnouncementsViewModel with StateFlow-based UI state management
  • Widget - Jetpack Compose UI with Material Design 3 components

Design

  • Square logo with 8dp rounded corners (changed from circular)
  • Icon badge positioned at top-start corner with 8dp offset (50% overlap)
  • Solid icon variants with appropriate color tinting (warning=textWarning, error=textDanger, others=textInfo)
  • Widget hides when loading, on error, or when no announcements available
  • Announcement card shows: institution name, date/time, subject, message preview

Testing

  • 31 unit tests covering repository, use case, and view model layers
  • 9 instrumentation tests covering UI states, paging, clicks, and multi-column layout
  • All tests passing on Pixel 2 API 29 emulator

Test plan:

  1. Log in to Student app with an account that has institutional announcements configured
  2. Navigate to Dashboard
  3. Verify Institutional Announcements Widget appears between Course Invitations and Welcome widgets
  4. Verify widget title shows "Announcements (x)" where x is the number of announcements
  5. Verify institution logo is displayed as a square with rounded corners
  6. Verify icon badge appears at top-start corner of logo with appropriate color
  7. If multiple announcements exist, swipe left/right to view different announcements
  8. Verify page indicators appear and update when swiping
  9. Tap on an announcement to verify it opens the announcement details
  10. Test in landscape/tablet mode to verify multi-column layout
  11. Test with accounts that have no announcements - widget should not be displayed

refs: MBL-19457
affects: Student
release note: Students can now view institutional announcements on their dashboard

Checklist

  • Follow-up e2e test ticket created or not needed
  • Tested in dark mode
  • Tested in light mode
  • Test in landscape mode and/or tablet
  • A11y checked
  • Approve from product

hermannakos and others added 3 commits November 18, 2025 14:05
Adds institutional announcements widget to Student dashboard that displays
up to 5 recent institutional announcements in a carousel layout.

- Create AccountNotificationRepository with implementation
- Add InstitutionalAnnouncement domain model
- Implement LoadInstitutionalAnnouncementsUseCase (sorts by date, limits to 5)
- Create InstitutionalAnnouncementsWidget with carousel and pagination
- Integrate widget into dashboard with DashboardRouter navigation
- Add comprehensive unit tests for use case and ViewModel (14 tests)
- Widget hides when loading, empty, or error state
- Supports responsive grid layout (1-3 columns)

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

Co-Authored-By: Claude <[email protected]>
…go and comprehensive tests

- Add UserRepository interface and implementation for account data fetching
- Update LoadInstitutionalAnnouncementsUseCase to fetch institution name and logo URL
- Add logoUrl field to InstitutionalAnnouncement domain model
- Update widget UI to display square logo with rounded corners
- Add notification icon badge on top-start corner with half overlap
- Use brand color for institution name and fallback logo background
- Add solid icon variants (warning, calendar, question, info)
- Create comprehensive repository tests (AccountNotificationRepositoryTest, UserRepositoryTest)
- Update use case and view model tests with new dependencies
- All 31 tests passing

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

Co-Authored-By: Claude <[email protected]>
… and add screen tests

Updates the Institutional Announcements Widget UI design and adds
comprehensive instrumentation tests.

## Changes

### UI Design Updates
- Changed logo from circular to square with 8dp rounded corners
- Repositioned icon badge to top-start corner with 50% overlap (8dp offset)
- Updated widget title to "Announcements (x)" format with dynamic count
- Changed icon resources to solid variants for better visibility
- Updated WARNING icon tint from textDanger to textWarning

### Icon Resources
- Removed padding from ic_calendar_solid.xml while preserving structure
- Removed padding from ic_question_solid.xml while preserving structure
- Changed viewport from 16x16 to 13.333x13.333 and adjusted all coordinates

### Testing
- Added InstitutionalAnnouncementsWidgetTest.kt with 9 screen tests
- Tests cover loading/error/empty states, single/multiple announcements
- Tests verify paging, click callbacks, multi-column layout, and pager indicators
- Updated EnsureDefaultWidgetsUseCaseTest for new widget positioning

### Test Results
- All 9 instrumentation tests passing on Pixel 2 API 29 emulator
- All 4 EnsureDefaultWidgetsUseCaseTest unit tests passing
- All existing unit tests passing (31 total)

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

Co-Authored-By: Claude <[email protected]>
@github-actions
Copy link

github-actions bot commented Nov 18, 2025

📊 Code Coverage Report

⚠️ Student

  • PR Coverage: 42.49%
  • Master Coverage: 42.61%
  • Delta: -0.11%

✅ Teacher

  • PR Coverage: 25.44%
  • Master Coverage: 25.44%
  • Delta: +0.00%

⚠️ Pandautils

  • PR Coverage: 22.57%
  • Master Coverage: 22.59%
  • Delta: -0.02%

📈 Overall Average

  • PR Coverage: 30.17%
  • Master Coverage: 30.21%
  • Delta: -0.04%

Copy link

@claude claude bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR Review: Institutional Announcements Widget

Summary

This PR adds a new Institutional Announcements widget to the dashboard. The implementation includes proper repository layers, use cases, ViewModels, and comprehensive test coverage. Overall, the code follows good architectural patterns and Android best practices.

Positive Highlights

Excellent test coverage - Unit tests for repository, use case, ViewModel, and UI components
Clean architecture - Proper separation with repository, use case, and ViewModel layers
Compose best practices - Good use of state management and composables
Accessibility considerations - Includes proper content descriptions for icons
Proper dependency injection - Uses Hilt throughout (with one exception noted below)
Error handling - Handles loading, error, and empty states appropriately

Issues to Address

Code Quality

  • Missing @Inject annotation in UserRepositoryImpl.kt:24 - Constructor needs @Inject for Hilt dependency injection
  • Lazy initialization over injection in DashboardFragment.kt:35 - Consider using Hilt @Inject for the router instead of lazy initialization for better testability
  • Generic exception catching in InstitutionalAnnouncementsViewModel.kt:59 - Should log exceptions for debugging purposes

Maintainability

  • Magic number in LoadInstitutionalAnnouncementsUseCase.kt:47 - The hardcoded limit of 5 announcements should be extracted as a named constant
  • Unused imports in InstitutionalAnnouncementsWidget.kt:67 - Consider organizing imports to remove unused ones

Accessibility & Localization

  • Color contrast concern in InstitutionalAnnouncementsWidget.kt:201 - Using ThemePrefs.brandColor directly without considering contrast ratios could lead to accessibility issues
  • Locale handling in InstitutionalAnnouncementsWidget.kt:307 - Date formatting uses default locale which may not match Canvas user preferences

Security & Performance

No security vulnerabilities or significant performance concerns identified. The implementation:

  • Uses proper Kotlin coroutines for async operations
  • Implements efficient pagination with HorizontalPager
  • Properly limits data to 5 announcements
  • Uses appropriate caching strategies

Test Coverage

Comprehensive test coverage includes:

  • Repository layer tests (AccountNotificationRepositoryTest, UserRepositoryTest)
  • Use case tests (LoadInstitutionalAnnouncementsUseCaseTest)
  • ViewModel tests (InstitutionalAnnouncementsViewModelTest)
  • UI component tests (InstitutionalAnnouncementsWidgetTest)

Recommendation

The implementation is solid with only minor issues that should be addressed. The architectural approach is sound and the code is well-tested. Once the issues above are resolved, this will be ready to merge.

@hermannakos
Copy link
Collaborator Author

hermannakos commented Nov 18, 2025

Addressing the comments:

Already Fixed

Router injection - DashboardFragment.kt:35-36 already uses @Inject lateinit var router: DashboardRouter (not lazy initialization)

Not Needed

@Inject annotation in UserRepositoryImpl - This repository is manually provided in RepositoryModule, which is a valid pattern used throughout the codebase. The @Inject annotation is not needed when the binding is provided explicitly in a module.

Magic number (5 announcements limit) - This is the business requirement. Having a named constant for this single use case would be over-engineering.

Exception logging - The ViewModel catch block properly updates the UI state. Additional logging would be redundant with existing error tracking.

Brand color contrast - ThemePrefs.brandColor is used consistently throughout the app for institutional branding. This follows the existing pattern.

Date formatting locale - Locale.getDefault() is the correct approach for Android as it respects the user's device locale settings. Canvas user preferences don't override device locale for date formatting.

All tests passing (31 unit tests + 9 instrumentation tests).

Changes DashboardFragment to use proper Hilt dependency injection
for the router instead of lazy initialization for better testability.

Also updates DashboardScreenTest to provide mock router parameter.

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

Co-Authored-By: Claude <[email protected]>
@github-actions
Copy link

github-actions bot commented Nov 18, 2025

Student Install Page

Copy link
Contributor

@adamNagy56 adamNagy56 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

QA +1

@hermannakos hermannakos merged commit 60eb51d into master Nov 21, 2025
26 checks passed
@hermannakos hermannakos deleted the MBL-19457-institutional-announcements-widget branch November 21, 2025 12:12
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.

4 participants