feat: Add expense screen

This commit is contained in:
Jakob Stornig 2024-01-05 00:13:56 +01:00
parent e1efed5b21
commit 36679279c1
18 changed files with 459 additions and 57 deletions

View file

@ -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

View file

@ -1,26 +1,93 @@
import { View, Text, StyleSheet, TextInput, NativeSyntheticEvent, TextInputKeyPressEventData, TouchableOpacity } from 'react-native'
import { View, Text, StyleSheet, Alert } from 'react-native'
import React, { useRef, useState } from 'react'
import { SIZES } from '../../../constants/theme'
import { useTheme } from '../../contexts/ThemeContext'
import { AutoDecimalInput } from '../../../components'
import { AutoDecimalInput, CategorySelector, CategorySelectorModal, DateSelectorButton, RoundedButton, TextInputBar } from '../../../components'
import { Category } from '../../../types/dbItems'
import DateTimePicker from '@react-native-community/datetimepicker';
import { addExpense } from '../../../services/database'
import { SimpleDate } from '../../../util/SimpleDate'
import { useRouter } from 'expo-router'
export default function AddItem() {
const value = useRef<string>("");
const {colors} = useTheme();
const router = useRouter();
const [formatedValue, setFormatedValue] = useState<string>("");
const [selectorModalVisible, setSelecorModalVisible] = useState<boolean>(false);
const [selectedCategory, setSelectedCategory] = useState<Category|undefined>()
const [expenseName, setExpenseName] = useState<string>("");
const [datePickerShown, setDatePickerShown] = useState<boolean>(false);
const [selectedDate, setSelectedDate] = useState<Date>(new Date())
const handleValueChange = (formatedValue: string) => {
setFormatedValue(formatedValue);
}
console.log(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")
}
}
return (
<View style={styles.container}>
<CategorySelectorModal visible={selectorModalVisible} onRequestClose={()=>{setSelecorModalVisible(false)}} onCategoryTap={handleCategorySelect}></CategorySelectorModal>
<AutoDecimalInput onValueChange={handleValueChange} label='Amount'></AutoDecimalInput>
<CategorySelector onPress={()=>{setSelecorModalVisible(true)}} selectedCategory={selectedCategory}/>
<TextInputBar placeholder='Name' onChangeText={(text)=>setExpenseName(text)}/>
<DateSelectorButton selectedDate={selectedDate} onPress={()=>{setDatePickerShown(true)}}/>
{datePickerShown &&
<DateTimePicker
value={new Date()}
maximumDate={new Date()}
onChange={(event, date)=>{
setDatePickerShown(false);
if(date){
setSelectedDate(date);
}
}}
/>}
<RoundedButton color={colors.accentColor} style={styles.save} onPress={submit}>
<Text style={[styles.submitText, {color: colors.primaryText}]}>Save</Text>
</RoundedButton>
</View>
)
}
const styles = StyleSheet.create({
save: {
marginTop: 40,
padding: 10,
},
container: {
margin: SIZES.normal,
display: "flex",
gap: 10
},
submitText: {
fontSize: SIZES.large
}
})

View file

@ -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)
@ -92,7 +92,7 @@ export default function Page() {
ListHeaderComponent={
<>
<Welcome name="My Dude" image={profile} onPress={() => {router.push("/home/userSettings")}}/>
<Calendar key={theme} maxDate={SimpleDate.now().format("YYYY-MM-DD")} style={{margin: 10, borderRadius: 20, padding:10}} theme={{
<Calendar key={theme} maxDate={SimpleDate.now().format("YYYY-MM-DD")} style={{borderRadius: 20, padding:10}} theme={{
dayTextColor: colors.primaryText,
textDisabledColor: colors.secondaryText,
todayTextColor: colors.accentColor,
@ -106,7 +106,7 @@ export default function Page() {
>
</Calendar>
<SearchBar placeholder='Type to Search...'></SearchBar>
<TextInputBar placeholder='Type to Search...' style={{marginBottom: 20}}></TextInputBar>
</>
}
renderItem = {({item}) => <ExpenseItem category={item.category_name} color={item.category_color} date={item.expense_datetime} title={item.expense_name} value={item.expense_amount}/>}
@ -114,6 +114,9 @@ export default function Page() {
ItemSeparatorComponent={() => {
return (<View style={styles.itemSeperatorStyle}/>);
}}
refreshControl={
<RefreshControl refreshing={isLoading} onRefresh={reFetch}/>
}
onScroll={handleScroll}
scrollEventThrottle={20}
/>
@ -124,6 +127,7 @@ export default function Page() {
const styles = StyleSheet.create({
safeAreaViewStyle: {
flex: 1,
paddingHorizontal: 10
},
itemSeperatorStyle: {
marginVertical: 5,