Skip to content

Update library UI to conform to MVP release requirements#136

Open
RyanCheung555 wants to merge 1 commit intomainfrom
ryan/mvp-library
Open

Update library UI to conform to MVP release requirements#136
RyanCheung555 wants to merge 1 commit intomainfrom
ryan/mvp-library

Conversation

@RyanCheung555
Copy link
Contributor

@RyanCheung555 RyanCheung555 commented Mar 20, 2026

Overview

  • Added images for each library
  • Don't show detailed sheet content anymore for library

Changes Made

  • Hard-coded images for each library
  • Removed incorrect/irrelavent "library" locations
  • Direct user to route screen instead of showing detailed sheet content screen without about section/hours section (synced with IOS)

Test Coverage

  • Ecosystem build on medium phone, check out library tab (images are the main feature)

Next Steps

  • Use correct information from an updated backend (when it is implemented)

Screenshots

Library Implementation Showcase
library_showcase.webm

Summary by CodeRabbit

  • New Features

    • Library cards in the ecosystem view now display with customized placeholder images.
  • Refactor

    • Updated library rendering and navigation in the ecosystem bottom sheet.
    • Refined library filtering and favorites management to exclude certain libraries from display.

…o route when clicked instead of empty detail screen
@coderabbitai
Copy link

coderabbitai bot commented Mar 20, 2026

📝 Walkthrough

Walkthrough

This change introduces dynamic library card state management by adding a new LibraryCardUiState data class and libraryCardsFlow StateFlow in the ViewModel. Libraries are filtered to exclude specific locations and mapped with custom placeholder images, then the state flow is threaded through the HomeScreen to the EcosystemBottomSheetContent component for rendering library favorites and lists with API response handling.

Changes

Cohort / File(s) Summary
Library Card State Management
app/src/main/java/com/cornellappdev/transit/ui/viewmodels/HomeViewModel.kt
Added libraryCardsFlow StateFlow that filters excluded libraries and maps them to LibraryCardUiState with placeholder resource overrides. Introduced new LibraryCardUiState data class, exclusion logic via excludedLibraryLocations, and libraryImageOverridesByLocation mapping. Updated staticPlacesFlow and favorites filtering to exclude certain library places. Changed EcosystemFavoritesUiState.libraryByPlace to libraryCardByPlace mapping Library to LibraryCardUiState.
Data Flow Integration
app/src/main/java/com/cornellappdev/transit/ui/screens/HomeScreen.kt
Collects libraryCardsFlow from ViewModel and passes it as libraryCardsApiResponse parameter to EcosystemBottomSheetContent.
Library Card UI Rendering
app/src/main/java/com/cornellappdev/transit/ui/components/home/EcosystemBottomSheetContent.kt
Added libraryCardsApiResponse: ApiResponse<List<LibraryCardUiState>> parameter and threaded through BottomSheetFilteredContent and libraryList function. Updated library list rendering to use LibraryCardUiState.placeholderRes and extract data from LibraryCardUiState.library. Changed navigation behavior to use navigateToPlace() instead of onDetailsClick(). Updated favorites rendering to use libraryCardByPlace instead of libraryByPlace.

Sequence Diagram

sequenceDiagram
    participant Repo as Repository
    participant VM as HomeViewModel
    participant Screen as HomeScreen
    participant Sheet as EcosystemBottomSheetContent
    participant UI as Library Card UI

    Repo->>VM: libraryFlow emits List<Library>
    VM->>VM: Filter excluded libraries
    VM->>VM: Map to LibraryCardUiState<br/>(with placeholderRes)
    VM->>Screen: libraryCardsFlow StateFlow<br/>(ApiResponse<List<LibraryCardUiState>>)
    Screen->>Screen: collectAsStateWithLifecycle()
    Screen->>Sheet: Pass libraryCardsApiResponse
    Sheet->>Sheet: Render favorites via<br/>libraryCardByPlace
    Sheet->>Sheet: Render list via<br/>libraryList function
    Sheet->>UI: RoundedImagePlaceCard<br/>(library, placeholderRes)
    UI->>Screen: navigateToPlace(library.toPlace())
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

