feat(iOS): Add comprehensive Trail Conditions feature with filtering, reporting, and condition history#1885
Conversation
|
@coderabbitai Please review this PR for code quality, best practices, and potential issues. |
Rate Limit Exceeded
|
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
|
Important Review skippedBot user detected. To trigger a single review, invoke the ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
There was a problem hiding this comment.
Pull request overview
Expands the Expo app’s Trail Conditions experience by introducing a richer condition taxonomy, filtering + history UI, and a new entry point from the Trips tab, with supporting i18n strings.
Changes:
- Added
trailConditionsi18n namespace andcommon.submit. - Added a Trips tab banner linking to
/trail-conditions. - Reworked the Trail Conditions screen with typed condition categories, a sticky surface filter, expandable history cards, and a “Report Condition” modal (UI-only submission).
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 4 comments.
| File | Description |
|---|---|
| apps/expo/lib/i18n/locales/en.json | Adds Trail Conditions translation namespace + common.submit. |
| apps/expo/features/trips/screens/TripListScreen.tsx | Adds TrailConditionsBanner as a Trips list header linking to the Trail Conditions screen. |
| apps/expo/app/(app)/trail-conditions.tsx | Implements new Trail Conditions UI: typed conditions, filter bar, expandable report history, and reporting modal. |
You can also share your feedback on Copilot code review. Take the survey.
| const SURFACE_FILTERS: Array<{ label: string; value: SurfaceCondition | 'All' }> = [ | ||
| { label: 'All', value: 'All' }, | ||
| { label: 'Dry', value: 'Dry' }, | ||
| { label: 'Muddy', value: 'Muddy' }, | ||
| { label: 'Snow', value: 'Snow' }, | ||
| { label: 'Ice', value: 'Ice' }, | ||
| { label: 'Closed', value: 'Closed' }, | ||
| ]; |
There was a problem hiding this comment.
SURFACE_FILTERS hard-codes English labels ("All", "Dry", etc.) even though the rest of the screen is localized via t(...). Consider adding i18n keys for these filter labels (and optionally deriving this array from a single SurfaceCondition[] source) so the filter bar can be translated consistently.
| activeFilter === filter.value | ||
| ? filter.value === 'All' | ||
| ? 'bg-primary' | ||
| : getSurfaceBadgeColor(filter.value as SurfaceCondition) | ||
| : 'bg-muted dark:bg-gray-50/10', |
There was a problem hiding this comment.
The filter chip color logic uses a as SurfaceCondition cast when calling getSurfaceBadgeColor(...), which bypasses type-safety and can hide future bugs if new filter values are added. You can avoid the cast by narrowing on filter.value !== 'All' (or by splitting the "All" option out) so TypeScript enforces the valid surface values.
| <ScrollView className="flex-1" stickyHeaderIndices={[0]}> | ||
| {/* Filter bar — sticky */} | ||
| <View className="border-b border-border bg-background px-4 pb-3 pt-2"> | ||
| <ScrollView horizontal showsHorizontalScrollIndicator={false}> | ||
| <View className="flex-row gap-2"> |
There was a problem hiding this comment.
This screen renders the trail list inside a vertical ScrollView and maps items directly, which will render all cards at once (no virtualization). If this is intended to scale beyond a handful of mock rows, consider switching to FlatList (with a header component for the filter bar + subtitle) to avoid performance/memory issues as the number of trails/reports grows.
| interface TrailReport { | ||
| user: string; | ||
| date: string; | ||
| text: string; | ||
| timestamp: string; | ||
| } |
There was a problem hiding this comment.
TrailReport stores both a display date string and a timestamp ISO string, but the UI displays report.date while timestamp is only used as the React key. To avoid duplicated/possibly-inconsistent date sources, consider storing a single timestamp and formatting it for display (or remove timestamp if you only need a display date).
d672a8b to
4bcf824
Compare
…ng, reporting, and condition history Co-authored-by: andrew-bierman <94939237+andrew-bierman@users.noreply.github.com>
…arnings and add safe area padding for header overlap
…tion
- Add trailConditions.filters.{all,paved,gravel,dirt,rocky,snow,mud} keys
to en.json so surface filter labels are localizable
- Introduce SURFACE_FILTERS (FilterItem[]) inside the component, using t()
for each label — no more hardcoded English strings
- Add SurfaceFilter type (TrailSurface | 'all') and selectedSurface state;
filter reports with useMemo before rendering
- getSurfaceBadgeColor takes a narrowed TrailSurface (never 'all') via a
filter.value !== 'all' check, eliminating the unsafe type cast
- Replace ScrollView + map with FlatList; filter bar and subtitle moved
into ListHeaderComponent, disclaimer into ListFooterComponent — list
items are now virtualized
f843b96 to
3a222cc
Compare
#1885 shipped with Icon name="terrain" which isn't in the @roninoss/icons SF Symbol allowlist, breaking check-types on development. Replace with "map" — valid and semantically equivalent for a trail-conditions banner.
#1885 shipped with Icon name="terrain" which isn't in the @roninoss/icons SF Symbol allowlist, breaking check-types on development. Replace with "map" — valid and semantically equivalent for a trail-conditions banner.
#1885 shipped with Icon name="terrain" which isn't in the @roninoss/icons SF Symbol allowlist, breaking check-types on development. Replace with "map" — valid and semantically equivalent for a trail-conditions banner.
#1885 shipped with Icon name="terrain" which isn't in the @roninoss/icons SF Symbol allowlist, breaking check-types on development. Replace with "map" — valid and semantically equivalent for a trail-conditions banner.
Trail Conditions was only accessible via a home dashboard tile with read-only mock data using vague condition labels. This PR expands the feature to the full spec — proper condition taxonomy, field reporting, filtering, and a dedicated entry point in the Trips tab.
Trail Conditions Screen (
trail-conditions.tsx)Dry | Muddy | Snow | Ice | ClosedpresentationStyle="pageSheet") with chip selectors for surface/obstacles/water crossings, a notes field, and a photo upload placeholderTrips Tab (
TripListScreen.tsx)TrailConditionsBannerasListHeaderComponent— gives iOS users a direct entry point from the Trips tab, not just the home dashboardi18n (
en.json)trailConditionsnamespace (34 keys) andcommon.submitOriginal prompt
✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.