- Changed state management for next day's activity to use 'dayLabel' instead of 'dateStr'. - Updated logic to determine the day label for next day's activity. - Modified badge text in HomeScreen to reflect the new label and improved localization for today's activity.
237 lines
6.4 KiB
TypeScript
237 lines
6.4 KiB
TypeScript
import { useState } from 'react';
|
|
import { StyleSheet, Text, View, TouchableOpacity, ScrollView, ActivityIndicator } from 'react-native';
|
|
import Colors from '@/constants/Colors';
|
|
import { FontAwesome, FontAwesome5 } from '@expo/vector-icons';
|
|
import { useSafeAreaInsets } from 'react-native-safe-area-context';
|
|
import { getPrograms, ProgramActivities, ProgramActivity } from '@/utils/programs';
|
|
import { useEffect } from 'react';
|
|
|
|
const Icon = ({ iconSet, iconName }: { iconSet: ProgramActivity['iconSet']; iconName: ProgramActivity['iconName'] }) => {
|
|
const color = "black";
|
|
const size = 24;
|
|
|
|
switch (iconSet) {
|
|
case 'FontAwesome':
|
|
return <FontAwesome name={iconName as any} size={size} color={color} />;
|
|
case 'FontAwesome5':
|
|
return <FontAwesome5 name={iconName as any} size={size} color={color} />;
|
|
default:
|
|
return null;
|
|
}
|
|
};
|
|
|
|
export default function Programs() {
|
|
const colorScheme = 'dark';
|
|
const [activeDay, setActiveDay] = useState<string | null>(null);
|
|
const insets = useSafeAreaInsets();
|
|
const [activities, setActivities] = useState<ProgramActivities>({});
|
|
const [loading, setLoading] = useState(true);
|
|
const [error, setError] = useState<string | null>(null);
|
|
const [isStale, setIsStale] = useState(false);
|
|
|
|
useEffect(() => {
|
|
const fetchPrograms = async () => {
|
|
try {
|
|
const { activities: data, isStale } = await getPrograms();
|
|
setActivities(data);
|
|
setIsStale(isStale);
|
|
if (Object.keys(data).length > 0) {
|
|
const today = new Date();
|
|
const day = String(today.getDate()).padStart(2, '0');
|
|
const month = String(today.getMonth() + 1).padStart(2, '0');
|
|
const year = today.getFullYear();
|
|
const formattedDate = `${day}.${month}.${year}`;
|
|
|
|
if (data[formattedDate]) {
|
|
setActiveDay(formattedDate);
|
|
} else {
|
|
setActiveDay(Object.keys(data)[0]);
|
|
}
|
|
}
|
|
} catch (e) {
|
|
setError('Failed to load program activities.');
|
|
} finally {
|
|
setLoading(false);
|
|
}
|
|
};
|
|
|
|
fetchPrograms();
|
|
}, []);
|
|
|
|
const dayKeys = Object.keys(activities);
|
|
|
|
if (loading) {
|
|
return (
|
|
<View style={[styles.container, styles.center]}>
|
|
<ActivityIndicator size="large" color={Colors[colorScheme].text} />
|
|
</View>
|
|
);
|
|
}
|
|
|
|
if (error) {
|
|
return (
|
|
<View style={[styles.container, styles.center]}>
|
|
<Text style={{ color: Colors[colorScheme].text }}>{error}</Text>
|
|
</View>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<View style={[styles.container, { backgroundColor: Colors[colorScheme].background, paddingTop: insets.top }]}>
|
|
<View style={styles.header}>
|
|
<Text style={[styles.title, { color: Colors[colorScheme].text }]}>Respisaniýa</Text>
|
|
</View>
|
|
|
|
{isStale && (
|
|
<View style={styles.warningContainer}>
|
|
<Text style={styles.warningText}>Soňky maglumatlary almak başartmady. Saklanan çäreler görkezilýär.</Text>
|
|
</View>
|
|
)}
|
|
|
|
<View>
|
|
<ScrollView horizontal showsHorizontalScrollIndicator={false} style={styles.daysScroll}>
|
|
{dayKeys.map((day) => (
|
|
<TouchableOpacity
|
|
key={day}
|
|
style={[styles.dayButton, activeDay === day && styles.activeDayButton]}
|
|
onPress={() => setActiveDay(day)}
|
|
>
|
|
<Text style={[styles.dayText, activeDay === day && styles.activeDayText]}>{day}</Text>
|
|
</TouchableOpacity>
|
|
))}
|
|
</ScrollView>
|
|
</View>
|
|
|
|
<ScrollView style={styles.content}>
|
|
{activeDay &&
|
|
activities[activeDay]?.map((activity, index) => (
|
|
<View key={index}>
|
|
<View style={styles.activityCard}>
|
|
<View style={styles.timeContainer}>
|
|
{activity.time && <Text style={styles.timeText}>{activity.time}</Text>}
|
|
<Text style={styles.activityTitle}>{activity.title}</Text>
|
|
<Text style={styles.activityDescription}>{activity.description}</Text>
|
|
</View>
|
|
<View style={styles.iconContainer}>
|
|
<Icon iconSet={activity.iconSet} iconName={activity.iconName} />
|
|
</View>
|
|
</View>
|
|
{activity.transport && (
|
|
<View style={styles.transportContainer}>
|
|
<View style={styles.dot} />
|
|
<View style={styles.dot} />
|
|
<View style={styles.dot} />
|
|
<Text style={styles.transportText}>{activity.transport}</Text>
|
|
</View>
|
|
)}
|
|
</View>
|
|
))}
|
|
</ScrollView>
|
|
</View>
|
|
);
|
|
}
|
|
|
|
const styles = StyleSheet.create({
|
|
container: {
|
|
flex: 1,
|
|
},
|
|
center: {
|
|
justifyContent: 'center',
|
|
alignItems: 'center',
|
|
},
|
|
header: {
|
|
alignItems: 'center',
|
|
paddingVertical: 10,
|
|
paddingHorizontal: 20,
|
|
},
|
|
warningContainer: {
|
|
backgroundColor: 'orange',
|
|
padding: 10,
|
|
alignItems: 'center',
|
|
},
|
|
warningText: {
|
|
color: 'white',
|
|
textAlign: 'center',
|
|
},
|
|
title: {
|
|
fontSize: 24,
|
|
fontWeight: 'bold',
|
|
},
|
|
daysScroll: {
|
|
paddingHorizontal: 20,
|
|
paddingVertical: 10,
|
|
},
|
|
dayButton: {
|
|
paddingVertical: 8,
|
|
paddingHorizontal: 16,
|
|
borderRadius: 20,
|
|
backgroundColor: '#333',
|
|
marginRight: 10,
|
|
},
|
|
activeDayButton: {
|
|
backgroundColor: '#555',
|
|
},
|
|
dayText: {
|
|
color: 'white',
|
|
},
|
|
activeDayText: {
|
|
fontWeight: 'bold',
|
|
},
|
|
content: {
|
|
flex: 1,
|
|
paddingHorizontal: 20,
|
|
},
|
|
activityCard: {
|
|
backgroundColor: '#222',
|
|
borderRadius: 15,
|
|
padding: 20,
|
|
flexDirection: 'row',
|
|
justifyContent: 'space-between',
|
|
alignItems: 'center',
|
|
marginBottom: 10,
|
|
},
|
|
timeContainer: {
|
|
flex: 1,
|
|
},
|
|
timeText: {
|
|
color: 'gray',
|
|
fontSize: 14,
|
|
marginBottom: 4,
|
|
},
|
|
activityTitle: {
|
|
color: 'white',
|
|
fontSize: 20,
|
|
fontWeight: 'bold',
|
|
marginBottom: 4,
|
|
},
|
|
activityDescription: {
|
|
color: 'gray',
|
|
fontSize: 14,
|
|
},
|
|
iconContainer: {
|
|
width: 50,
|
|
height: 50,
|
|
borderRadius: 25,
|
|
backgroundColor: 'white',
|
|
justifyContent: 'center',
|
|
alignItems: 'center',
|
|
},
|
|
transportContainer: {
|
|
flexDirection: 'row',
|
|
alignItems: 'center',
|
|
justifyContent: 'center',
|
|
marginVertical: 10,
|
|
},
|
|
dot: {
|
|
width: 6,
|
|
height: 6,
|
|
borderRadius: 3,
|
|
backgroundColor: 'gray',
|
|
marginHorizontal: 3,
|
|
},
|
|
transportText: {
|
|
color: 'gray',
|
|
marginLeft: 10,
|
|
},
|
|
});
|