Add stale data handling in Programs component
- Enhanced the getPrograms function to return a stale flag indicating if cached data is being used. - Implemented a warning message in the Programs component to inform users when stale data is displayed. - Updated styles for the warning message to improve visibility.
This commit is contained in:
@@ -27,12 +27,14 @@ export default function Programs() {
|
|||||||
const [activities, setActivities] = useState<ProgramActivities>({});
|
const [activities, setActivities] = useState<ProgramActivities>({});
|
||||||
const [loading, setLoading] = useState(true);
|
const [loading, setLoading] = useState(true);
|
||||||
const [error, setError] = useState<string | null>(null);
|
const [error, setError] = useState<string | null>(null);
|
||||||
|
const [isStale, setIsStale] = useState(false);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const fetchPrograms = async () => {
|
const fetchPrograms = async () => {
|
||||||
try {
|
try {
|
||||||
const data = await getPrograms();
|
const { activities: data, isStale } = await getPrograms();
|
||||||
setActivities(data);
|
setActivities(data);
|
||||||
|
setIsStale(isStale);
|
||||||
if (Object.keys(data).length > 0) {
|
if (Object.keys(data).length > 0) {
|
||||||
const today = new Date();
|
const today = new Date();
|
||||||
const day = String(today.getDate()).padStart(2, '0');
|
const day = String(today.getDate()).padStart(2, '0');
|
||||||
@@ -80,6 +82,12 @@ export default function Programs() {
|
|||||||
<Text style={[styles.title, { color: Colors[colorScheme].text }]}>Umrah Pilgrimage</Text>
|
<Text style={[styles.title, { color: Colors[colorScheme].text }]}>Umrah Pilgrimage</Text>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
|
{isStale && (
|
||||||
|
<View style={styles.warningContainer}>
|
||||||
|
<Text style={styles.warningText}>Failed to fetch latest data. Showing cached activities.</Text>
|
||||||
|
</View>
|
||||||
|
)}
|
||||||
|
|
||||||
<View>
|
<View>
|
||||||
<ScrollView horizontal showsHorizontalScrollIndicator={false} style={styles.daysScroll}>
|
<ScrollView horizontal showsHorizontalScrollIndicator={false} style={styles.daysScroll}>
|
||||||
{dayKeys.map((day) => (
|
{dayKeys.map((day) => (
|
||||||
@@ -136,6 +144,15 @@ const styles = StyleSheet.create({
|
|||||||
paddingVertical: 10,
|
paddingVertical: 10,
|
||||||
paddingHorizontal: 20,
|
paddingHorizontal: 20,
|
||||||
},
|
},
|
||||||
|
warningContainer: {
|
||||||
|
backgroundColor: 'orange',
|
||||||
|
padding: 10,
|
||||||
|
alignItems: 'center',
|
||||||
|
},
|
||||||
|
warningText: {
|
||||||
|
color: 'white',
|
||||||
|
textAlign: 'center',
|
||||||
|
},
|
||||||
title: {
|
title: {
|
||||||
fontSize: 24,
|
fontSize: 24,
|
||||||
fontWeight: 'bold',
|
fontWeight: 'bold',
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
|
|
||||||
import { FontAwesome, FontAwesome5, MaterialCommunityIcons } from '@expo/vector-icons';
|
import { FontAwesome, FontAwesome5, MaterialCommunityIcons } from '@expo/vector-icons';
|
||||||
|
import AsyncStorage from '@react-native-async-storage/async-storage';
|
||||||
|
|
||||||
export type ProgramActivity = {
|
export type ProgramActivity = {
|
||||||
time: string;
|
time: string;
|
||||||
@@ -14,18 +15,29 @@ export type ProgramActivities = {
|
|||||||
[date: string]: ProgramActivity[];
|
[date: string]: ProgramActivity[];
|
||||||
};
|
};
|
||||||
|
|
||||||
const PROGRAMS_URL = 'http://kepilhyzmat.com/assets/programs.json';
|
export type ProgramData = {
|
||||||
|
activities: ProgramActivities;
|
||||||
|
isStale: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
export const getPrograms = async (): Promise<ProgramActivities> => {
|
const PROGRAMS_URL = 'http://kepilhyzmat.com/assets/programs.json';
|
||||||
|
const PROGRAMS_CACHE_KEY = 'program_activities_cache';
|
||||||
|
|
||||||
|
export const getPrograms = async (): Promise<ProgramData> => {
|
||||||
try {
|
try {
|
||||||
const response = await fetch(PROGRAMS_URL);
|
const response = await fetch(PROGRAMS_URL);
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
throw new Error(`Request failed with status ${response.status}`);
|
throw new Error(`Request failed with status ${response.status}`);
|
||||||
}
|
}
|
||||||
const data: ProgramActivities = await response.json();
|
const data: ProgramActivities = await response.json();
|
||||||
return data;
|
await AsyncStorage.setItem(PROGRAMS_CACHE_KEY, JSON.stringify(data));
|
||||||
|
return { activities: data, isStale: false };
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Failed to fetch programs:', error);
|
console.error('Failed to fetch programs:', error);
|
||||||
throw error;
|
const cachedData = await AsyncStorage.getItem(PROGRAMS_CACHE_KEY);
|
||||||
|
if (cachedData) {
|
||||||
|
return { activities: JSON.parse(cachedData), isStale: true };
|
||||||
|
}
|
||||||
|
throw new Error('Failed to fetch programs and no cache available.');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user