207 lines
6.1 KiB
TypeScript
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,
|
|
},
|
|
});
|