1- import { LargeTitleHeader , Text } from '@packrat/ui/nativewindui' ;
2- import { cn } from 'expo-app/lib/cn' ;
3- import { ScrollView , View } from 'react-native' ;
1+ import { ActivityIndicator , LargeTitleHeader , Text } from '@packrat/ui/nativewindui' ;
2+ import { featureFlags } from 'expo-app/config' ;
3+ import { SubmitConditionReportForm } from 'expo-app/features/trail-conditions/components/SubmitConditionReportForm' ;
4+ import { TrailConditionReportCard } from 'expo-app/features/trail-conditions/components/TrailConditionReportCard' ;
5+ import { useTrailConditionReports } from 'expo-app/features/trail-conditions/hooks/useTrailConditionReports' ;
6+ import { useState } from 'react' ;
7+ import { Modal , Pressable , ScrollView , View } from 'react-native' ;
48
5- // Mock data for trail conditions
6- const TRAIL_CONDITIONS = [
7- {
8- id : '1' ,
9- section : 'Springer Mountain to Neels Gap' ,
10- state : 'GA' ,
11- lastUpdated : '2 days ago' ,
12- condition : 'Good' ,
13- details :
14- 'Trail is well maintained with clear blazes. Some muddy sections after recent rain but passable. Water sources are flowing well.' ,
15- reports : [
16- {
17- user : 'HikerJohn' ,
18- date : 'May 10' ,
19- text : 'Trail in great shape. Saw some trail maintenance crews working near Blood Mountain.' ,
20- } ,
21- {
22- user : 'MountainGoat' ,
23- date : 'May 8' ,
24- text : 'Muddy near stream crossings but otherwise good. All water sources flowing.' ,
25- } ,
26- ] ,
27- } ,
28- {
29- id : '2' ,
30- section : 'Neels Gap to Unicoi Gap' ,
31- state : 'GA' ,
32- lastUpdated : '5 days ago' ,
33- condition : 'Fair' ,
34- details :
35- 'Some blowdowns reported between Low Gap and Blue Mountain shelters. Rocky sections can be slippery when wet. Moderate difficulty.' ,
36- reports : [
37- {
38- user : 'TrailAngel22' ,
39- date : 'May 7' ,
40- text : 'Three large trees down about 2 miles north of Low Gap shelter. Passable but difficult.' ,
41- } ,
42- {
43- user : 'ThruHiker2024' ,
44- date : 'May 5' ,
45- text : 'Rocky sections are challenging in rain. Trekking poles recommended.' ,
46- } ,
47- ] ,
48- } ,
49- {
50- id : '3' ,
51- section : 'Unicoi Gap to Tray Mountain' ,
52- state : 'GA' ,
53- lastUpdated : '1 week ago' ,
54- condition : 'Excellent' ,
55- details :
56- 'Recently maintained trail with clear path and blazes. Some steep sections but well-graded. All water sources reliable.' ,
57- reports : [
58- {
59- user : 'MountainLover' ,
60- date : 'May 4' ,
61- text : 'Trail is in excellent condition. Views from Rocky Mountain are spectacular!' ,
62- } ,
63- {
64- user : 'GearTester' ,
65- date : 'May 2' ,
66- text : 'Easy to follow trail with good camping spots near Tray Mountain shelter.' ,
67- } ,
68- ] ,
69- } ,
70- {
71- id : '4' ,
72- section : "Tray Mountain to Dick's Creek Gap" ,
73- state : 'GA' ,
74- lastUpdated : '10 days ago' ,
75- condition : 'Poor' ,
76- details :
77- 'Multiple blowdowns and washouts reported after recent storms. Some trail reroutes in effect. Check with local rangers for updates.' ,
78- reports : [
79- {
80- user : 'SectionHiker' ,
81- date : 'April 30' ,
82- text : 'Difficult hiking with many obstacles. Several trees down across trail.' ,
83- } ,
84- {
85- user : 'TrailRunner' ,
86- date : 'April 28' ,
87- text : 'Trail badly eroded in places. Slow going and requires careful navigation.' ,
88- } ,
89- ] ,
90- } ,
91- ] ;
92-
93- function ConditionBadge ( { condition } : { condition : string } ) {
94- const getColor = ( ) => {
95- switch ( condition ) {
96- case 'Excellent' :
97- return 'bg-green-500' ;
98- case 'Good' :
99- return 'bg-blue-500' ;
100- case 'Fair' :
101- return 'bg-amber-500' ;
102- case 'Poor' :
103- return 'bg-red-500' ;
104- default :
105- return 'bg-gray-500' ;
106- }
107- } ;
9+ export default function TrailConditionsScreen ( ) {
10+ const [ showSubmitForm , setShowSubmitForm ] = useState ( false ) ;
11+ const { data : reports , isLoading, error } = useTrailConditionReports ( ) ;
10812
109- return (
110- < View className = { cn ( 'rounded-full px-2 py-1' , getColor ( ) ) } >
111- < Text variant = "caption2" className = "font-medium text-white" >
112- { condition }
113- </ Text >
114- </ View >
115- ) ;
116- }
13+ if ( ! featureFlags . enableTrailConditions ) return null ;
11714
118- function TrailConditionCard ( { trail } : { trail : ( typeof TRAIL_CONDITIONS ) [ 0 ] } ) {
119- return (
120- < View className = "mx-4 mb-3 overflow-hidden rounded-xl bg-card shadow-sm" >
121- < View className = "border-b border-border p-4" >
122- < View className = "flex-row items-center justify-between" >
123- < Text variant = "heading" className = "flex-1 font-semibold" >
124- { trail . section }
125- </ Text >
126- < ConditionBadge condition = { trail . condition } />
127- </ View >
128- < Text variant = "subhead" className = "mt-1 text-muted-foreground" >
129- { trail . state } • Updated { trail . lastUpdated }
130- </ Text >
131- </ View >
132-
133- < View className = "p-4" >
134- < Text variant = "body" className = "mb-3" >
135- { trail . details }
136- </ Text >
137-
138- < View className = "mt-2" >
139- < Text variant = "subhead" className = "mb-2 font-medium" >
140- Recent Reports:
141- </ Text >
142- { trail . reports . map ( ( report ) => (
143- < View key = { report . text } className = "mb-2 rounded-md bg-muted p-3 dark:bg-gray-50/10" >
144- < View className = "flex-row items-center justify-between" >
145- < Text variant = "footnote" className = "font-medium" >
146- { report . user }
147- </ Text >
148- < Text variant = "caption1" className = "text-muted-foreground" >
149- { report . date }
150- </ Text >
151- </ View >
152- < Text variant = "footnote" className = "mt-1" >
153- { report . text }
154- </ Text >
155- </ View >
156- ) ) }
157- </ View >
158- </ View >
159- </ View >
160- ) ;
161- }
162-
163- export default function TrailConditionsScreen ( ) {
16415 return (
16516 < >
166- < LargeTitleHeader title = "Trail Conditions" />
17+ < LargeTitleHeader
18+ title = "Trail Conditions"
19+ rightView = { ( ) => (
20+ < Pressable
21+ onPress = { ( ) => setShowSubmitForm ( true ) }
22+ className = "mr-2 rounded-full bg-primary px-3 py-1.5"
23+ >
24+ < Text variant = "footnote" className = "font-semibold text-primary-foreground" >
25+ + Report
26+ </ Text >
27+ </ Pressable >
28+ ) }
29+ />
30+
16731 < ScrollView className = "flex-1" >
16832 < View className = "p-4" >
16933 < Text variant = "subhead" className = "mb-2 text-muted-foreground" >
17034 Current trail conditions from recent hiker reports
17135 </ Text >
17236 </ View >
17337
174- < View className = "pb-4" >
175- { TRAIL_CONDITIONS . map ( ( trail ) => (
176- < TrailConditionCard key = { trail . id } trail = { trail } />
177- ) ) }
178- </ View >
38+ { isLoading ? (
39+ < View className = "flex-1 items-center justify-center py-12" >
40+ < ActivityIndicator />
41+ </ View >
42+ ) : error ? (
43+ < View className = "mx-4 mb-3 rounded-xl bg-card p-4" >
44+ < Text variant = "body" className = "text-center text-muted-foreground" >
45+ Unable to load trail conditions. Pull to refresh.
46+ </ Text >
47+ </ View >
48+ ) : reports && reports . length > 0 ? (
49+ < View className = "pb-4" >
50+ { reports . map ( ( report ) => (
51+ < TrailConditionReportCard key = { report . id } report = { report } />
52+ ) ) }
53+ </ View >
54+ ) : (
55+ < View className = "mx-4 mb-3 rounded-xl bg-card p-8" >
56+ < Text variant = "body" className = "text-center text-muted-foreground" >
57+ No trail condition reports yet. Be the first to report!
58+ </ Text >
59+ < Pressable
60+ onPress = { ( ) => setShowSubmitForm ( true ) }
61+ className = "mt-4 rounded-lg bg-primary px-4 py-3"
62+ >
63+ < Text className = "text-center font-semibold text-primary-foreground" >
64+ Submit a Report
65+ </ Text >
66+ </ Pressable >
67+ </ View >
68+ ) }
17969
18070 < View className = "mx-4 my-2 mb-6 rounded-lg bg-card p-4" >
18171 < View className = "rounded-md bg-muted p-3 dark:bg-gray-50/10" >
@@ -186,6 +76,26 @@ export default function TrailConditionsScreen() {
18676 </ View >
18777 </ View >
18878 </ ScrollView >
79+
80+ { /* Submit Report Modal */ }
81+ < Modal
82+ visible = { showSubmitForm }
83+ animationType = "slide"
84+ presentationStyle = "pageSheet"
85+ onRequestClose = { ( ) => setShowSubmitForm ( false ) }
86+ >
87+ < View className = "flex-1 bg-background" >
88+ < View className = "flex-row items-center justify-between border-b border-border px-4 py-3" >
89+ < Text variant = "heading" className = "font-semibold" >
90+ Report Trail Conditions
91+ </ Text >
92+ < Pressable onPress = { ( ) => setShowSubmitForm ( false ) } >
93+ < Text className = "font-semibold text-primary" > Cancel</ Text >
94+ </ Pressable >
95+ </ View >
96+ < SubmitConditionReportForm onSuccess = { ( ) => setShowSubmitForm ( false ) } />
97+ </ View >
98+ </ Modal >
18999 </ >
190100 ) ;
191101}
0 commit comments