Sync cities between prayers
This commit is contained in:
@@ -4,6 +4,7 @@ import { useColorScheme, View } from 'react-native';
|
||||
|
||||
import Colors from '@/constants/Colors';
|
||||
import i18n from '@/i18n';
|
||||
import { CityProvider } from '../../context/CityContext';
|
||||
|
||||
/**
|
||||
* You can explore the built-in icon families and icons on the web at https://icons.expo.fyi/
|
||||
@@ -19,43 +20,45 @@ export default function TabLayout() {
|
||||
const colorScheme = 'dark'; // Force dark mode
|
||||
|
||||
return (
|
||||
<Tabs
|
||||
screenOptions={{
|
||||
tabBarActiveTintColor: Colors[colorScheme].tint,
|
||||
tabBarStyle: {
|
||||
backgroundColor: Colors[colorScheme].secondary,
|
||||
borderTopColor: Colors[colorScheme].secondary,
|
||||
},
|
||||
headerShown: false, // hide header globally for tabs
|
||||
}}>
|
||||
<Tabs.Screen
|
||||
name="home"
|
||||
options={{
|
||||
title: i18n.t('home'),
|
||||
tabBarIcon: ({ color }) => <TabBarIcon name="home" color={color} />,
|
||||
}}
|
||||
/>
|
||||
<Tabs.Screen
|
||||
name="services"
|
||||
options={{
|
||||
title: i18n.t('services'),
|
||||
tabBarIcon: ({ color }) => <TabBarIcon name="th-large" color={color} />,
|
||||
}}
|
||||
/>
|
||||
<Tabs.Screen
|
||||
name="index"
|
||||
options={{
|
||||
title: i18n.t('menuSalah'),
|
||||
tabBarIcon: ({ color }) => <TabBarIcon name="moon-o" color={color} />,
|
||||
}}
|
||||
/>
|
||||
<Tabs.Screen
|
||||
name="programs"
|
||||
options={{
|
||||
title: i18n.t('Programs'),
|
||||
tabBarIcon: ({ color }) => <TabBarIcon name="calendar" color={color} />,
|
||||
}}
|
||||
/>
|
||||
</Tabs>
|
||||
<CityProvider>
|
||||
<Tabs
|
||||
screenOptions={{
|
||||
tabBarActiveTintColor: Colors[colorScheme].tint,
|
||||
tabBarStyle: {
|
||||
backgroundColor: Colors[colorScheme].secondary,
|
||||
borderTopColor: Colors[colorScheme].secondary,
|
||||
},
|
||||
headerShown: false, // hide header globally for tabs
|
||||
}}>
|
||||
<Tabs.Screen
|
||||
name="home"
|
||||
options={{
|
||||
title: i18n.t('home'),
|
||||
tabBarIcon: ({ color }) => <TabBarIcon name="home" color={color} />,
|
||||
}}
|
||||
/>
|
||||
<Tabs.Screen
|
||||
name="services"
|
||||
options={{
|
||||
title: i18n.t('services'),
|
||||
tabBarIcon: ({ color }) => <TabBarIcon name="th-large" color={color} />,
|
||||
}}
|
||||
/>
|
||||
<Tabs.Screen
|
||||
name="index"
|
||||
options={{
|
||||
title: i18n.t('menuSalah'),
|
||||
tabBarIcon: ({ color }) => <TabBarIcon name="moon-o" color={color} />,
|
||||
}}
|
||||
/>
|
||||
<Tabs.Screen
|
||||
name="programs"
|
||||
options={{
|
||||
title: i18n.t('Programs'),
|
||||
tabBarIcon: ({ color }) => <TabBarIcon name="calendar" color={color} />,
|
||||
}}
|
||||
/>
|
||||
</Tabs>
|
||||
</CityProvider>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { Pressable, ScrollView, StyleSheet, Text, View } from 'react-native';
|
||||
import { useCallback, useEffect, useState } from 'react';
|
||||
import { useSafeAreaInsets } from 'react-native-safe-area-context';
|
||||
import AsyncStorage from '@react-native-async-storage/async-storage';
|
||||
|
||||
import { getPrayerTimes, cities } from '../../utils/prayerTimeCalculator';
|
||||
import i18n from '../../i18n';
|
||||
import Colors from '../../constants/Colors';
|
||||
import { useCity } from '../../context/CityContext';
|
||||
|
||||
type Prayer = {
|
||||
name: string;
|
||||
@@ -17,26 +17,11 @@ type City = keyof typeof cities;
|
||||
export default function TabIndex() {
|
||||
const colorScheme = 'dark';
|
||||
const theme = Colors[colorScheme ?? 'light'];
|
||||
const [selectedCity, setSelectedCity] = useState<City>('Makkah');
|
||||
const { selectedCity, setSelectedCity } = useCity();
|
||||
const [prayerTimes, setPrayerTimes] = useState<Prayer[]>([]);
|
||||
const [nextPrayerName, setNextPrayerName] = useState<string | null>(null);
|
||||
const insets = useSafeAreaInsets();
|
||||
|
||||
useEffect(() => {
|
||||
const loadSelectedCity = async () => {
|
||||
try {
|
||||
const city = (await AsyncStorage.getItem('selectedCity')) as City;
|
||||
if (city) {
|
||||
setSelectedCity(city);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to load selected city:', error);
|
||||
}
|
||||
};
|
||||
|
||||
loadSelectedCity();
|
||||
}, []);
|
||||
|
||||
const prayerNameMapping: { [key: string]: string } = {
|
||||
fajr: i18n.t('fajr'),
|
||||
dhuhr: i18n.t('dhuhr'),
|
||||
@@ -82,15 +67,6 @@ export default function TabIndex() {
|
||||
return () => clearInterval(interval);
|
||||
}, [updatePrayerTimes]);
|
||||
|
||||
const handleCityChange = async (city: City) => {
|
||||
setSelectedCity(city);
|
||||
try {
|
||||
await AsyncStorage.setItem('selectedCity', city);
|
||||
} catch (error) {
|
||||
console.error('Failed to save selected city:', error);
|
||||
}
|
||||
};
|
||||
|
||||
const renderPrayerTime = (prayer: Prayer) => {
|
||||
const isNextPrayer = prayer.name === nextPrayerName;
|
||||
return (
|
||||
@@ -119,7 +95,7 @@ export default function TabIndex() {
|
||||
{(Object.keys(cities) as City[]).map((city) => (
|
||||
<Pressable
|
||||
key={city}
|
||||
onPress={() => handleCityChange(city)}
|
||||
onPress={() => setSelectedCity(city)}
|
||||
style={[styles.cityButton, { backgroundColor: theme.secondary }, selectedCity === city && [styles.activeCityButton, { backgroundColor: theme.tint }]]}>
|
||||
<Text
|
||||
style={[
|
||||
|
||||
@@ -4,7 +4,7 @@ import Colors from '@/constants/Colors';
|
||||
import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons';
|
||||
import { getPrayerTimes, cities } from '@/utils/prayerTimeCalculator';
|
||||
import i18n from '@/i18n';
|
||||
import { createIconSetFromFontello } from 'react-native-vector-icons';
|
||||
import { useCity } from '../context/CityContext';
|
||||
|
||||
type Prayer = {
|
||||
name: string;
|
||||
@@ -25,7 +25,7 @@ export default function PrayerTimeCard() {
|
||||
const [prayerTimes, setPrayerTimes] = useState<Prayer[]>([]);
|
||||
const [nextPrayer, setNextPrayer] = useState<{ name: string; time: string } | null>(null);
|
||||
const [remainingTime, setRemainingTime] = useState('');
|
||||
const [selectedCity, setSelectedCity] = useState<keyof typeof cities>('Makkah');
|
||||
const { selectedCity, setSelectedCity } = useCity();
|
||||
|
||||
useEffect(() => {
|
||||
const times = getPrayerTimes(selectedCity);
|
||||
|
||||
54
context/CityContext.tsx
Normal file
54
context/CityContext.tsx
Normal file
@@ -0,0 +1,54 @@
|
||||
import React, { createContext, useState, useEffect, useContext, ReactNode } from 'react';
|
||||
import AsyncStorage from '@react-native-async-storage/async-storage';
|
||||
import { cities } from '../utils/prayerTimeCalculator';
|
||||
|
||||
type City = keyof typeof cities;
|
||||
|
||||
interface CityContextType {
|
||||
selectedCity: City;
|
||||
setSelectedCity: (city: City) => void;
|
||||
}
|
||||
|
||||
const CityContext = createContext<CityContextType | undefined>(undefined);
|
||||
|
||||
export const CityProvider = ({ children }: { children: ReactNode }) => {
|
||||
const [selectedCity, setSelectedCityState] = useState<City>('Makkah');
|
||||
|
||||
useEffect(() => {
|
||||
const loadSelectedCity = async () => {
|
||||
try {
|
||||
const city = await AsyncStorage.getItem('selectedCity') as City;
|
||||
if (city) {
|
||||
setSelectedCityState(city);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to load selected city:', error);
|
||||
}
|
||||
};
|
||||
|
||||
loadSelectedCity();
|
||||
}, []);
|
||||
|
||||
const handleSetSelectedCity = async (city: City) => {
|
||||
setSelectedCityState(city);
|
||||
try {
|
||||
await AsyncStorage.setItem('selectedCity', city);
|
||||
} catch (error) {
|
||||
console.error('Failed to save selected city:', error);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<CityContext.Provider value={{ selectedCity, setSelectedCity: handleSetSelectedCity }}>
|
||||
{children}
|
||||
</CityContext.Provider>
|
||||
);
|
||||
};
|
||||
|
||||
export const useCity = () => {
|
||||
const context = useContext(CityContext);
|
||||
if (context === undefined) {
|
||||
throw new Error('useCity must be used within a CityProvider');
|
||||
}
|
||||
return context;
|
||||
};
|
||||
Reference in New Issue
Block a user