Sync cities between prayers

This commit is contained in:
Mekan1206
2025-09-20 12:06:56 +05:00
parent 30dd67ecdf
commit 803bbfc30f
4 changed files with 100 additions and 67 deletions

View File

@@ -4,6 +4,7 @@ import { useColorScheme, View } from 'react-native';
import Colors from '@/constants/Colors'; import Colors from '@/constants/Colors';
import i18n from '@/i18n'; 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/ * You can explore the built-in icon families and icons on the web at https://icons.expo.fyi/
@@ -19,6 +20,7 @@ export default function TabLayout() {
const colorScheme = 'dark'; // Force dark mode const colorScheme = 'dark'; // Force dark mode
return ( return (
<CityProvider>
<Tabs <Tabs
screenOptions={{ screenOptions={{
tabBarActiveTintColor: Colors[colorScheme].tint, tabBarActiveTintColor: Colors[colorScheme].tint,
@@ -57,5 +59,6 @@ export default function TabLayout() {
}} }}
/> />
</Tabs> </Tabs>
</CityProvider>
); );
} }

View File

@@ -1,11 +1,11 @@
import { Pressable, ScrollView, StyleSheet, Text, View } from 'react-native'; import { Pressable, ScrollView, StyleSheet, Text, View } from 'react-native';
import { useCallback, useEffect, useState } from 'react'; import { useCallback, useEffect, useState } from 'react';
import { useSafeAreaInsets } from 'react-native-safe-area-context'; import { useSafeAreaInsets } from 'react-native-safe-area-context';
import AsyncStorage from '@react-native-async-storage/async-storage';
import { getPrayerTimes, cities } from '../../utils/prayerTimeCalculator'; import { getPrayerTimes, cities } from '../../utils/prayerTimeCalculator';
import i18n from '../../i18n'; import i18n from '../../i18n';
import Colors from '../../constants/Colors'; import Colors from '../../constants/Colors';
import { useCity } from '../../context/CityContext';
type Prayer = { type Prayer = {
name: string; name: string;
@@ -17,26 +17,11 @@ type City = keyof typeof cities;
export default function TabIndex() { export default function TabIndex() {
const colorScheme = 'dark'; const colorScheme = 'dark';
const theme = Colors[colorScheme ?? 'light']; const theme = Colors[colorScheme ?? 'light'];
const [selectedCity, setSelectedCity] = useState<City>('Makkah'); const { selectedCity, setSelectedCity } = useCity();
const [prayerTimes, setPrayerTimes] = useState<Prayer[]>([]); const [prayerTimes, setPrayerTimes] = useState<Prayer[]>([]);
const [nextPrayerName, setNextPrayerName] = useState<string | null>(null); const [nextPrayerName, setNextPrayerName] = useState<string | null>(null);
const insets = useSafeAreaInsets(); 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 } = { const prayerNameMapping: { [key: string]: string } = {
fajr: i18n.t('fajr'), fajr: i18n.t('fajr'),
dhuhr: i18n.t('dhuhr'), dhuhr: i18n.t('dhuhr'),
@@ -82,15 +67,6 @@ export default function TabIndex() {
return () => clearInterval(interval); return () => clearInterval(interval);
}, [updatePrayerTimes]); }, [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 renderPrayerTime = (prayer: Prayer) => {
const isNextPrayer = prayer.name === nextPrayerName; const isNextPrayer = prayer.name === nextPrayerName;
return ( return (
@@ -119,7 +95,7 @@ export default function TabIndex() {
{(Object.keys(cities) as City[]).map((city) => ( {(Object.keys(cities) as City[]).map((city) => (
<Pressable <Pressable
key={city} key={city}
onPress={() => handleCityChange(city)} onPress={() => setSelectedCity(city)}
style={[styles.cityButton, { backgroundColor: theme.secondary }, selectedCity === city && [styles.activeCityButton, { backgroundColor: theme.tint }]]}> style={[styles.cityButton, { backgroundColor: theme.secondary }, selectedCity === city && [styles.activeCityButton, { backgroundColor: theme.tint }]]}>
<Text <Text
style={[ style={[

View File

@@ -4,7 +4,7 @@ import Colors from '@/constants/Colors';
import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons'; import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons';
import { getPrayerTimes, cities } from '@/utils/prayerTimeCalculator'; import { getPrayerTimes, cities } from '@/utils/prayerTimeCalculator';
import i18n from '@/i18n'; import i18n from '@/i18n';
import { createIconSetFromFontello } from 'react-native-vector-icons'; import { useCity } from '../context/CityContext';
type Prayer = { type Prayer = {
name: string; name: string;
@@ -25,7 +25,7 @@ export default function PrayerTimeCard() {
const [prayerTimes, setPrayerTimes] = useState<Prayer[]>([]); const [prayerTimes, setPrayerTimes] = useState<Prayer[]>([]);
const [nextPrayer, setNextPrayer] = useState<{ name: string; time: string } | null>(null); const [nextPrayer, setNextPrayer] = useState<{ name: string; time: string } | null>(null);
const [remainingTime, setRemainingTime] = useState(''); const [remainingTime, setRemainingTime] = useState('');
const [selectedCity, setSelectedCity] = useState<keyof typeof cities>('Makkah'); const { selectedCity, setSelectedCity } = useCity();
useEffect(() => { useEffect(() => {
const times = getPrayerTimes(selectedCity); const times = getPrayerTimes(selectedCity);

54
context/CityContext.tsx Normal file
View 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;
};