187 lines
5.7 KiB
TypeScript
187 lines
5.7 KiB
TypeScript
import React, { useState, useEffect } from 'react';
|
|
import { View, Text, StyleSheet, ImageBackground, Pressable } from 'react-native';
|
|
import Colors from '@/constants/Colors';
|
|
import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons';
|
|
import { getPrayerTimes, cities } from '@/utils/prayerTimeCalculator';
|
|
import i18n from '@/i18n';
|
|
import { useCity } from '../context/CityContext';
|
|
|
|
type Prayer = {
|
|
name: string;
|
|
time: string;
|
|
icon: string;
|
|
};
|
|
|
|
const prayerIconMapping: { [key: string]: string } = {
|
|
fajr: 'weather-sunset-up',
|
|
sunrise: 'weather-sunny',
|
|
dhuhr: 'weather-partly-cloudy',
|
|
asr: 'weather-cloudy',
|
|
maghrib: 'weather-sunset-down',
|
|
isha: 'weather-night',
|
|
};
|
|
|
|
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 } = useCity();
|
|
|
|
useEffect(() => {
|
|
const times = getPrayerTimes(selectedCity);
|
|
const prayers: Prayer[] = Object.keys(prayerIconMapping).map(key => ({
|
|
name: i18n.t(key),
|
|
time: times[key] || '-----',
|
|
icon: prayerIconMapping[key],
|
|
}));
|
|
setPrayerTimes(prayers);
|
|
|
|
const interval = setInterval(() => {
|
|
calculateRemainingTime();
|
|
}, 1000);
|
|
|
|
const calculateRemainingTime = () => {
|
|
const now = new Date();
|
|
let nextPrayerInfo: { name: string; time: string } | null = null;
|
|
|
|
for (const prayer of prayers) {
|
|
if (prayer.time === '-----') continue;
|
|
const [hours, minutes] = prayer.time.split(':').map(Number);
|
|
const prayerDate = new Date(now.getFullYear(), now.getMonth(), now.getDate(), hours, minutes);
|
|
if (prayerDate > now) {
|
|
nextPrayerInfo = { name: prayer.name, time: prayer.time };
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!nextPrayerInfo && prayers.length > 0) {
|
|
const firstPrayer = prayers.find(p => p.time !== '-----');
|
|
if (firstPrayer) {
|
|
nextPrayerInfo = { name: firstPrayer.name, time: firstPrayer.time };
|
|
}
|
|
}
|
|
|
|
setNextPrayer(current => {
|
|
if (current?.name === nextPrayerInfo?.name) return current;
|
|
return nextPrayerInfo;
|
|
});
|
|
|
|
if (nextPrayerInfo) {
|
|
const [hours, minutes] = nextPrayerInfo.time.split(':').map(Number);
|
|
let prayerDate = new Date(now.getFullYear(), now.getMonth(), now.getDate(), hours, minutes);
|
|
|
|
if (prayerDate < now) {
|
|
prayerDate.setDate(prayerDate.getDate() + 1);
|
|
}
|
|
|
|
const diff = prayerDate.getTime() - now.getTime();
|
|
const h = Math.floor(diff / (1000 * 60 * 60));
|
|
const m = Math.floor((diff % (1000 * 60 * 60)) / (1000 * 60));
|
|
const s = Math.floor((diff % (1000 * 60)) / 1000);
|
|
setRemainingTime(`${h.toString().padStart(2, '0')}:${m.toString().padStart(2, '0')}:${s.toString().padStart(2, '0')}`);
|
|
} else {
|
|
setRemainingTime('');
|
|
}
|
|
}
|
|
|
|
calculateRemainingTime();
|
|
|
|
return () => clearInterval(interval);
|
|
}, [selectedCity]);
|
|
|
|
return (
|
|
<ImageBackground
|
|
source={{ uri: 'https://i.imgur.com/your-image.jpg' }} // Replace with a real image URL
|
|
style={styles.container}
|
|
imageStyle={{ borderRadius: 15 }}
|
|
>
|
|
<View style={styles.overlay}>
|
|
<View style={styles.header}>
|
|
<View style={styles.citySelector}>
|
|
{(Object.keys(cities) as Array<keyof typeof cities>).map(city => (
|
|
<Pressable key={city} onPress={() => setSelectedCity(city)} style={[styles.cityButton, selectedCity === city && styles.activeCity]}>
|
|
<Text style={styles.cityButtonText}>{i18n.t(city)}</Text>
|
|
</Pressable>
|
|
))}
|
|
</View>
|
|
</View>
|
|
<Text style={styles.remainingTimeLabel}>
|
|
{nextPrayer ? i18n.t('leftOnPrayer', { prayerName: nextPrayer.name }) : i18n.t('prayerTimes')}
|
|
</Text>
|
|
<Text style={styles.remainingTime}>{remainingTime}</Text>
|
|
<View style={styles.prayerTimesContainer}>
|
|
{prayerTimes.map((prayer, index) => (
|
|
<View key={index} style={styles.prayerTimeItem}>
|
|
<MaterialCommunityIcons name={prayer.icon} size={24} color={Colors.dark.text} />
|
|
<Text style={styles.prayerName}>{prayer.name}</Text>
|
|
<Text style={styles.prayerTime}>{prayer.time}</Text>
|
|
</View>
|
|
))}
|
|
</View>
|
|
</View>
|
|
</ImageBackground>
|
|
);
|
|
}
|
|
|
|
const styles = StyleSheet.create({
|
|
container: {
|
|
marginVertical: 20,
|
|
borderRadius: 15,
|
|
},
|
|
overlay: {
|
|
backgroundColor: 'rgba(0,0,0,0.5)',
|
|
borderRadius: 15,
|
|
padding: 20,
|
|
},
|
|
header: {
|
|
flexDirection: 'row',
|
|
alignItems: 'center',
|
|
marginBottom: 20,
|
|
justifyContent: 'center',
|
|
},
|
|
citySelector: {
|
|
flexDirection: 'row',
|
|
backgroundColor: Colors.dark.secondary,
|
|
borderRadius: 10,
|
|
},
|
|
cityButton: {
|
|
paddingVertical: 8,
|
|
paddingHorizontal: 15,
|
|
borderRadius: 10,
|
|
},
|
|
activeCity: {
|
|
backgroundColor: Colors.dark.tint,
|
|
},
|
|
cityButtonText: {
|
|
color: Colors.dark.text,
|
|
fontWeight: 'bold',
|
|
},
|
|
remainingTimeLabel: {
|
|
color: Colors.dark.textSecondary,
|
|
textAlign: 'center',
|
|
},
|
|
remainingTime: {
|
|
color: Colors.dark.text,
|
|
fontSize: 48,
|
|
fontWeight: 'bold',
|
|
textAlign: 'center',
|
|
marginVertical: 10,
|
|
},
|
|
prayerTimesContainer: {
|
|
flexDirection: 'row',
|
|
justifyContent: 'space-around',
|
|
marginTop: 20,
|
|
},
|
|
prayerTimeItem: {
|
|
alignItems: 'center',
|
|
},
|
|
prayerName: {
|
|
color: Colors.dark.text,
|
|
marginTop: 5,
|
|
},
|
|
prayerTime: {
|
|
color: Colors.dark.textSecondary,
|
|
fontSize: 12,
|
|
},
|
|
});
|