Skip to content

Implement the error screen designs for the various cases#206

Merged
MrPeterss merged 3 commits into
mainfrom
arielle/error-screens
Dec 3, 2025
Merged

Implement the error screen designs for the various cases#206
MrPeterss merged 3 commits into
mainfrom
arielle/error-screens

Conversation

@ArielleNu
Copy link
Copy Markdown
Contributor

Overview

These changes mainly revolve around adding in the error screen ui (takes a big portion of the lines added so pr might seem quite long), but in order to implement the Figma designs, some of the current workflows had to be reworked. Specifically, the CompareMenus logic and the MenuPickerSheetViewController had to be reworked because neither worked in the error state and both were supposed to work according to the design. Some key areas where error screens are implemented are the HomeViewController (when no eateries are being loaded or all of them have no items), MenusViewController (when no upcoming menus are being loaded), EateryModelController (when menu is not being loaded), and CompareMenusViewController (when at least one of the menus being compared produces an error screen).

Changes Made

HomeViewController

Add Inline Error UI for Empty States

  • Implemented a custom empty/error screen inside the collection view using buildEmptyStateView() to match the new error UI across the app.
  • Replaced generic blank states with the same red error icon, title, and message that was also implemented throughout Eatery Blue.

EateryModelController

Add full error-screen UI for networking failures

  • When Networking.default.loadEatery returns nil, the controller now:
    • Shows a MenuHeaderView with the correct selected day instead of always defaulting to “Closed Today.”
    • Adds the inline error block instead of spinner.
    • Ensures the “Change Date” button remains tappable.

addMenuFromState() now distinguishes between networking failure and “Closed Today” case

  • Networking failure: eatery == nil → show error screen for selected day
    • The header now correctly shows the day selected in the picker even with zero data.
    •      guard let event = selectedEvent else {
        
            guard let eat = eatery else {
                let selectedDay: Day
                if let picker = presentedViewController as? MenuPickerSheetViewController,
                   let day = picker.selectedCanonicalDay {
                    selectedDay = day
                } else {
                    selectedDay = Day()
                }
        
                addMenuHeaderView(
                    eateryId: eatery?.id,
                    title: selectedDay.toWeekdayString(),
                    subtitle: ""
                ) { [self] in presentMenuPicker() }
        
                addInlineErrorBlock(reportIssueEateryId: eatery.flatMap { Int64($0.id) })
                return
            }
      
  • Closed-today case preserved
    •      eateryId: eatery?.id,
           title: "Closed Today",
           subtitle: "Choose a different date to see menu"
       )
      

Treat “menu exists but has zero items” as empty

  • Added logic to treat categories with no items as “empty menu” and show the error block:
    if nonEmptyCategories.isEmpty {
        addInlineErrorBlock(...)
    }
    

Add support for selectedCanonicalDay

  • To support correct date selection when events are missing, the code now uses picker.selectedCanonicalDay
  • Ensures functionality of showing the correct weekday in the header, showing the error screen under it, and making the date picker functional regardless of data

MenusViewController

Menus automatically reload when the user changes filters or the selected day

  • After switching the meal period (Breakfast/Lunch/Dinner), toggling dietary filters, or selecting a new date, the controller now:
    • re-runs the networking fetch,
    • rebuilds the menu state,
    • refreshes the table view
  • Date switching now properly triggers a full refresh rather than only updating part of the UI.

MenuPickerSheet Folder

Keep the “Change Date” and “Show Menu” flows consistent

  • The “Show Menu” action no longer fails when a day has no menu.
  • The controller receives the selected day and refreshes itself normally, letting the error screen be shown in the correct, expected way.

Update how empty-menu days are handled in the controller

  • The controller now always updates the header to the selected day (or Closed Today), even when no menu or event exists.
  • The controller shows the proper red error block for that day when the networking error is present instead of defaulting to “Closed Today.”

Expose the selected day from the sheet

  • Added a public property (selectedCanonicalDay) so the controller can read the user-selected day.
  • Allows EateryModelController to know which day the user tapped even when no menus exist.

CompareMenus Folder

New delegates for menu-load failures

  • Added two new delegate protocols:
    • CompareMenusPageViewControllerDelegate
    • CompareMenusEateryViewControllerDelegate
  • These allow menu-loading failures inside sub-pages like CompareMenusEateryViewController to bubble up so the top-level CompareMenusViewController can show an inline error screen.

Update networking logic

  • Wrapped the initial data fetch in the sheet with: Task { [weak self] in ... } ensuring UI builds instantly, eateries load asynchronously, and the table updates after networking completes

Add inline error screen

  • Added a dedicated showInlineError() function to CompareMenusViewController
  • When any eatery page fails to load menus:
    • CompareMenusEateryViewControllerDelegate reports the error to its parent
    • CompareMenusPageViewController forwards the failure through CompareMenusPageViewControllerDelegate
    • CompareMenusViewController replaces the UI with the red error block and message

Test Coverage

  • Some cases that I tested included:
    • Changing eatery menu where networking succeeds to a day where it is closed
    • Changing eatery menu where networking fails to a day where it is closed
    • Eating the dining halls selected when comparing menus with the error screen showing
    • Toggling filters on the upcoming menus screen with error ui showing
    • No eateries returned
    • Eatery has no categories
    • Eatery has categories returned but the categories have no items

Screenshots

Compare Menus populated-compare-menus compare-menus
Eatery Model closed-today eatery
Upcoming Menus upcoming-menus

Copy link
Copy Markdown

@AdelynnWu AdelynnWu left a comment

Choose a reason for hiding this comment

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

Looks good to me. Great job!

Copy link
Copy Markdown
Contributor

@MrPeterss MrPeterss left a comment

Choose a reason for hiding this comment

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

Nice work! Looks great. Shoot me a DM/text when you want to merge and I'll bypass the branch restrictions, but next time try your best to keep it under 500 🙏

// Determine if this eatery has no retrievable menu
let hasMenu = (selectedEvent?.menu?.categories.isEmpty == false)
if !hasMenu {
delegate?.compareMenusEateryViewControllerDidFailToLoadMenu(self)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

nice! delegation!

@MrPeterss MrPeterss merged commit 38b21c4 into main Dec 3, 2025
4 of 5 checks passed
@MrPeterss MrPeterss deleted the arielle/error-screens branch December 3, 2025 19:08
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.

3 participants