wavelength_app/components/home/Countdown.tsx

207 lines
6.1 KiB
TypeScript

import React, { useEffect, useState } from 'react';
import { StyleSheet, ActivityIndicator, TouchableOpacity } from 'react-native';
import { ThemedText, ThemedView } from '@/components/theme/Theme';
import { Countdown, Relationship, User } from '@/constants/Types';
import { getCountdown } from '@/constants/APIs';
import TextButton from '@/components/theme/buttons/TextButton';
import {
getCountdown as getCountdownFromSecureStore,
getUser,
getRelationship,
saveCountdown,
} from '@/components/services/SecureStore';
import CountdownChangeDateModal from '@/components/home/CountdownChangeDateModal';
const CountdownView = () => {
const [countdownData, setCountdownData] = useState({
days: 0,
hours: 0,
minutes: 0,
seconds: 0,
});
const [countdown, setCountdown] = useState<Countdown | null>(null);
const [isLoading, setIsLoading] = useState(true);
const [isDateModalOpen, setIsDateModalOpen] = useState(false);
const [user, setUser] = useState<User | null>(null);
const [relationship, setRelationship] = useState<Relationship | null>(null);
useEffect(() => {
const loadData = async () => {
setIsLoading(true);
const userData = await getUser();
setUser(userData);
const relationshipData = await getRelationship();
setRelationship(relationshipData);
const countdownFromSecureStore = await getCountdownFromSecureStore();
if (countdownFromSecureStore) {
setCountdown(countdownFromSecureStore);
} else if (userData) {
const countdownFromServer = await getCountdown(userData.id);
if (countdownFromServer) {
setCountdown(countdownFromServer);
await saveCountdown(countdownFromServer);
}
}
setIsLoading(false);
};
loadData();
}, []);
useEffect(() => {
if (countdown === null) return;
const interval = setInterval(() => {
const now = new Date();
const diff = new Date(countdown.date).getTime() - now.getTime();
const days = Math.floor(diff / (1000 * 60 * 60 * 24));
const hours = Math.floor((diff % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
const minutes = Math.floor((diff % (1000 * 60 * 60)) / (1000 * 60));
const seconds = Math.floor((diff % (1000 * 60)) / 1000);
setCountdownData({ days, hours, minutes, seconds });
if (diff <= 0) {
clearInterval(interval);
setCountdownData({ days: 0, hours: 0, minutes: 0, seconds: 0 });
}
}, 1000);
return () => clearInterval(interval);
}, [countdown]);
const handleCountdownUpdate = async (newDate: Date, newTitle: string) => {
if (relationship) {
const newCountdown: Countdown = countdown
? { ...countdown, date: newDate, title: newTitle }
: {
id: 0, // This will be set by the server
relationshipId: relationship.id,
title: newTitle ? newTitle : 'Countdown to Next Visit',
date: newDate,
createdAt: new Date(),
};
setCountdown(newCountdown);
await saveCountdown(newCountdown);
}
};
if (isLoading) {
return (
<ThemedView style={styles.container}>
<ActivityIndicator size='large' color='#0000ff' />
</ThemedView>
);
}
if (!relationship) {
return (
<ThemedView style={styles.container}>
<ThemedText>You are not in a relationship yet.</ThemedText>
</ThemedView>
);
}
if (!countdown) {
return (
<ThemedView style={styles.container}>
<ThemedText>No countdown set yet.</ThemedText>
<TextButton
width={320} height={68}
text='Set Countdown'
fontSize={24}
onPress={() => setIsDateModalOpen(true)}
/>
</ThemedView>
);
}
return (
<ThemedView style={styles.innerContainer}>
<ThemedText style={styles.title}>
{countdown?.title ?? 'Countdown til Next Visit'}
</ThemedText>
<ThemedView style={styles.countdownContainer}>
<CountdownItem
value={countdownData.days}
label={countdownData.days === 1 ? 'Day' : 'Days'}
/>
<CountdownItem
value={countdownData.hours}
label={countdownData.hours === 1 ? 'Hour' : 'Hours'}
/>
<CountdownItem
value={countdownData.minutes}
label={countdownData.minutes === 1 ? 'Minute' : 'Minutes'}
/>
<CountdownItem
value={countdownData.seconds}
label={countdownData.seconds === 1 ? 'Second' : 'Seconds'}
/>
</ThemedView>
<TextButton
width={160} height={48}
text='Change Countdown'
fontSize={18}
onPress={() => setIsDateModalOpen(true)}
/>
{user && countdown && (
<CountdownChangeDateModal
user={user}
isVisible={isDateModalOpen}
onClose={() => setIsDateModalOpen(false)}
onDateChange={handleCountdownUpdate}
currentCountdown={countdown}
/>
)}
</ThemedView>
);
};
export default CountdownView;
const CountdownItem = ({value, label}: { value: number, label: string }) => {
return (
<ThemedView style={styles.countdownItem}>
<ThemedText style={styles.countdownValue}>{value}</ThemedText>
<ThemedText style={styles.countdownLabel}>{label}</ThemedText>
</ThemedView>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: 'transparent',
},
innerContainer: {
flex: 1,
alignItems: 'center',
paddingHorizontal: 10,
backgroundColor: 'transparent',
},
title: {
fontSize: 24,
lineHeight: 32,
fontWeight: '600',
textAlign: 'center',
marginHorizontal: 'auto',
},
countdownContainer: {
flexDirection: 'row',
justifyContent: 'space-around',
alignItems: 'center',
width: '90%',
backgroundColor: 'transparent',
marginVertical: 10,
},
countdownItem: {
alignItems: 'center',
marginHorizontal: 5,
backgroundColor: 'transparent',
},
countdownValue: {
fontSize: 28,
lineHeight: 42,
fontWeight: 'bold',
},
countdownLabel: {
fontSize: 18,
lineHeight: 24,
},
});