[APP] Dish detail page#359
Conversation
Reviewer's GuideImplements a new dish details modal flow and supporting UI components/styles, refines typical dishes interactions and layout, and extends domain/navigation schemas with vegan flags and dish detail navigation. Sequence diagram for the new dish details modal flowsequenceDiagram
actor User
participant FoodCard
participant NavigationService
participant TypicalDishesModalPage
participant TypicalDishesList
participant DishItem
participant DishDetailsModalPage
participant useDishDetailsModalPageLogic
participant useGetTripById
participant useGetWikimediaDishImage
User ->> FoodCard: Pressable onPress handleOpenModal
FoodCard ->> NavigationService: toTypicalDishesModal tripId
NavigationService ->> TypicalDishesModalPage: push Modals.TypicalDishes with tripId
User ->> DishItem: Pressable onPress
DishItem ->> TypicalDishesList: onPress searchTerm
TypicalDishesList ->> TypicalDishesModalPage: onDishPress searchTerm
TypicalDishesModalPage ->> NavigationService: toDishDetailsModal { tripId, searchTerm }
NavigationService ->> DishDetailsModalPage: push Modals.DishDetails with params
DishDetailsModalPage ->> useDishDetailsModalPageLogic: useDishDetailsModalPageLogic
useDishDetailsModalPageLogic ->> useGetTripById: useGetTripById tripId
useDishDetailsModalPageLogic ->> useGetWikimediaDishImage: useGetWikimediaDishImage searchTerm
useGetTripById -->> useDishDetailsModalPageLogic: trip
useGetWikimediaDishImage -->> useDishDetailsModalPageLogic: { url, isLoading }
useDishDetailsModalPageLogic -->> DishDetailsModalPage: dishName, dishDescription, dishIngredients, isGlutenFree, isVegetarian, isVegan, image, imageIsLoading
User ->> DishDetailsModalPage: Tap close
DishDetailsModalPage ->> useDishDetailsModalPageLogic: handleClose
useDishDetailsModalPageLogic ->> NavigationService: back
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
|
Ready to act? Review this PR in Change Stack to turn feedback into patch suggestions you can inspect and refine. No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (2)
🚧 Files skipped from review as they are similar to previous changes (2)
📝 WalkthroughWalkthroughThis PR adds a dish details modal to the create-trip flow: domain/schema updates (isVegan), navigation APIs and router registration, new UI components (Badge, BottomSheetHeader, IngredientsList), and wiring from typical dishes to open the dish details modal showing image, ingredients, description, and dietary badges. ChangesDish Details Modal Feature
Sequence DiagramsequenceDiagram
participant TypicalDishesList
participant NavigationService
participant Router
participant DishDetailsModalPage
participant TripAPI
participant WikimediaImageService
TypicalDishesList->>NavigationService: toDishDetailsModal({tripId, searchTerm})
NavigationService->>Router: push(Stacks.CreateTrip, Modals.DishDetails, params)
Router->>DishDetailsModalPage: open with {tripId, searchTerm}
DishDetailsModalPage->>TripAPI: useGetTripById(tripId)
DishDetailsModalPage->>WikimediaImageService: useGetWikimediaDishImage(searchTerm)
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 3 | ❌ 2❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Code Review
This pull request introduces a new 'Dish Details' modal page to display typical dish information, including its description, ingredients, and dietary badges (Gluten-Free, Vegan, Vegetarian), along with supporting navigation, schemas, and translations. Feedback on the changes suggests avoiding dynamic StyleSheet.create calls in the Badge component to prevent performance issues, exposing and handling the trip query loading state with skeleton screens in the modal page to avoid visual flashes, and localizing the hardcoded 'Ingredients' string.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
There was a problem hiding this comment.
Hey - I've found 2 issues, and left some high level feedback:
- In
Badge.tsxyou referenceicons.success, but the icons map only declarescheckmarkandcloseCircle, so this will resolve toundefinedat runtime—either addsuccessto the icons map or reuse an existing icon key. - The
Badgecomponent uppercases translation keys vialabel.toLocaleUpperCase()before passing them toCustomText, which likely expects the raw i18n key; this will break lookups—consider leaving the key unchanged and handling casing via styles or by uppercasing the translated text instead. - The new
IngredientsListandDishDetailsModalPagecomponents mix plain strings (e.g."Ingredients") and translation keys; for consistency with the rest of the app, consider standardizing on translation keys and lettingCustomTexthandle localization.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- In `Badge.tsx` you reference `icons.success`, but the icons map only declares `checkmark` and `closeCircle`, so this will resolve to `undefined` at runtime—either add `success` to the icons map or reuse an existing icon key.
- The `Badge` component uppercases translation keys via `label.toLocaleUpperCase()` before passing them to `CustomText`, which likely expects the raw i18n key; this will break lookups—consider leaving the key unchanged and handling casing via styles or by uppercasing the translated text instead.
- The new `IngredientsList` and `DishDetailsModalPage` components mix plain strings (e.g. `"Ingredients"`) and translation keys; for consistency with the rest of the app, consider standardizing on translation keys and letting `CustomText` handle localization.
## Individual Comments
### Comment 1
<location path="features/core/ui/components/composite/Badge/Badge.tsx" line_range="29-30" />
<code_context>
+ <CustomImage source={image} style={styles.badgeImage} />
+ </View>
+ <View style={styles.checkBadge}>
+ <CustomIcon
+ name={active ? icons.success : icons.closeCircle}
+ size={spacing.TripleAndHalf}
+ color={active ? colors.tertiaryGreen : colors.primaryRed}
</code_context>
<issue_to_address>
**issue (bug_risk):** The `icons.success` key is not defined in the icons map and will likely cause a runtime error.
`icons.checkmark` is the defined success glyph in the icons map; `icons.success` does not exist. As written, this will pass `undefined` as the icon name, leading to a missing or broken icon at runtime. Please switch to `icons.checkmark` (or another existing key) so the success state renders properly.
</issue_to_address>
### Comment 2
<location path="features/trips/ui/components/IngredientsList/IngredientsList.tsx" line_range="14-24" />
<code_context>
+ <View style={styles.container}>
+ <CustomText text={title.toLocaleUpperCase()} style={styles.title} />
+ <View style={styles.chipsRow}>
+ {ingredients.map(ingredient => (
+ <Cheap
+ key={ingredient}
+ title={ingredient}
+ color={colors.secondaryGrey}
</code_context>
<issue_to_address>
**suggestion (bug_risk):** Using the ingredient value as the React key can lead to duplicate keys if the list contains repeated ingredients.
If an ingredient appears more than once, React will get duplicate keys, which can cause unstable rendering. Use a guaranteed-unique key instead, such as the map index or a combination of value and index (e.g. `key={`${ingredient}-${index}`}`).
```suggestion
<View style={styles.chipsRow}>
{ingredients.map((ingredient, index) => (
<Cheap
key={`${ingredient}-${index}`}
title={ingredient}
color={colors.secondaryGrey}
icon={icons.checkmark}
uppercase={false}
/>
))}
</View>
```
</issue_to_address>Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
There was a problem hiding this comment.
Actionable comments posted: 4
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@features/trips/ui/components/FoodCard/components/DishItem/DishItem.tsx`:
- Line 14: The Pressable in the DishItem component needs accessibility
semantics: add accessibilityRole="button" to the Pressable and supply an
accessibilityLabel derived from the dish name prop (e.g., `${name}, button` or
similar) so screen readers announce it properly; also forward accessibilityState
(e.g., disabled if onPress is undefined) and keep the existing onPress and style
props (look for the Pressable using styles.container and the onPress handler in
DishItem) so behavior and visual styling are unchanged.
In `@features/trips/ui/components/IngredientsList/IngredientsList.tsx`:
- Around line 15-18: The current IngredientsList map uses key={ingredient} which
can collide for duplicate ingredients; update the map in the IngredientsList
component to use a guaranteed-unique key (e.g., include the map index or a
unique id) by changing the map callback to accept the index and pass a composite
key such as `${ingredient}-${index}` (or use an ingredient unique identifier if
one exists) to the Cheap component's key prop to avoid reconciliation issues.
In `@features/trips/ui/pages/DishDetailsModalPage/DishDetailsModalPage.tsx`:
- Around line 27-31: When imageIsLoading is false but image is missing,
CustomImage may receive an undefined source; update the rendering logic in
DishDetailsModalPage so it checks for a loaded-but-no-image case before
rendering CustomImage. Specifically, inside the JSX that currently switches on
imageIsLoading, add an explicit branch for when imageIsLoading === false &&
!image to render a fallback (e.g., BaseSkeleton or a placeholder view) using
styles.image, otherwise render CustomImage with the existing source logic;
adjust the conditional that references imageIsLoading, image, CustomImage, and
BaseSkeleton accordingly.
- Line 32: Replace the hardcoded "Ingredients" string passed to IngredientsList
in DishDetailsModalPage with a localized string lookup (e.g., use your i18n
translate function such as t('dishDetails.ingredients') or a locale prop) so the
title comes from translations; update the IngredientsList invocation to:
title={t('...')} (or equivalent) and add the corresponding translation key to
your locale files (refer to IngredientsList, dishIngredients, and
DishDetailsModalPage to locate the change).
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 6abe06b9-c0a8-4400-a4b5-a51e851ab70c
⛔ Files ignored due to path filters (3)
features/core/ui/assets/images/gluten_free.pngis excluded by!**/*.pngfeatures/core/ui/assets/images/vegan.pngis excluded by!**/*.pngfeatures/core/ui/assets/images/vegetarian.pngis excluded by!**/*.png
📒 Files selected for processing (35)
app/(main)/(authenticated)/create-trip/_layout.tsxapp/(main)/(authenticated)/create-trip/dish-details-modal.tsxconvex/validators/Trips.tsfeatures/core/navigation/data/services/NavigationService.tsfeatures/core/navigation/domain/entities/Modals.tsfeatures/core/navigation/domain/entities/services/INavigationService.tsfeatures/core/translations/libraries/locales/en.jsonfeatures/core/translations/libraries/locales/it.jsonfeatures/core/ui/components/basic/Cheap/Cheap.tsxfeatures/core/ui/components/composite/Badge/Badge.style.tsfeatures/core/ui/components/composite/Badge/Badge.tsxfeatures/core/ui/components/composite/BottomSheetHeader/BottomSheetHeader.style.tsfeatures/core/ui/components/composite/BottomSheetHeader/BottomSheetHeader.tsxfeatures/core/ui/index.tsfeatures/core/ui/style/colors.tsfeatures/core/ui/style/dimensions/components.tsfeatures/core/ui/style/dimensions/images.tsfeatures/core/ui/style/icons.tsfeatures/trip-generation/domain/schemas/GenerateTripSchema.tsfeatures/trips/domain/entities/TypicalDish.tsfeatures/trips/pages.tsfeatures/trips/ui/components/FoodCard/FoodCard.style.tsfeatures/trips/ui/components/FoodCard/FoodCard.tsxfeatures/trips/ui/components/FoodCard/components/DishItem/DishItem.style.tsfeatures/trips/ui/components/FoodCard/components/DishItem/DishItem.tsxfeatures/trips/ui/components/IngredientsList/IngredientsList.style.tsfeatures/trips/ui/components/IngredientsList/IngredientsList.tsxfeatures/trips/ui/components/TypicalDishesList/TypicalDishesList.style.tsfeatures/trips/ui/components/TypicalDishesList/TypicalDishesList.tsxfeatures/trips/ui/components/TypicalDishesModalHeader/TypicalDishesModalHeader.style.tsfeatures/trips/ui/pages/DishDetailsModalPage/DishDetailsModalPage.logic.tsfeatures/trips/ui/pages/DishDetailsModalPage/DishDetailsModalPage.style.tsfeatures/trips/ui/pages/DishDetailsModalPage/DishDetailsModalPage.tsxfeatures/trips/ui/pages/TypicalDishesModalPage/TypicalDishesModalPage.logic.tsfeatures/trips/ui/pages/TypicalDishesModalPage/TypicalDishesModalPage.tsx
💤 Files with no reviewable changes (1)
- features/trips/ui/components/TypicalDishesModalHeader/TypicalDishesModalHeader.style.ts
There was a problem hiding this comment.
1 issue found across 3 files (changes from recent commits).
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="features/trips/ui/components/FoodCard/components/DishItem/DishItem.logic.ts">
<violation number="1" location="features/trips/ui/components/FoodCard/components/DishItem/DishItem.logic.ts:4">
P2: Duplicate `require()` calls for the same dietary badge images across two logic files. The same three images (`gluten_free.png`, `vegan.png`, `vegetarian.png`) are required independently in `DishItem.logic.ts` and `DishDetailsModalPage.logic.ts`, creating a maintenance burden when adding/removing badges.</violation>
</file>
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
There was a problem hiding this comment.
3 issues found across 39 files
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@features/trips/ui/components/FoodCard/components/DishItem/DishItem.tsx`:
- Around line 47-49: Add accessible labels to the dietary badge images by
passing an accessibilityLabel prop to each CustomImage when isGlutenFree,
isVegan, and isVegetarian are true; update the three occurrences that render
CustomImage (the ones using glutenFreeImage, veganImage, and vegetarianImage) to
include descriptive labels like "Gluten free", "Vegan", and "Vegetarian" (or
localized equivalents) so screen readers announce the badges.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 77b316f5-8280-4abf-86d0-0b3c823bb120
📒 Files selected for processing (9)
features/core/translations/libraries/locales/en.jsonfeatures/core/translations/libraries/locales/it.jsonfeatures/core/ui/components/composite/Badge/Badge.tsxfeatures/trips/ui/components/FoodCard/components/DishItem/DishItem.logic.tsfeatures/trips/ui/components/FoodCard/components/DishItem/DishItem.style.tsfeatures/trips/ui/components/FoodCard/components/DishItem/DishItem.tsxfeatures/trips/ui/components/IngredientsList/IngredientsList.tsxfeatures/trips/ui/pages/DishDetailsModalPage/DishDetailsModalPage.logic.tsfeatures/trips/ui/pages/DishDetailsModalPage/DishDetailsModalPage.tsx
✅ Files skipped from review due to trivial changes (1)
- features/core/translations/libraries/locales/en.json
🚧 Files skipped from review as they are similar to previous changes (3)
- features/trips/ui/pages/DishDetailsModalPage/DishDetailsModalPage.logic.ts
- features/trips/ui/components/FoodCard/components/DishItem/DishItem.style.ts
- features/core/ui/components/composite/Badge/Badge.tsx
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Fixes #356
Summary by CodeRabbit
New Features
UI/UX Improvements
Localization