diff --git a/app/(tabs)/index.tsx b/app/(tabs)/index.tsx index 76a8bd8..0c3032f 100644 --- a/app/(tabs)/index.tsx +++ b/app/(tabs)/index.tsx @@ -3,6 +3,7 @@ import { StyleSheet } from 'react-native'; import { ThemedView } from '@/components/theme/Theme'; import UserInfo from '@/components/home/UserInfo'; import RelationshipView from '@/components/home/RelationshipView'; +import CountdownView from '@/components/home/Countdown'; const IndexScreen = () => { const [pfpUrl, setPfpUrl] = useState(null); @@ -12,6 +13,7 @@ const IndexScreen = () => { return ( + diff --git a/assets/images/adaptive-icon.png b/assets/images/adaptive-icon.png index fa3c871..7b5e242 100644 Binary files a/assets/images/adaptive-icon.png and b/assets/images/adaptive-icon.png differ diff --git a/assets/images/default-profile.png b/assets/images/default-profile.png index 0f5b1ff..e535732 100644 Binary files a/assets/images/default-profile.png and b/assets/images/default-profile.png differ diff --git a/assets/images/favicon.png b/assets/images/favicon.png index 11877b6..4792bf3 100644 Binary files a/assets/images/favicon.png and b/assets/images/favicon.png differ diff --git a/assets/images/icon.png b/assets/images/icon.png index fa3c871..7b5e242 100644 Binary files a/assets/images/icon.png and b/assets/images/icon.png differ diff --git a/assets/images/splash.png b/assets/images/splash.png index 3f3dd3a..3ad9315 100644 Binary files a/assets/images/splash.png and b/assets/images/splash.png differ diff --git a/components/auth/SignInScreen.tsx b/components/auth/SignInScreen.tsx index e2555b0..bb0f264 100644 --- a/components/auth/SignInScreen.tsx +++ b/components/auth/SignInScreen.tsx @@ -1,8 +1,10 @@ import React from 'react'; import * as AppleAuthentication from 'expo-apple-authentication'; -import { StyleSheet, Alert } from 'react-native'; -import { ThemedView } from '@/components/theme/Theme'; +import { StyleSheet, Alert, ImageBackground } from 'react-native'; +import { ThemedText, ThemedView } from '@/components/theme/Theme'; +import { SafeAreaView, SafeAreaProvider } from 'react-native-safe-area-context'; import { useColorScheme } from '@/hooks/useColorScheme'; +import { Colors } from '@/constants/Colors'; import * as Notifications from 'expo-notifications'; import Constants from 'expo-constants'; import { saveUser, saveInitialData } from '@/components/services/SecureStore'; @@ -13,6 +15,7 @@ import { } from '@/constants/APIs'; import type { InitialData, User } from '@/constants/Types'; + const SignInScreen = ({onSignIn}: {onSignIn: () => void}) => { const scheme = useColorScheme() ?? 'dark'; @@ -86,16 +89,27 @@ const SignInScreen = ({onSignIn}: {onSignIn: () => void}) => { return ( - + + + Wavelength + + + ); }; @@ -104,9 +118,23 @@ export default SignInScreen; const styles = StyleSheet.create({ container: { flex: 1, + }, + background: { + flex: 1, justifyContent: 'center', alignItems: 'center', }, + title: { + fontSize: 48, + lineHeight: 48, + fontWeight: 'bold', + marginBottom: 80, + textShadowOffset: { + width: 1, + height: 1, + }, + textShadowRadius: 5, + }, button: { width: 200, height: 45, diff --git a/components/home/Countdown.tsx b/components/home/Countdown.tsx index eee1673..8bec823 100644 --- a/components/home/Countdown.tsx +++ b/components/home/Countdown.tsx @@ -1,7 +1,207 @@ import React, { useEffect, useState } from 'react'; import { StyleSheet, ActivityIndicator, TouchableOpacity } from 'react-native'; import { ThemedText, ThemedView } from '@/components/theme/Theme'; -import { SafeAreaView } from 'react-native-safe-area-context'; +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(null); + const [isLoading, setIsLoading] = useState(true); + const [isDateModalOpen, setIsDateModalOpen] = useState(false); + const [user, setUser] = useState(null); + const [relationship, setRelationship] = useState(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) => { + if (relationship) { + const newCountdown: Countdown = countdown + ? { ...countdown, date: newDate } + : { + id: 0, // This will be set by the server + relationshipId: relationship.id, + title: 'Countdown to Next Visit', + date: newDate, + createdAt: new Date(), + }; + setCountdown(newCountdown); + await saveCountdown(newCountdown); + } + }; + + if (isLoading) { + return ( + + + + ); + } + if (!relationship) { + return ( + + You are not in a relationship yet. + + ); + } + + if (!countdown) { + return ( + + No countdown set yet. + setIsDateModalOpen(true)} + /> + + ); + } + + return ( + + + {countdown?.title ?? 'Countdown til Next Visit'} + + + + + + + + setIsDateModalOpen(true)} + /> + {user && countdown && ( + setIsDateModalOpen(false)} + onDateChange={handleCountdownUpdate} + currentCountdown={countdown} + /> + )} + + ); + +}; +export default CountdownView; + +const CountdownItem = ({value, label}: { value: number, label: string }) => { + return ( + + {value} + {label} + + ); +}; + +const styles = StyleSheet.create({ + container: { + flex: 1, + backgroundColor: 'transparent', + }, + innerContainer: { + flex: 1, + justifyContent: 'center', + alignItems: 'center', + paddingHorizontal: 10, + backgroundColor: 'transparent', + }, + title: { + fontSize: 32, + lineHeight: 32, + fontWeight: '600', + textAlign: 'center', + marginHorizontal: 'auto', + }, + countdownContainer: { + flexDirection: 'row', + justifyContent: 'space-around', + alignItems: 'center', + width: '100%', + backgroundColor: 'transparent', + marginVertical: 20, + }, + countdownItem: { + alignItems: 'center', + marginHorizontal: 10, + backgroundColor: 'transparent', + }, + countdownValue: { + fontSize: 32, + lineHeight: 42, + fontWeight: 'bold', + }, + countdownLabel: { + fontSize: 18, + lineHeight: 24, + }, +}); diff --git a/components/home/CountdownChangeDateModal.tsx b/components/home/CountdownChangeDateModal.tsx new file mode 100644 index 0000000..02e1e65 --- /dev/null +++ b/components/home/CountdownChangeDateModal.tsx @@ -0,0 +1,162 @@ +import React, { useState } from 'react'; +import { StyleSheet, Modal } from 'react-native'; +import { ThemedText, ThemedView } from '@/components/theme/Theme'; +import DateTimePicker from '@react-native-community/datetimepicker'; +import { Countdown, User } from '@/constants/Types'; +import { setCountdown } from '@/constants/APIs'; +import TextButton from '@/components/theme/buttons/TextButton'; + +type ChangeDateModalProps = { + user: User; + isVisible: boolean; + onClose: () => void; + onDateChange: (date: Date) => void; + currentCountdown?: Countdown; +}; + +const ChangeDateModal = ({ + user, isVisible, onClose, onDateChange, currentCountdown +}: ChangeDateModalProps) => { + const [date, setDate] = useState(currentCountdown ? new Date(currentCountdown.date) : new Date()); + + const handleDateChange = (event: any, selectedDate?: Date) => { + const currentDate = selectedDate ?? date; + setDate(currentDate); + }; + + const handleTimeChange = (event: any, selectedTime?: Date) => { + const currentTime = selectedTime ?? date; + setDate(currentTime); + }; + + const handleSave = async () => { + try { + let updatedCountdown: Countdown; + if (currentCountdown) { + updatedCountdown = { ...currentCountdown, date: date }; + await setCountdown(user.id, updatedCountdown); + onDateChange(date); + onClose(); + } + } catch (error) { + console.error('Error saving countdown:', error); + } + }; + + return ( + + + + + Set New Countdown + + + + + + + + + + + + + + + + + ); + +}; +export default ChangeDateModal; + +const styles = StyleSheet.create({ + centeredView: { + flex: 1, + justifyContent: 'center', + alignItems: 'center', + backgroundColor: 'transparent', + }, + modalView: { + margin: 10, + padding: 35, + borderRadius: 40, + alignItems: 'center', + shadowColor: '#000', + shadowOffset: { + width: 0, + height: 2, + }, + shadowOpacity: 0.25, + shadowRadius: 3.84, + elevation: 5, + width: '80%', + }, + modalText: { + marginBottom: 20, + textAlign: 'center', + fontWeight: 'bold', + fontSize: 24, + lineHeight: 32, + }, + container: { + flexDirection: 'row', + justifyContent: 'space-between', + alignItems: 'center', + margin: 'auto', + marginBottom: 20, + backgroundColor: 'transparent', + }, + buttonContainer: { + flexDirection: 'row', + justifyContent: 'space-between', + alignItems: 'center', + margin: 'auto', + backgroundColor: 'transparent', + }, + dateContainer: { + width: '50%', + justifyContent: 'center', + alignItems: 'center', + margin: 'auto', + backgroundColor: 'transparent', + }, + timeContainer: { + width: '50%', + justifyContent: 'center', + alignItems: 'center', + backgroundColor: 'transparent', + minWidth: 120, + }, +}); diff --git a/components/home/TestPush.tsx b/components/home/TestPush.tsx deleted file mode 100644 index fefd705..0000000 --- a/components/home/TestPush.tsx +++ /dev/null @@ -1,74 +0,0 @@ -import React, { useEffect, useState } from 'react'; -import { StyleSheet, Alert } from 'react-native'; -import { ThemedText } from '@/components/theme/Theme'; -import { Colors } from '@/constants/Colors'; -import { useColorScheme } from '@/hooks/useColorScheme'; -import FontAwesome from '@expo/vector-icons/FontAwesome'; -import Button from '@/components/theme/buttons/DefaultButton'; -import { getUser } from '@/components/services/SecureStore'; -import { sendPushNotification } from '@/components/services/notifications/PushNotificationManager'; -import type { NotificationMessage } from '@/constants/Types'; - -const TestPush = () => { - const scheme = useColorScheme() ?? 'dark'; - const [pushToken, setPushToken] = useState(null); - - useEffect(() => { - const fetchUserData = async () => { - const user = await getUser(); - if (user) { - setPushToken(user.pushToken); - } - }; - fetchUserData(); - }, []); - - const message: NotificationMessage = { - sound: 'default', - title: 'Test push notification', - body: 'This is a test push notification', - data: { - test: 'test', - }, - }; - - const handleSendPushNotification = async () => { - try { - await sendPushNotification(pushToken, message); - Alert.alert('Success', 'Push notification sent successfully.'); - } catch (error) { - Alert.alert('Error', 'Failed to send push notification.'); - } - }; - - return ( - - ); -}; -export default TestPush; - -const styles = StyleSheet.create({ - buttonLabel: { - fontSize: 16, - }, - buttonIcon: { - paddingRight: 8, - }, -}); diff --git a/components/theme/buttons/DefaultButton.tsx b/components/theme/buttons/DefaultButton.tsx index 3ac69e2..9a3bd6e 100644 --- a/components/theme/buttons/DefaultButton.tsx +++ b/components/theme/buttons/DefaultButton.tsx @@ -2,6 +2,7 @@ import { StyleSheet, Pressable } from "react-native"; import { ThemedView } from "@/components/theme/Theme"; import { Colors } from '@/constants/Colors'; import { useColorScheme } from '@/hooks/useColorScheme'; +import { StyleProp, ViewStyle } from 'react-native'; const DEFAULT_WIDTH = 320; const DEFAULT_HEIGHT = 68; diff --git a/package.json b/package.json index 25e27e8..60c8960 100644 --- a/package.json +++ b/package.json @@ -15,6 +15,7 @@ }, "dependencies": { "@expo/vector-icons": "^14.0.4", + "@react-native-community/datetimepicker": "8.0.1", "@react-navigation/native": "^6.1.18", "@teovilla/react-native-web-maps": "^0.9.5", "@types/lodash.debounce": "^4.0.9", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ac20d91..5e7ba63 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -11,6 +11,9 @@ importers: '@expo/vector-icons': specifier: ^14.0.4 version: 14.0.4 + '@react-native-community/datetimepicker': + specifier: 8.0.1 + version: 8.0.1(react-native@0.74.5(@babel/core@7.26.0)(@babel/preset-env@7.25.9(@babel/core@7.26.0))(@types/react@18.2.79)(react@18.2.0))(react@18.2.0) '@react-navigation/native': specifier: ^6.1.18 version: 6.1.18(react-native@0.74.5(@babel/core@7.26.0)(@babel/preset-env@7.25.9(@babel/core@7.26.0))(@types/react@18.2.79)(react@18.2.0))(react@18.2.0) @@ -131,10 +134,10 @@ importers: version: 18.3.0 jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@22.8.0) + version: 29.7.0(@types/node@22.8.2) jest-expo: specifier: ~51.0.4 - version: 51.0.4(@babel/core@7.26.0)(jest@29.7.0(@types/node@22.8.0))(react@18.2.0) + version: 51.0.4(@babel/core@7.26.0)(jest@29.7.0(@types/node@22.8.2))(react@18.2.0) react-test-renderer: specifier: 18.2.0 version: 18.2.0(react@18.2.0) @@ -269,8 +272,8 @@ packages: resolution: {integrity: sha512-llL88JShoCsth8fF8R4SJnIn+WLvR6ccFxu1H3FlMhDontdcmZWf2HgIZ7AIqV3Xcck1idlohrN4EUBQz6klbw==} engines: {node: '>=6.9.0'} - '@babel/parser@7.26.0': - resolution: {integrity: sha512-aP8x5pIw3xvYr/sXT+SEUwyhrXT8rUJRZltK/qN3Db80dcKpTett8cJxHyjk+xYSVXvNnl2SfcJVjbwxpOSscA==} + '@babel/parser@7.26.1': + resolution: {integrity: sha512-reoQYNiAJreZNsJzyrDNzFQ+IQ5JFiIzAHJg9bn94S3l+4++J7RsIhNMoB+lgP/9tpmiAQqspv+xfdxTSzREOw==} engines: {node: '>=6.0.0'} hasBin: true @@ -1216,6 +1219,16 @@ packages: engines: {node: '>=18'} hasBin: true + '@react-native-community/datetimepicker@8.0.1': + resolution: {integrity: sha512-4BO0t3geMNNw9cIIm9p9FNUzwMXexdzD4pAH0AaUAycs3BS71HLrX8jHbrI7nzq/+8O7cLAXn5Gudte+YpTV8Q==} + peerDependencies: + react: '*' + react-native: '*' + react-native-windows: '*' + peerDependenciesMeta: + react-native-windows: + optional: true + '@react-native/assets-registry@0.74.87': resolution: {integrity: sha512-1XmRhqQchN+pXPKEKYdpJlwESxVomJOxtEnIkbo7GAlaN2sym84fHEGDXAjLilih5GVPpcpSmFzTy8jx3LtaFg==} engines: {node: '>=18'} @@ -1475,11 +1488,11 @@ packages: '@types/node-forge@1.3.11': resolution: {integrity: sha512-FQx220y22OKNTqaByeBGqHWYz4cl94tpcxeFdvBo3wjG6XPBuZ0BNgNZRV5J5TFmmcsJ4IzsLkmGRiQbnYsBEQ==} - '@types/node@18.19.59': - resolution: {integrity: sha512-vizm2EqwV/7Zay+A6J3tGl9Lhr7CjZe2HmWS988sefiEmsyP9CeXEleho6i4hJk/8UtZAo0bWN4QPZZr83RxvQ==} + '@types/node@18.19.60': + resolution: {integrity: sha512-cYRj7igVqgxhlHFdBHHpU2SNw3+dN2x0VTZJtLYk6y/ieuGN4XiBgtDjYVktM/yk2y/8pKMileNc6IoEzEJnUw==} - '@types/node@22.8.0': - resolution: {integrity: sha512-84rafSBHC/z1i1E3p0cJwKA+CfYDNSXX9WSZBRopjIzLET8oNt6ht2tei4C7izwDeEiLLfdeSVBv1egOH916hg==} + '@types/node@22.8.2': + resolution: {integrity: sha512-NzaRNFV+FZkvK/KLCsNdTvID0SThyrs5SHB6tsD/lajr22FGC73N2QeDPM2wHtVde8mgcXuSsHQkH5cX1pbPLw==} '@types/prop-types@15.7.13': resolution: {integrity: sha512-hCZTSvwbzWGvhqxp/RqVqwU999pBf2vp7hzIjiYOsl8wqOmUxkQ6ddw1cV3l8811+kdUFus/q4d1Y3E3SyEifA==} @@ -1524,6 +1537,7 @@ packages: '@xmldom/xmldom@0.7.13': resolution: {integrity: sha512-lm2GW5PkosIzccsaZIz7tp8cPADSIlIHWDFTR1N0SzfinhhYgeIQjFMz4rYzanCScr3DqQLeomUDArp6MWKm+g==} engines: {node: '>=10.0.0'} + deprecated: this version is no longer supported, please update to at least 0.8.* '@xmldom/xmldom@0.8.10': resolution: {integrity: sha512-2WALfTl4xo2SkGCYRt6rDTFfk9R1czmBvUQy12gK2KuRKIpWEhcbbzy8EZXtz/jkRqHX8bFEc6FC1HjX4TUWYw==} @@ -1551,8 +1565,8 @@ packages: resolution: {integrity: sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==} engines: {node: '>=0.4.0'} - acorn@8.13.0: - resolution: {integrity: sha512-8zSiw54Oxrdym50NlZ9sUusyO1Z1ZchgRLWRaK6c86XJFClyCgFKetdowBg5bKxyp/u+CDBJG4Mpp0m3HLZl9w==} + acorn@8.14.0: + resolution: {integrity: sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==} engines: {node: '>=0.4.0'} hasBin: true @@ -1847,8 +1861,8 @@ packages: resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} engines: {node: '>=10'} - caniuse-lite@1.0.30001669: - resolution: {integrity: sha512-DlWzFDJqstqtIVx1zeSpIMLjunf5SmwOw0N2Ck/QSQdS8PLS4+9HrLaYei4w8BIAL7IB/UEDu889d8vhCTPA0w==} + caniuse-lite@1.0.30001674: + resolution: {integrity: sha512-jOsKlZVRnzfhLojb+Ykb+gyUSp9Xb57So+fAiFlLzzTKpqg8xxSav0e40c8/4F/v9N8QSvrRRaLeVzQbLqomYw==} chalk@2.4.2: resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} @@ -2216,8 +2230,8 @@ packages: ee-first@1.1.1: resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} - electron-to-chromium@1.5.45: - resolution: {integrity: sha512-vOzZS6uZwhhbkZbcRyiy99Wg+pYFV5hk+5YaECvx0+Z31NR3Tt5zS6dze2OepT6PCTzVzT0dIJItti+uAW5zmw==} + electron-to-chromium@1.5.49: + resolution: {integrity: sha512-ZXfs1Of8fDb6z7WEYZjXpgIRF6MEu8JdeGA0A40aZq6OQbS+eJpnnV49epZRna2DU/YsEjSQuGtQPPtvt6J65A==} emittery@0.13.1: resolution: {integrity: sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==} @@ -3825,8 +3839,8 @@ packages: resolution: {integrity: sha512-Nt/a5SfCLiTnQAjx3fHlqp8hRgTL3z7kTQZzvIMS9uCAepnCyjpdEc6M/sz69WqMBdaDBw9sF1F1UaHROYzGkQ==} engines: {node: '>=10'} - parse5@7.2.0: - resolution: {integrity: sha512-ZkDsAOcxsUMZ4Lz5fVciOehNcJ+Gb8gTzcA4yl3wnc273BAybYWrQ+Ks/OjCjSEpjvQkDSeZbybK9qj2VHHdGA==} + parse5@7.2.1: + resolution: {integrity: sha512-BuBYQYlv1ckiPdQi/ohiivi9Sagc9JG+Ozs0r7b/0iK3sKmrb0b9FdWdBbOdx6hBCM/F9Ir82ofnBhtZOjCRPQ==} parseurl@1.3.3: resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} @@ -4169,8 +4183,8 @@ packages: regjsgen@0.8.0: resolution: {integrity: sha512-RvwtGe3d7LvWiDQXeQw8p5asZUmfU1G/l6WbUXeHta7Y2PEIvBTwH6E2EfmYUK8pxcxEdEmaomqyp0vZZ7C+3Q==} - regjsparser@0.11.1: - resolution: {integrity: sha512-1DHODs4B8p/mQHU9kr+jv8+wIC9mtG4eBHxWxIq5mhjE3D5oORhCc6deRKzTjs9DcfRFmj9BHSDguZklqCGFWQ==} + regjsparser@0.11.2: + resolution: {integrity: sha512-3OGZZ4HoLJkkAZx/48mTXJNlmqTGOzc0o9OWQPuWpkOlXXPbyN6OafCcoXUnBqE2D3f/T5L+pWc1kdEmnfnRsA==} hasBin: true remove-trailing-slash@0.1.1: @@ -5121,7 +5135,7 @@ snapshots: '@babel/helper-compilation-targets': 7.25.9 '@babel/helper-module-transforms': 7.26.0(@babel/core@7.26.0) '@babel/helpers': 7.26.0 - '@babel/parser': 7.26.0 + '@babel/parser': 7.26.1 '@babel/template': 7.25.9 '@babel/traverse': 7.25.9 '@babel/types': 7.26.0 @@ -5143,7 +5157,7 @@ snapshots: '@babel/generator@7.26.0': dependencies: - '@babel/parser': 7.26.0 + '@babel/parser': 7.26.1 '@babel/types': 7.26.0 '@jridgewell/gen-mapping': 0.3.5 '@jridgewell/trace-mapping': 0.3.25 @@ -5290,7 +5304,7 @@ snapshots: js-tokens: 4.0.0 picocolors: 1.1.1 - '@babel/parser@7.26.0': + '@babel/parser@7.26.1': dependencies: '@babel/types': 7.26.0 @@ -6035,14 +6049,14 @@ snapshots: '@babel/template@7.25.9': dependencies: '@babel/code-frame': 7.26.0 - '@babel/parser': 7.26.0 + '@babel/parser': 7.26.1 '@babel/types': 7.26.0 '@babel/traverse@7.25.9': dependencies: '@babel/code-frame': 7.26.0 '@babel/generator': 7.26.0 - '@babel/parser': 7.26.0 + '@babel/parser': 7.26.1 '@babel/template': 7.25.9 '@babel/types': 7.26.0 debug: 4.3.7 @@ -6246,7 +6260,7 @@ snapshots: dependencies: '@babel/core': 7.26.0 '@babel/generator': 7.26.0 - '@babel/parser': 7.26.0 + '@babel/parser': 7.26.1 '@babel/types': 7.26.0 '@expo/config': 9.0.4 '@expo/env': 0.3.0 @@ -6437,7 +6451,7 @@ snapshots: '@jest/console@29.7.0': dependencies: '@jest/types': 29.6.3 - '@types/node': 22.8.0 + '@types/node': 22.8.2 chalk: 4.1.2 jest-message-util: 29.7.0 jest-util: 29.7.0 @@ -6450,14 +6464,14 @@ snapshots: '@jest/test-result': 29.7.0 '@jest/transform': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 22.8.0 + '@types/node': 22.8.2 ansi-escapes: 4.3.2 chalk: 4.1.2 ci-info: 3.9.0 exit: 0.1.2 graceful-fs: 4.2.11 jest-changed-files: 29.7.0 - jest-config: 29.7.0(@types/node@22.8.0) + jest-config: 29.7.0(@types/node@22.8.2) jest-haste-map: 29.7.0 jest-message-util: 29.7.0 jest-regex-util: 29.6.3 @@ -6486,7 +6500,7 @@ snapshots: dependencies: '@jest/fake-timers': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 22.8.0 + '@types/node': 22.8.2 jest-mock: 29.7.0 '@jest/expect-utils@29.7.0': @@ -6504,7 +6518,7 @@ snapshots: dependencies: '@jest/types': 29.6.3 '@sinonjs/fake-timers': 10.3.0 - '@types/node': 22.8.0 + '@types/node': 22.8.2 jest-message-util: 29.7.0 jest-mock: 29.7.0 jest-util: 29.7.0 @@ -6526,7 +6540,7 @@ snapshots: '@jest/transform': 29.7.0 '@jest/types': 29.6.3 '@jridgewell/trace-mapping': 0.3.25 - '@types/node': 22.8.0 + '@types/node': 22.8.2 chalk: 4.1.2 collect-v8-coverage: 1.0.2 exit: 0.1.2 @@ -6601,7 +6615,7 @@ snapshots: dependencies: '@types/istanbul-lib-coverage': 2.0.6 '@types/istanbul-reports': 3.0.4 - '@types/node': 22.8.0 + '@types/node': 22.8.2 '@types/yargs': 15.0.19 chalk: 4.1.2 @@ -6610,7 +6624,7 @@ snapshots: '@jest/schemas': 29.6.3 '@types/istanbul-lib-coverage': 2.0.6 '@types/istanbul-reports': 3.0.4 - '@types/node': 22.8.0 + '@types/node': 22.8.2 '@types/yargs': 17.0.33 chalk: 4.1.2 @@ -6828,6 +6842,12 @@ snapshots: - supports-color - utf-8-validate + '@react-native-community/datetimepicker@8.0.1(react-native@0.74.5(@babel/core@7.26.0)(@babel/preset-env@7.25.9(@babel/core@7.26.0))(@types/react@18.2.79)(react@18.2.0))(react@18.2.0)': + dependencies: + invariant: 2.2.4 + react: 18.2.0 + react-native: 0.74.5(@babel/core@7.26.0)(@babel/preset-env@7.25.9(@babel/core@7.26.0))(@types/react@18.2.79)(react@18.2.0) + '@react-native/assets-registry@0.74.87': {} '@react-native/babel-plugin-codegen@0.74.87(@babel/preset-env@7.25.9(@babel/core@7.26.0))': @@ -6888,7 +6908,7 @@ snapshots: '@react-native/codegen@0.74.87(@babel/preset-env@7.25.9(@babel/core@7.26.0))': dependencies: - '@babel/parser': 7.26.0 + '@babel/parser': 7.26.1 '@babel/preset-env': 7.25.9(@babel/core@7.26.0) glob: 7.2.3 hermes-parser: 0.19.1 @@ -7105,7 +7125,7 @@ snapshots: '@rnx-kit/chromium-edge-launcher@1.0.0': dependencies: - '@types/node': 18.19.59 + '@types/node': 18.19.60 escape-string-regexp: 4.0.0 is-wsl: 2.2.0 lighthouse-logger: 1.4.2 @@ -7152,7 +7172,7 @@ snapshots: '@types/babel__core@7.20.5': dependencies: - '@babel/parser': 7.26.0 + '@babel/parser': 7.26.1 '@babel/types': 7.26.0 '@types/babel__generator': 7.6.8 '@types/babel__template': 7.4.4 @@ -7164,7 +7184,7 @@ snapshots: '@types/babel__template@7.4.4': dependencies: - '@babel/parser': 7.26.0 + '@babel/parser': 7.26.1 '@babel/types': 7.26.0 '@types/babel__traverse@7.20.6': @@ -7179,7 +7199,7 @@ snapshots: '@types/graceful-fs@4.1.9': dependencies: - '@types/node': 22.8.0 + '@types/node': 22.8.2 '@types/hammerjs@2.0.46': {} @@ -7210,9 +7230,9 @@ snapshots: '@types/jsdom@20.0.1': dependencies: - '@types/node': 22.8.0 + '@types/node': 22.8.2 '@types/tough-cookie': 4.0.5 - parse5: 7.2.0 + parse5: 7.2.1 '@types/json-schema@7.0.15': {} @@ -7228,13 +7248,13 @@ snapshots: '@types/node-forge@1.3.11': dependencies: - '@types/node': 22.8.0 + '@types/node': 22.8.2 - '@types/node@18.19.59': + '@types/node@18.19.60': dependencies: undici-types: 5.26.5 - '@types/node@22.8.0': + '@types/node@22.8.2': dependencies: undici-types: 6.19.8 @@ -7301,14 +7321,14 @@ snapshots: acorn-globals@7.0.1: dependencies: - acorn: 8.13.0 + acorn: 8.14.0 acorn-walk: 8.3.4 acorn-walk@8.3.4: dependencies: - acorn: 8.13.0 + acorn: 8.14.0 - acorn@8.13.0: {} + acorn@8.14.0: {} agent-base@6.0.2: dependencies: @@ -7599,8 +7619,8 @@ snapshots: browserslist@4.24.2: dependencies: - caniuse-lite: 1.0.30001669 - electron-to-chromium: 1.5.45 + caniuse-lite: 1.0.30001674 + electron-to-chromium: 1.5.49 node-releases: 2.0.18 update-browserslist-db: 1.1.1(browserslist@4.24.2) @@ -7667,7 +7687,7 @@ snapshots: camelcase@6.3.0: {} - caniuse-lite@1.0.30001669: {} + caniuse-lite@1.0.30001674: {} chalk@2.4.2: dependencies: @@ -7695,7 +7715,7 @@ snapshots: chrome-launcher@0.15.2: dependencies: - '@types/node': 22.8.0 + '@types/node': 22.8.2 escape-string-regexp: 4.0.0 is-wsl: 2.2.0 lighthouse-logger: 1.4.2 @@ -7834,13 +7854,13 @@ snapshots: js-yaml: 3.14.1 parse-json: 4.0.0 - create-jest@29.7.0(@types/node@22.8.0): + create-jest@29.7.0(@types/node@22.8.2): dependencies: '@jest/types': 29.6.3 chalk: 4.1.2 exit: 0.1.2 graceful-fs: 4.2.11 - jest-config: 29.7.0(@types/node@22.8.0) + jest-config: 29.7.0(@types/node@22.8.2) jest-util: 29.7.0 prompts: 2.4.2 transitivePeerDependencies: @@ -8009,7 +8029,7 @@ snapshots: ee-first@1.1.1: {} - electron-to-chromium@1.5.45: {} + electron-to-chromium@1.5.49: {} emittery@0.13.1: {} @@ -8934,7 +8954,7 @@ snapshots: istanbul-lib-instrument@5.2.1: dependencies: '@babel/core': 7.26.0 - '@babel/parser': 7.26.0 + '@babel/parser': 7.26.1 '@istanbuljs/schema': 0.1.3 istanbul-lib-coverage: 3.2.2 semver: 6.3.1 @@ -8944,7 +8964,7 @@ snapshots: istanbul-lib-instrument@6.0.3: dependencies: '@babel/core': 7.26.0 - '@babel/parser': 7.26.0 + '@babel/parser': 7.26.1 '@istanbuljs/schema': 0.1.3 istanbul-lib-coverage: 3.2.2 semver: 7.6.3 @@ -8988,7 +9008,7 @@ snapshots: '@jest/expect': 29.7.0 '@jest/test-result': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 22.8.0 + '@types/node': 22.8.2 chalk: 4.1.2 co: 4.6.0 dedent: 1.5.3 @@ -9008,16 +9028,16 @@ snapshots: - babel-plugin-macros - supports-color - jest-cli@29.7.0(@types/node@22.8.0): + jest-cli@29.7.0(@types/node@22.8.2): dependencies: '@jest/core': 29.7.0 '@jest/test-result': 29.7.0 '@jest/types': 29.6.3 chalk: 4.1.2 - create-jest: 29.7.0(@types/node@22.8.0) + create-jest: 29.7.0(@types/node@22.8.2) exit: 0.1.2 import-local: 3.2.0 - jest-config: 29.7.0(@types/node@22.8.0) + jest-config: 29.7.0(@types/node@22.8.2) jest-util: 29.7.0 jest-validate: 29.7.0 yargs: 17.7.2 @@ -9027,7 +9047,7 @@ snapshots: - supports-color - ts-node - jest-config@29.7.0(@types/node@22.8.0): + jest-config@29.7.0(@types/node@22.8.2): dependencies: '@babel/core': 7.26.0 '@jest/test-sequencer': 29.7.0 @@ -9052,7 +9072,7 @@ snapshots: slash: 3.0.0 strip-json-comments: 3.1.1 optionalDependencies: - '@types/node': 22.8.0 + '@types/node': 22.8.2 transitivePeerDependencies: - babel-plugin-macros - supports-color @@ -9082,7 +9102,7 @@ snapshots: '@jest/fake-timers': 29.7.0 '@jest/types': 29.6.3 '@types/jsdom': 20.0.1 - '@types/node': 22.8.0 + '@types/node': 22.8.2 jest-mock: 29.7.0 jest-util: 29.7.0 jsdom: 20.0.3 @@ -9096,11 +9116,11 @@ snapshots: '@jest/environment': 29.7.0 '@jest/fake-timers': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 22.8.0 + '@types/node': 22.8.2 jest-mock: 29.7.0 jest-util: 29.7.0 - jest-expo@51.0.4(@babel/core@7.26.0)(jest@29.7.0(@types/node@22.8.0))(react@18.2.0): + jest-expo@51.0.4(@babel/core@7.26.0)(jest@29.7.0(@types/node@22.8.2))(react@18.2.0): dependencies: '@expo/config': 9.0.4 '@expo/json-file': 8.3.3 @@ -9109,7 +9129,7 @@ snapshots: find-up: 5.0.0 jest-environment-jsdom: 29.7.0 jest-watch-select-projects: 2.0.0 - jest-watch-typeahead: 2.2.1(jest@29.7.0(@types/node@22.8.0)) + jest-watch-typeahead: 2.2.1(jest@29.7.0(@types/node@22.8.2)) json5: 2.2.3 lodash: 4.17.21 react-test-renderer: 18.2.0(react@18.2.0) @@ -9129,7 +9149,7 @@ snapshots: dependencies: '@jest/types': 29.6.3 '@types/graceful-fs': 4.1.9 - '@types/node': 22.8.0 + '@types/node': 22.8.2 anymatch: 3.1.3 fb-watchman: 2.0.2 graceful-fs: 4.2.11 @@ -9168,7 +9188,7 @@ snapshots: jest-mock@29.7.0: dependencies: '@jest/types': 29.6.3 - '@types/node': 22.8.0 + '@types/node': 22.8.2 jest-util: 29.7.0 jest-pnp-resolver@1.2.3(jest-resolve@29.7.0): @@ -9203,7 +9223,7 @@ snapshots: '@jest/test-result': 29.7.0 '@jest/transform': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 22.8.0 + '@types/node': 22.8.2 chalk: 4.1.2 emittery: 0.13.1 graceful-fs: 4.2.11 @@ -9231,7 +9251,7 @@ snapshots: '@jest/test-result': 29.7.0 '@jest/transform': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 22.8.0 + '@types/node': 22.8.2 chalk: 4.1.2 cjs-module-lexer: 1.4.1 collect-v8-coverage: 1.0.2 @@ -9277,7 +9297,7 @@ snapshots: jest-util@29.7.0: dependencies: '@jest/types': 29.6.3 - '@types/node': 22.8.0 + '@types/node': 22.8.2 chalk: 4.1.2 ci-info: 3.9.0 graceful-fs: 4.2.11 @@ -9298,11 +9318,11 @@ snapshots: chalk: 3.0.0 prompts: 2.4.2 - jest-watch-typeahead@2.2.1(jest@29.7.0(@types/node@22.8.0)): + jest-watch-typeahead@2.2.1(jest@29.7.0(@types/node@22.8.2)): dependencies: ansi-escapes: 6.2.1 chalk: 4.1.2 - jest: 29.7.0(@types/node@22.8.0) + jest: 29.7.0(@types/node@22.8.2) jest-regex-util: 29.6.3 jest-watcher: 29.7.0 slash: 5.1.0 @@ -9313,7 +9333,7 @@ snapshots: dependencies: '@jest/test-result': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 22.8.0 + '@types/node': 22.8.2 ansi-escapes: 4.3.2 chalk: 4.1.2 emittery: 0.13.1 @@ -9322,17 +9342,17 @@ snapshots: jest-worker@29.7.0: dependencies: - '@types/node': 22.8.0 + '@types/node': 22.8.2 jest-util: 29.7.0 merge-stream: 2.0.0 supports-color: 8.1.1 - jest@29.7.0(@types/node@22.8.0): + jest@29.7.0(@types/node@22.8.2): dependencies: '@jest/core': 29.7.0 '@jest/types': 29.6.3 import-local: 3.2.0 - jest-cli: 29.7.0(@types/node@22.8.0) + jest-cli: 29.7.0(@types/node@22.8.2) transitivePeerDependencies: - '@types/node' - babel-plugin-macros @@ -9369,7 +9389,7 @@ snapshots: jscodeshift@0.14.0(@babel/preset-env@7.25.9(@babel/core@7.26.0)): dependencies: '@babel/core': 7.26.0 - '@babel/parser': 7.26.0 + '@babel/parser': 7.26.1 '@babel/plugin-proposal-class-properties': 7.18.6(@babel/core@7.26.0) '@babel/plugin-proposal-nullish-coalescing-operator': 7.18.6(@babel/core@7.26.0) '@babel/plugin-proposal-optional-chaining': 7.21.0(@babel/core@7.26.0) @@ -9394,7 +9414,7 @@ snapshots: jsdom@20.0.3: dependencies: abab: 2.0.6 - acorn: 8.13.0 + acorn: 8.14.0 acorn-globals: 7.0.1 cssom: 0.5.0 cssstyle: 2.3.0 @@ -9408,7 +9428,7 @@ snapshots: https-proxy-agent: 5.0.1 is-potential-custom-element-name: 1.0.1 nwsapi: 2.2.13 - parse5: 7.2.0 + parse5: 7.2.1 saxes: 6.0.0 symbol-tree: 3.2.4 tough-cookie: 4.1.4 @@ -9719,7 +9739,7 @@ snapshots: dependencies: '@babel/core': 7.26.0 '@babel/generator': 7.26.0 - '@babel/parser': 7.26.0 + '@babel/parser': 7.26.1 '@babel/types': 7.26.0 flow-enums-runtime: 0.0.6 metro: 0.80.12 @@ -9740,7 +9760,7 @@ snapshots: '@babel/code-frame': 7.26.0 '@babel/core': 7.26.0 '@babel/generator': 7.26.0 - '@babel/parser': 7.26.0 + '@babel/parser': 7.26.1 '@babel/template': 7.25.9 '@babel/traverse': 7.25.9 '@babel/types': 7.26.0 @@ -10046,7 +10066,7 @@ snapshots: dependencies: pngjs: 3.4.0 - parse5@7.2.0: + parse5@7.2.1: dependencies: entities: 4.5.0 @@ -10450,13 +10470,13 @@ snapshots: regenerate: 1.4.2 regenerate-unicode-properties: 10.2.0 regjsgen: 0.8.0 - regjsparser: 0.11.1 + regjsparser: 0.11.2 unicode-match-property-ecmascript: 2.0.0 unicode-match-property-value-ecmascript: 2.2.0 regjsgen@0.8.0: {} - regjsparser@0.11.1: + regjsparser@0.11.2: dependencies: jsesc: 3.0.2 @@ -10943,7 +10963,7 @@ snapshots: terser@5.36.0: dependencies: '@jridgewell/source-map': 0.3.6 - acorn: 8.13.0 + acorn: 8.14.0 commander: 2.20.3 source-map-support: 0.5.21