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 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>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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={[
|
||||||
|
|||||||
@@ -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
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