🐰 Through hopping bytes, the cards now flow,
Libraries mapped with placeholders aglow,
Exclusions filtered by location's call,
StateFlow threads them through it all,
A bundled dance of state and place,
Cards rendered with picture-perfect grace! 🎨

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 25.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and specifically describes the main change: updating library UI to meet MVP release requirements, which aligns with the core changes across three files.
Description check ✅ Passed The description covers most required sections with clear explanations of changes, test coverage, and next steps. However, it lacks detailed technical depth about parameter additions and API response handling.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch ryan/mvp-library
📝 Coding Plan
  • Generate coding plan for human review comments

Comment @coderabbitai help to get the list of available commands and usage tips.

Tip

You can disable the changed files summary in the walkthrough.

Disable the reviews.changed_files_summary setting to disable the changed files summary in the walkthrough.

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Updates the Home ecosystem “Libraries” UI to align with MVP requirements by introducing per-library placeholder images, filtering out unwanted library entries, and routing users to the route screen instead of showing the detailed bottom sheet content for libraries.

Changes:

  • Added LibraryCardUiState and a libraryCardsFlow to provide UI-ready library data with hard-coded drawable placeholders and excluded-library filtering.
  • Updated ecosystem bottom sheet to render library cards using the new UI state (including per-library images) and to navigate directly to the route screen on library tap.
  • Added a new drawable asset for Mann Library.

Reviewed changes

Copilot reviewed 3 out of 16 changed files in this pull request and generated 3 comments.

