diff --git a/app/(tabs)/_layout.tsx b/app/(tabs)/_layout.tsx index 4eb7245..79ff582 100644 --- a/app/(tabs)/_layout.tsx +++ b/app/(tabs)/_layout.tsx @@ -25,6 +25,7 @@ export default function Layout() { tabBarInactiveTintColor: colors.tabIconDefault, headerShown: false, tabBarStyle: styles.tabBar, + tabBarHideOnKeyboard: true } if(!authState?.authenticated){ diff --git a/app/(tabs)/home/_layout.tsx b/app/(tabs)/home/_layout.tsx index f6c2a2b..abe83bf 100644 --- a/app/(tabs)/home/_layout.tsx +++ b/app/(tabs)/home/_layout.tsx @@ -12,10 +12,10 @@ export default function _Layout() { initialRouteName="index" screenOptions={{ contentStyle: { - backgroundColor:colors.backgroundColor, + backgroundColor:colors.containerColor, }, headerStyle: { - backgroundColor: colors.backgroundColor + backgroundColor: colors.containerColor }, headerTintColor: colors.primaryText @@ -24,7 +24,9 @@ export default function _Layout() { title: "test", headerShown: false, }}/> - + (""); + const [selectorModalVisible, setSelecorModalVisible] = useState(false); + const [selectedCategory, setSelectedCategory] = useState() + const [expenseName, setExpenseName] = useState(""); + const [datePickerShown, setDatePickerShown] = useState(false); + const [selectedDate, setSelectedDate] = useState(new Date()) + + const handleValueChange = (formatedValue: string) => { + setFormatedValue(formatedValue); + } + + const handleCategorySelect = (category : Category) => { + setSelecorModalVisible(false); + setSelectedCategory(category); + } + + const validateInput = ():boolean => { + if(formatedValue == "" || expenseName == "" || selectedCategory === undefined || selectedDate === null){ + return false; + } + return true; + } + + const submit = () => { + const insert = async () => { + await addExpense(expenseName, selectedCategory?.guid!, new SimpleDate(selectedDate).format("YYYY-MM-DD"), Number(formatedValue)) + } + if(validateInput()){ + insert(); + router.back(); + }else { + Alert.alert("Invalid input", "One of the Props is not properly defined") + } + + } -export default function addItem() { return ( - - addItem + + {setSelecorModalVisible(false)}} onCategoryTap={handleCategorySelect}> + + {setSelecorModalVisible(true)}} selectedCategory={selectedCategory}/> + setExpenseName(text)}/> + {setDatePickerShown(true)}}/> + {datePickerShown && + { + setDatePickerShown(false); + if(date){ + setSelectedDate(date); + } + }} + />} + + Save + ) -} \ No newline at end of file +} + +const styles = StyleSheet.create({ + save: { + marginTop: 40, + padding: 10, + }, + container: { + margin: SIZES.normal, + display: "flex", + gap: 10 + }, + + submitText: { + fontSize: SIZES.large + } + +}) \ No newline at end of file diff --git a/app/(tabs)/home/index.tsx b/app/(tabs)/home/index.tsx index eaa0b22..5a0a5a8 100644 --- a/app/(tabs)/home/index.tsx +++ b/app/(tabs)/home/index.tsx @@ -1,9 +1,9 @@ import React, { useRef, useState, useMemo } from 'react'; import { NativeScrollEvent, NativeSyntheticEvent, StyleSheet, View } from 'react-native'; import { Calendar } from 'react-native-calendars'; -import { FlatList } from 'react-native-gesture-handler'; +import { FlatList, RefreshControl } from 'react-native-gesture-handler'; import { SafeAreaView } from 'react-native-safe-area-context'; -import { ExpenseItem, LoadingSymbol, Plus, SearchBar, Welcome } from '../../../components'; +import { ExpenseItem, LoadingSymbol, Plus, TextInputBar, Welcome } from '../../../components'; import useFetch from '../../../hooks/useFetch'; import { addExpense, executeQuery } from "../../../services/database"; @@ -63,7 +63,7 @@ export default function Page() { } } - const {data, isLoading, reFetch} = useFetch({sql: "SELECT e.guid AS expense_guid, c.guid AS category_guid, e.name AS expense_name, c.name AS category_name, e.datetime AS expense_datetime, e.amount AS expense_amount, c.color AS category_color, c.type AS category_type FROM expense e JOIN category c ON e.category_guid = c.guid;", args: []}); + const {data, isLoading, reFetch} = useFetch({sql: "SELECT e.guid AS expense_guid, c.guid AS category_guid, e.name AS expense_name, c.name AS category_name, e.datetime AS expense_datetime, e.amount AS expense_amount, c.color AS category_color, c.type AS category_type FROM expense e JOIN category c ON e.category_guid = c.guid ORDER BY expense_datetime desc;", args: []}); const expenseDates = useMemo(()=> constructMarkedDates(data) @@ -74,15 +74,15 @@ export default function Page() { return ( {plusShow && { - // router.push("/(tabs)/home/addItem"); + router.push("/(tabs)/home/addItem"); - executeQuery({sql: "SELECT guid FROM category", args: []}).then((result) => { - if("rows" in result[0]) { - newExpense("Test Title", result[0]["rows"][0]["guid"], "69.69.1234", 100).then(() => { - reFetch(); - }); - } - }) + // executeQuery({sql: "SELECT guid FROM category", args: []}).then((result) => { + // if("rows" in result[0]) { + // newExpense("Test Title", result[0]["rows"][0]["guid"], "69.69.1234", 100).then(() => { + // reFetch(); + // }); + // } + // }) }}/>} {isLoading && } @@ -92,7 +92,7 @@ export default function Page() { ListHeaderComponent={ <> {router.push("/home/userSettings")}}/> - - + } renderItem = {({item}) => } @@ -114,6 +114,9 @@ export default function Page() { ItemSeparatorComponent={() => { return (); }} + refreshControl={ + + } onScroll={handleScroll} scrollEventThrottle={20} /> @@ -124,6 +127,7 @@ export default function Page() { const styles = StyleSheet.create({ safeAreaViewStyle: { flex: 1, + paddingHorizontal: 10 }, itemSeperatorStyle: { marginVertical: 5, diff --git a/components/budget/budgetHeader.tsx b/components/budget/budgetHeader.tsx index eed9624..7fe8f01 100644 --- a/components/budget/budgetHeader.tsx +++ b/components/budget/budgetHeader.tsx @@ -1,5 +1,5 @@ import { StyleSheet, Text, TouchableHighlight, View } from "react-native"; -import SearchBar from "../common/SearchBar"; +import TextInputBar from "../common/TextInputBar"; import { useTheme } from "../../app/contexts/ThemeContext"; type BudgetHeaderProperties = { @@ -34,7 +34,7 @@ const BudgetHeader = (properties: BudgetHeaderProperties) => { }} /> - + ); } diff --git a/components/common/AutoDecimalInput.tsx b/components/common/AutoDecimalInput.tsx new file mode 100644 index 0000000..52821fc --- /dev/null +++ b/components/common/AutoDecimalInput.tsx @@ -0,0 +1,94 @@ +import { View, Text, TouchableOpacity, TextInput, StyleSheet, NativeSyntheticEvent, TextInputKeyPressEventData } from 'react-native' +import React, {LegacyRef, MutableRefObject, useRef, useState} from 'react' +import { SIZES } from '../../constants/theme'; +import { useTheme } from '../../app/contexts/ThemeContext'; + +const formatDecimal = (value: string)=>{ + switch(value.length){ + case 0: + return ""; + case 1: + return "0.0"+value + case 2: + return "0."+value + default: + return value.substring(0, value.length - 2) + "." + value.substring(value.length - 2, value.length) + } +} + +interface AutoDecimalInputProps{ + onValueChange?: (formattedValue: string) => void | undefined + label: string, +} + +const AutoDecimalInput: React.FC = ({onValueChange, label}) => { + const { colors } = useTheme(); + const inputRef = useRef(null); + const [pressedNumbers, setPressedNumbers] = useState(""); + + const update = (newValues : string) => { + if(onValueChange){ + onValueChange(formatDecimal(newValues)) + } + setPressedNumbers(newValues); + } + + const handleInput = (e: NativeSyntheticEvent)=>{ + const pressedKey:string = e.nativeEvent.key + if(Number.isInteger(Number.parseInt(pressedKey))){ + if(pressedNumbers.length === 0 && pressedKey === "0"){ + return + } + update(pressedNumbers + pressedKey) + }else if(pressedKey === "Backspace"){ + update(pressedNumbers.substring(0, pressedNumbers.length - 1)) + } + } + return ( + { + if(inputRef.current) + inputRef.current.focus() + }}> + {label} + + + EUR + + + ) +} + +const styles = StyleSheet.create({ + inputContainer: { + minHeight: 50, + borderRadius: 20, + flexDirection: "row", + justifyContent: 'space-between', + alignItems: "center" + }, + text:{ + fontSize: SIZES.large, + marginHorizontal: 15, + }, + currency: { + fontSize: SIZES.normal, + color: "#007acc", + marginRight: 15, + }, + currencyWrapper: { + flexDirection:"row", + justifyContent: 'flex-end', + alignItems: "center" + } +}) + +export default AutoDecimalInput; \ No newline at end of file diff --git a/components/common/CategoryListItem.tsx b/components/common/CategoryListItem.tsx new file mode 100644 index 0000000..3d432a6 --- /dev/null +++ b/components/common/CategoryListItem.tsx @@ -0,0 +1,66 @@ +import { StyleSheet, Text, View, Pressable } from 'react-native' +import React from 'react' +import { Category } from '../../types/dbItems' +import CustomCard from './CustomCard'; +import { SIZES } from '../../constants/theme'; +import { useTheme } from '../../app/contexts/ThemeContext'; + +interface CategoryListItemProps{ + category: Category; + onPress?: (category: Category) =>void | undefined +} + + + +const CategoryListItem: React.FC = (props: CategoryListItemProps) => { + const {category, onPress} = props; + const {colors} = useTheme(); + + const handlePress = ()=>{ + if(onPress){ + onPress(category); + } + } + + return ( + + + + + {category.name ?? "#noData#"} + + + + + ) +} + +export default CategoryListItem + +const styles = StyleSheet.create({ + tile: { + height: 60, + flexDirection: "row", + alignItems: "center", + justifyContent: "space-between", + borderRadius: 20 + }, + colorTip:{ + height: "100%", + width: 30, + borderTopLeftRadius:20, + borderBottomLeftRadius: 20 + }, + textWrapper: { + + }, + tileTail:{ + height: "100%", + width: 30, + borderTopRightRadius:20, + borderBottomRightRadius: 20 + }, + text: { + fontSize: SIZES.large, + } +}) \ No newline at end of file diff --git a/components/common/CustomCard.tsx b/components/common/CustomCard.tsx index 5358d51..a866d8c 100644 --- a/components/common/CustomCard.tsx +++ b/components/common/CustomCard.tsx @@ -39,10 +39,7 @@ export default function CustomCard(props : ViewProps) { const styles = StyleSheet.create({ container:{ - flexDirection: "row", - alignItems: "stretch", - alignContent: "space-between", - borderRadius: 10, + borderRadius: 20, marginHorizontal: 10, }, boxShadow: {}, diff --git a/components/common/RoundedButton.tsx b/components/common/RoundedButton.tsx new file mode 100644 index 0000000..1852212 --- /dev/null +++ b/components/common/RoundedButton.tsx @@ -0,0 +1,32 @@ +import { StyleSheet, Text, View, ViewProps, TouchableOpacity } from 'react-native' +import React from 'react' +import { SIZES } from '../../constants/theme'; + +interface RoundedButtonProps extends ViewProps{ + onPress?: ()=> void | undefined; + color: string; +} + +const RoundedButton: React.FC = (props: RoundedButtonProps) => { + const {onPress, color, style, ...restProps} = props; + return ( + + + {restProps.children} + + + ) +} + +export default RoundedButton + +const styles = StyleSheet.create({ + btn:{ + justifyContent: 'center', + alignItems: 'center', + borderRadius: 80 + }, + text: { + fontSize: SIZES.normal + } +}) \ No newline at end of file diff --git a/components/common/SearchBar.tsx b/components/common/TextInputBar.tsx similarity index 60% rename from components/common/SearchBar.tsx rename to components/common/TextInputBar.tsx index 372d052..a2ffa84 100644 --- a/components/common/SearchBar.tsx +++ b/components/common/TextInputBar.tsx @@ -1,14 +1,18 @@ import { AntDesign } from '@expo/vector-icons'; -import React from 'react'; +import React, { useState } from 'react'; import { StyleSheet, TextInput, TouchableOpacity, View, ViewProps } from 'react-native'; import { SIZES } from '../../constants/theme'; import { useTheme } from '../../app/contexts/ThemeContext'; -type SearchBarProps = {placeholder: string} & ViewProps +interface SearchBarProps extends ViewProps { + placeholder? : string; + onChangeText? : (text: string) => void | undefined +} -export default function SearchBar(props: SearchBarProps) { +export default function TextInputBar(props: SearchBarProps) { const [isActive, setIsactive] = React.useState(false); const { colors } = useTheme(); + const [text, setText] = useState(""); const textColor = colors const backgroundColor = colors.elementDefaultColor; @@ -23,6 +27,10 @@ export default function SearchBar(props: SearchBarProps) { setIsactive(false) } } + if(props.onChangeText){ + props.onChangeText(text) + } + setText(text) } // cant apply the background color otherwise @@ -34,12 +42,12 @@ export default function SearchBar(props: SearchBarProps) { //TODO: Handle textCancel // changed styles.container to containerStyle return ( - - + + handleChange(text)} onEndEditing={()=>setIsactive(false)}/> {isActive && - - + {handleChange("")}}> + } @@ -48,8 +56,6 @@ export default function SearchBar(props: SearchBarProps) { const styles = StyleSheet.create({ container: { - marginHorizontal: 10, - marginBottom: 20, flexDirection: 'row', justifyContent: "center", alignItems: "center", diff --git a/components/home/addItem/CategorySelector.tsx b/components/home/addItem/CategorySelector.tsx new file mode 100644 index 0000000..27d5cfe --- /dev/null +++ b/components/home/addItem/CategorySelector.tsx @@ -0,0 +1,60 @@ +import { StyleSheet, Text, View, TouchableOpacity } from 'react-native' +import React, { useState } from 'react' +import { useTheme } from '../../../app/contexts/ThemeContext' +import { SIZES } from '../../../constants/theme'; +import { Category } from '../../../types/dbItems'; +import CategorySelectorModal from './CategorySelectorModal'; + +interface CategorySelectorProps { + onPress? : () => void | undefined; + selectedCategory? : Category; +} + +const CategorySelector: React.FC = (props : CategorySelectorProps) => { + const {colors} = useTheme(); + + + return ( + <> + + + + + + {props.selectedCategory?.name ?? "Tap to select Categroy"} + + + + + ) +} + +export default CategorySelector + +const styles = StyleSheet.create({ + tile: { + height: 60, + flexDirection: "row", + alignItems: "center", + justifyContent: "space-between", + borderRadius: 20 + }, + colorTip:{ + height: "100%", + width: 30, + borderTopLeftRadius:20, + borderBottomLeftRadius: 20 + }, + textWrapper: { + + }, + tileTail:{ + height: "100%", + width: 30, + borderTopRightRadius:20, + borderBottomRightRadius: 20 + }, + text: { + fontSize: SIZES.large, + } +}) \ No newline at end of file diff --git a/components/home/addItem/CategorySelectorModal.tsx b/components/home/addItem/CategorySelectorModal.tsx new file mode 100644 index 0000000..d758669 --- /dev/null +++ b/components/home/addItem/CategorySelectorModal.tsx @@ -0,0 +1,93 @@ +import { Modal, NativeSyntheticEvent, StyleSheet, Text, View, FlatList } from 'react-native' +import React, { useEffect, useMemo, useState } from 'react' +import { Category } from '../../../types/dbItems'; +import { useTheme } from '../../../app/contexts/ThemeContext'; +import CategoryListItem from '../../common/CategoryListItem'; +import { SIZES } from '../../../constants/theme'; +import useFetch from '../../../hooks/useFetch'; +import TextInputBar from '../../common/TextInputBar'; + + +interface CategorySelectorModalProps{ + visible: boolean; + onCategoryTap?: (category : Category) => void | undefined; + selectMulitple?: boolean; + onRequestClose?: ((event: NativeSyntheticEvent) => void) | undefined; +} + +//TODO: select Multiple + +const CategorySelectorModal: React.FC = (props : CategorySelectorModalProps) => { + const {visible, onCategoryTap, selectMulitple} = props; + const {data, reFetch} = useFetch({sql: "SELECT * FROM category;", args:[]}); + const {colors} = useTheme(); + const [searchtext, setSearchtext] = useState(""); + + const handleSearchText = (text : string) => { + setSearchtext(text); + } + + const categories = useMemo(()=>{ + return data.map((elem) => { + return {name: elem["name"], color: elem["color"], guid: elem["guid"]} + }) + }, [data]) + + const filteredCategories = categories.filter((category) => category.name?.toLowerCase().includes(searchtext.toLowerCase())) + + useEffect(()=>{ + if(visible){ + //reFetch(); Uncomment if newly added categories do not appear + handleSearchText(""); + } + }, [visible]) + + return ( + + + + + {selectMulitple ? "Categories" : "Category"} + + + item.guid!} + renderItem={({item})=> } + ItemSeparatorComponent={() => } + ListFooterComponent={() => } + keyboardShouldPersistTaps="always" + > + + + + + + ) +} + +export default CategorySelectorModal + +const styles = StyleSheet.create({ + main: { + backgroundColor: 'rgba(0, 0, 0, 0.5)', + height: "100%", + width: "100%", + alignItems: "center", + }, + modal: { + height: "70%", + width: "90%", + top: "10%", + borderRadius: 30, + paddingVertical: 20, + paddingHorizontal: 20 + }, + heading: { + fontSize: SIZES.xlarge, + fontWeight: "bold" + }, + itemSeperatorStyle: { + paddingBottom: 10 + } +}) \ No newline at end of file diff --git a/components/home/addItem/DateSelectorButton.tsx b/components/home/addItem/DateSelectorButton.tsx new file mode 100644 index 0000000..4f07297 --- /dev/null +++ b/components/home/addItem/DateSelectorButton.tsx @@ -0,0 +1,38 @@ +import { View, Text, StyleSheet, TouchableOpacity, TouchableOpacityProps } from 'react-native' +import React, { useState } from 'react' +import { useTheme } from '../../../app/contexts/ThemeContext'; +import { SIZES } from '../../../constants/theme'; +import { SimpleDate } from '../../../util/SimpleDate'; +import { ViewProps } from 'react-native/Libraries/Components/View/ViewPropTypes'; + +interface DateSelectorProps extends ViewProps { + onPress?: ()=>void | undefined; + selectedDate: Date +} + +const DateSelectorButton:React.FC = (props: DateSelectorProps) => { + const {onPress, selectedDate, ...restProps} = props; + const {colors} = useTheme(); + + return ( + + Date: + {new SimpleDate(selectedDate).format("DD.MM.YYYY")} + + ) +} +const styles = StyleSheet.create({ + inputContainer: { + minHeight: 50, + borderRadius: 20, + flexDirection: "row", + justifyContent: 'space-between', + alignItems: "center" + }, + text:{ + fontSize: SIZES.large, + marginHorizontal: 15, + }, +}) + +export default DateSelectorButton \ No newline at end of file diff --git a/components/home/expenseItem.tsx b/components/home/expenseItem.tsx index d541d48..ade5ccd 100644 --- a/components/home/expenseItem.tsx +++ b/components/home/expenseItem.tsx @@ -9,28 +9,29 @@ export default function ExpenseItem(itemProps : ExpenseItemProps) { const { colors } = useTheme(); return ( - - - {itemProps.category} - {itemProps.title} - {itemProps.date} - - - {itemProps.value} - - + + + + {itemProps.category} + {itemProps.title} + {itemProps.date} + + + {itemProps.value} + + ) @@ -42,6 +43,12 @@ const styles = StyleSheet.create({ borderTopLeftRadius: 20, borderBottomLeftRadius: 20, }, + + tile: { + flexDirection: "row", + alignItems: "stretch", + alignContent: "space-between", + }, textSection: { flexDirection: "column", diff --git a/components/index.tsx b/components/index.tsx index f3dd44f..b20c5fd 100644 --- a/components/index.tsx +++ b/components/index.tsx @@ -3,14 +3,21 @@ import { ButtonSetting, ToggleSetting } from "./home/Setting" import Welcome from "./home/Welcome" import ExpenseItem from "./home/expenseItem" +//home/addItem +import CategorySelector from "./home/addItem/CategorySelector" +import CategorySelectorModal from "./home/addItem/CategorySelectorModal" +import DateSelectorButton from "./home/addItem/DateSelectorButton" + //common import CustomCard from "./common/CustomCard" -import SearchBar from "./common/SearchBar" import NavigationButton from "./common/button" import LoadingSymbol from "./common/loadingSymbol" import Plus from "./common/plus" +import TextInputBar from "./common/TextInputBar" +import AutoDecimalInput from "./common/AutoDecimalInput" +import RoundedButton from "./common/RoundedButton" -//budget +//login import BudgetHeader from "./budget/budgetHeader" import CategoryItem from "./budget/categoryItem" import CustomColorPicker from "./budget/customColorPicker" @@ -20,8 +27,24 @@ import TypeSelectorSwitch from "./budget/typeSelectorSwitch" import Input from "./login/input" export { - BudgetHeader, ButtonSetting, CategoryItem, CustomCard, CustomColorPicker, ExpenseItem, Input, - LoadingSymbol, NavigationButton, Plus, - SearchBar, ToggleSetting, TypeSelectorSwitch, Welcome + BudgetHeader, + ButtonSetting, + CustomCard, + ExpenseItem, + Input, + LoadingSymbol, + Plus, + TextInputBar, + ToggleSetting, + Welcome, + AutoDecimalInput, + CategorySelector, + CategorySelectorModal, + DateSelectorButton, + RoundedButton, + CategoryItem, + TypeSelectorSwitch, + NavigationButton, + CustomColorPicker } diff --git a/package-lock.json b/package-lock.json index 16b6032..aab706f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,6 +10,7 @@ "dependencies": { "@expo/vector-icons": "^13.0.0", "@react-native-async-storage/async-storage": "1.18.2", + "@react-native-community/datetimepicker": "7.2.0", "@react-navigation/native": "^6.0.2", "expo": "~49.0.15", "expo-font": "~11.4.0", @@ -6275,6 +6276,14 @@ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, + "node_modules/@react-native-community/datetimepicker": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@react-native-community/datetimepicker/-/datetimepicker-7.2.0.tgz", + "integrity": "sha512-dO1sQy83M/EvnHE2egto05iwXZX7EYn5f/VDMp6afZFRFXRiRo7CzB3VFg4B55gJRJMNBv06NYMLPM3SlpnEGQ==", + "dependencies": { + "invariant": "^2.2.4" + } + }, "node_modules/@react-native/assets-registry": { "version": "0.72.0", "resolved": "https://registry.npmjs.org/@react-native/assets-registry/-/assets-registry-0.72.0.tgz", diff --git a/package.json b/package.json index abb4142..2e627b2 100644 --- a/package.json +++ b/package.json @@ -41,7 +41,8 @@ "react-native-screens": "~3.22.0", "react-native-uuid": "^2.0.1", "react-native-web": "~0.19.6", - "reanimated-color-picker": "^2.4.2" + "reanimated-color-picker": "^2.4.2", + "@react-native-community/datetimepicker": "7.2.0" }, "devDependencies": { "@babel/core": "^7.20.0", diff --git a/services/DebugMenu.tsx b/services/DebugMenu.tsx index 896a667..29ce4e8 100644 --- a/services/DebugMenu.tsx +++ b/services/DebugMenu.tsx @@ -1,6 +1,6 @@ import React from 'react'; import { View, Button, Alert } from 'react-native'; -import { addCategory, addExpense, deleteExpenses, deleteCategories, DEV_populateDatabase } from './database'; +import { addCategory, addExpense, deleteExpenses, deleteCategories, DEV_populateDatabase, deleteDatabase } from './database'; import uuid from 'react-native-uuid'; const randomColors = ["red", "blue", "green", "purple", "yellow"]; @@ -19,6 +19,11 @@ const getRandomNumber = () => { const DebugMenu = () => { + const deleteDBFile = () => { + console.warn("Deleting DB. App Restart is required") + return deleteDatabase(); + } + const handleNukeDatabase = () => { return deleteExpenses(), deleteCategories() }; @@ -60,6 +65,7 @@ const DebugMenu = () => { return ( +