File Description
app/src/main/res/drawable/library_img_mann_library.jpg Adds a new library image asset used as a placeholder for Mann Library.
app/src/main/java/com/cornellappdev/transit/ui/viewmodels/HomeViewModel.kt Introduces LibraryCardUiState, libraryCardsFlow, image override mapping, and excluded-library filtering applied to libraries and favorites.
app/src/main/java/com/cornellappdev/transit/ui/screens/HomeScreen.kt Plumbs libraryCardsFlow into the bottom sheet content.
app/src/main/java/com/cornellappdev/transit/ui/components/home/EcosystemBottomSheetContent.kt Switches library rendering to LibraryCardUiState, uses per-library placeholder images, and navigates to route options on library selection.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +54 to +66
val libraryCardsFlow: StateFlow<ApiResponse<List<LibraryCardUiState>>> =
routeRepository.libraryFlow.map { response ->
when (response) {
is ApiResponse.Success -> {
ApiResponse.Success(
response.data
.filterNot { it.isExcludedLibrary() }
.map { it.toLibraryCardUiState() }
)
}
is ApiResponse.Pending -> ApiResponse.Pending
is ApiResponse.Error -> ApiResponse.Error
}
Copy link

Copilot AI Mar 20, 2026

Choose a reason for hiding this comment

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

libraryCardsFlow repeats the same excluded-library filtering logic that also exists in withExcludedLibrariesRemoved()/Library.isExcludedLibrary(). Consider reusing the shared helper when building libraryCardsFlow so the exclusion behavior stays centralized.

Copilot uses AI. Check for mistakes.
Comment on lines 66 to 70
activeFilter: FilterState,
onFilterClick: (FilterState) -> Unit,
staticPlaces: StaticPlaces,
libraryCardsApiResponse: ApiResponse<List<LibraryCardUiState>>,
favorites: Set<Place>,
Copy link

Copilot AI Mar 20, 2026

Choose a reason for hiding this comment

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

The KDoc above EcosystemBottomSheetContent doesn’t mention the new libraryCardsApiResponse parameter, and the staticPlaces description implies libraries come only from staticPlaces. Please update the KDoc to reflect the new source of library UI state.

Copilot uses AI. Check for mistakes.
staticPlaces: StaticPlaces,
libraryCardsApiResponse: ApiResponse<List<LibraryCardUiState>>,
navigateToPlace: (Place) -> Unit,
navigateToDetails: (DetailedEcosystemPlace) -> Unit,
Copy link

Copilot AI Mar 20, 2026

Choose a reason for hiding this comment

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

libraryList still takes navigateToDetails, but it’s unused because the call is commented out. Consider removing the parameter (and corresponding call sites) or renaming it to _navigateToDetails until it’s needed again, to avoid unused-parameter warnings and confusion about expected behavior.

Suggested change
navigateToDetails: (DetailedEcosystemPlace) -> Unit,
_navigateToDetails: (DetailedEcosystemPlace) -> Unit,

Copilot uses AI. Check for mistakes.
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (1)
app/src/main/java/com/cornellappdev/transit/ui/viewmodels/HomeViewModel.kt (1)

466-515: Match overrides and exclusions on a stable key, not location.

These tables currently depend on location.trim().lowercase(), so a backend rename or punctuation tweak will silently pick the wrong placeholder or stop excluding the intended library. Given the planned backend refresh, this is safer if it runs on a stable identifier before the model is converted to Place.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/src/main/java/com/cornellappdev/transit/ui/viewmodels/HomeViewModel.kt`
around lines 466 - 515, The override/exclusion logic uses mutable location
strings causing fragility; change all maps and checks to use a stable identifier
(e.g., Library.id or Place.id) instead of location. Replace
libraryImageOverridesByLocation and excludedLibraryLocations keys to the stable
id values; update Library.isExcludedLibrary(), Place.isExcludedLibraryPlace(),
Library.toLibraryCardUiState() and the
ApiResponse.withExcludedLibrariesRemoved() filter to reference that stable id
field (normalizing only if needed) so lookups use the stable id property rather
than location.trim().lowercase().
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@app/src/main/java/com/cornellappdev/transit/ui/components/home/EcosystemBottomSheetContent.kt`:
- Around line 582-587: When handling libraryCardsApiResponse, don't render
nothing for ApiResponse.Pending and ApiResponse.Error: update the when branches
for libraryCardsApiResponse to display a loading indicator when the state is
ApiResponse.Pending (reuse the existing spinner/composable used elsewhere), and
display an "unavailable" error state when the state is ApiResponse.Error (show a
message and optional retry action or placeholder composable). Specifically
modify the ApiResponse.Pending branch to call the existing spinner composable
and the ApiResponse.Error branch to call or create a lightweight
librariesUnavailable/error placeholder (with a retry lambda that re-fetches the
library cards), referencing libraryCardsApiResponse, ApiResponse.Pending and
ApiResponse.Error to locate the change.

In `@app/src/main/java/com/cornellappdev/transit/ui/viewmodels/HomeViewModel.kt`:
- Around line 168-170: Centralize filtering of excluded libraries by extracting
a helper that removes items where isExcludedLibraryPlace() is true and apply it
to the source favorites flow in HomeViewModel (e.g., replace direct uses of
favorites / favoritesFlow with a filteredFavoritesFlow); then update derived
states that currently build from raw favorites — such as
filteredSortedFavorites, ecosystemFavoritesUiState, and where
SearchBarUIState.RecentAndFavorites is constructed — to consume this
filteredFavoritesFlow so excluded library favorites are removed before any UI
state is created.

---

Nitpick comments:
In `@app/src/main/java/com/cornellappdev/transit/ui/viewmodels/HomeViewModel.kt`:
- Around line 466-515: The override/exclusion logic uses mutable location
strings causing fragility; change all maps and checks to use a stable identifier
(e.g., Library.id or Place.id) instead of location. Replace
libraryImageOverridesByLocation and excludedLibraryLocations keys to the stable
id values; update Library.isExcludedLibrary(), Place.isExcludedLibraryPlace(),
Library.toLibraryCardUiState() and the
ApiResponse.withExcludedLibrariesRemoved() filter to reference that stable id
field (normalizing only if needed) so lookups use the stable id property rather
than location.trim().lowercase().

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: d96bd720-d94b-4597-a205-124e9890a74d

📥 Commits

Reviewing files that changed from the base of the PR and between 5e4023c and 92ca9c0.

⛔ Files ignored due to path filters (13)
  • app/src/main/res/drawable/library_img_africana_studies.jpeg is excluded by !**/*.jpeg
  • app/src/main/res/drawable/library_img_carpenter_hall.jpg is excluded by !**/*.jpg
  • app/src/main/res/drawable/library_img_clark_hall.jpg is excluded by !**/*.jpg
  • app/src/main/res/drawable/library_img_comstock_hall.jpg is excluded by !**/*.jpg
  • app/src/main/res/drawable/library_img_ives_hall.jpg is excluded by !**/*.jpg
  • app/src/main/res/drawable/library_img_lincoln_hall.jpg is excluded by !**/*.jpg
  • app/src/main/res/drawable/library_img_malott_hall.jpg is excluded by !**/*.jpg
  • app/src/main/res/drawable/library_img_mann_library.jpg is excluded by !**/*.jpg
  • app/src/main/res/drawable/library_img_myron_taylor_hall.jpg is excluded by !**/*.jpg
  • app/src/main/res/drawable/library_img_rand_hall.jpg is excluded by !**/*.jpg
  • app/src/main/res/drawable/library_img_sage_hall.jpeg is excluded by !**/*.jpeg
  • app/src/main/res/drawable/library_img_statler_hall.jpg is excluded by !**/*.jpg
  • app/src/main/res/drawable/library_img_vet_center.jpg is excluded by !**/*.jpg
📒 Files selected for processing (3)
  • app/src/main/java/com/cornellappdev/transit/ui/components/home/EcosystemBottomSheetContent.kt
  • app/src/main/java/com/cornellappdev/transit/ui/screens/HomeScreen.kt
  • app/src/main/java/com/cornellappdev/transit/ui/viewmodels/HomeViewModel.kt

Comment on lines +582 to 587
when (libraryCardsApiResponse) {
is ApiResponse.Error -> {
}

is ApiResponse.Pending -> {
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Don't leave the libraries tab blank while loading or after a failure.

Both branches render nothing, so a slow or failed fetch is indistinguishable from “there are no libraries.” At minimum, the Pending case should show the existing spinner, and the Error case should show some unavailable state instead of an empty list.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@app/src/main/java/com/cornellappdev/transit/ui/components/home/EcosystemBottomSheetContent.kt`
around lines 582 - 587, When handling libraryCardsApiResponse, don't render
nothing for ApiResponse.Pending and ApiResponse.Error: update the when branches
for libraryCardsApiResponse to display a loading indicator when the state is
ApiResponse.Pending (reuse the existing spinner/composable used elsewhere), and
display an "unavailable" error state when the state is ApiResponse.Error (show a
message and optional retry action or placeholder composable). Specifically
modify the ApiResponse.Pending branch to call the existing spinner composable
and the ApiResponse.Error branch to call or create a lightweight
librariesUnavailable/error placeholder (with a retry lambda that re-fetches the
library cards), referencing libraryCardsApiResponse, ApiResponse.Pending and
ApiResponse.Error to locate the change.

Comment on lines 168 to +170
val filteredSortedFavorites = favorites.asSequence()
.filter { allowedTypes.isEmpty() || it.type in allowedTypes }
.filterNot { it.isExcludedLibraryPlace() }
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Apply the exclusion before favorites reach any UI surface.

Line 170 only strips excluded libraries out of ecosystemFavoritesUiState. This same ViewModel still feeds raw favorites into SearchBarUIState.RecentAndFavorites, so previously-favorited excluded libraries will keep showing up in search suggestions while disappearing from the ecosystem sheet. Centralize this filter once instead of hiding them in just one derived state.

Possible extraction
+private fun Set<Place>.withoutExcludedLibraryPlaces(): Set<Place> =
+    filterNot { it.isExcludedLibraryPlace() }.toSet()

Then reuse that helper both here and anywhere RecentAndFavorites is built from favoritesFlow.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/src/main/java/com/cornellappdev/transit/ui/viewmodels/HomeViewModel.kt`
around lines 168 - 170, Centralize filtering of excluded libraries by extracting
a helper that removes items where isExcludedLibraryPlace() is true and apply it
to the source favorites flow in HomeViewModel (e.g., replace direct uses of
favorites / favoritesFlow with a filteredFavoritesFlow); then update derived
states that currently build from raw favorites — such as
filteredSortedFavorites, ecosystemFavoritesUiState, and where
SearchBarUIState.RecentAndFavorites is constructed — to consume this
filteredFavoritesFlow so excluded library favorites are removed before any UI
state is created.

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