diff --git a/app/(tabs)/_layout.tsx b/app/(tabs)/_layout.tsx index 2987b71..299bba8 100644 --- a/app/(tabs)/_layout.tsx +++ b/app/(tabs)/_layout.tsx @@ -1,10 +1,10 @@ import { Tabs } from "expo-router/tabs"; -import {StyleSheet, View, Text} from "react-native" +import { StyleSheet } from "react-native"; import { FontAwesome } from "@expo/vector-icons"; -import {useThemeColor} from "../../hooks/hooks"; -import React, { useEffect } from "react"; import { Redirect } from "expo-router"; +import React, { useEffect } from "react"; +import { useThemeColor } from "../../hooks/useThemeColor"; import { useAuth } from "../contexts/AuthContext"; export default function Layout() { @@ -53,6 +53,7 @@ export default function Layout() { tabBarLabel: "Home", tabBarIcon: ({size, color}) => ( ), + unmountOnBlur: true } }/> )=>{ @@ -37,43 +46,29 @@ export default function Page() { setPlusShow(isScrollingUp || isTop) } - const [data, setData] = useState<{[column: string]: any;}[]>([]); - - //only for demonstration during phase 1, delete later - useEffect(() => { - addCategory("Test Category", "red", "budget"); - update(); - }, []); - - useFocusEffect(() => { - update(); - }); - - const update = () => { - executeQuery("SELECT e.guid AS expense_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 FROM expense e JOIN category c ON e.category_guid = c.guid;").then((result) => { - if(result === undefined) return; - setData(result); - }).catch((error) => { - throw error; - }); + const newExpense = async (title: string, category_guid: string, date: string, amount: number) => { + try { + await addExpense(title, category_guid, date, amount); + } catch (error: any) { + console.error("Adding new expense has failed: ", error); + } } + const {data, isLoading, reFetch} = useFetch(); + + + return ( - - {plusShow && { + + {plusShow && { // router.push("/(tabs)/home/addItem"); - - executeQuery("SELECT guid FROM category").then((result) => { - if(result === undefined) return; - addExpense("Random Expense", result[0]["guid"], "12.08.2023", 1).then(() => { - update(); - }); - }).catch((error) => { - throw error; + newExpense("Test Title", "3b33b8ac-5fc1-43e5-81fc-cf61628861f7", "69.69.1234", 100).then(() => { + reFetch(); }); + }}/>} - }}/>} - + {isLoading && } + - - + ); } \ No newline at end of file diff --git a/app/login.tsx b/app/login.tsx index 1c04bd6..35a67e7 100644 --- a/app/login.tsx +++ b/app/login.tsx @@ -1,10 +1,10 @@ -import { View, Text, SafeAreaView, TextInput, Button} from 'react-native' -import React, { useEffect, useState } from 'react' -import { useAuth } from './contexts/AuthContext' -import { Redirect } from 'expo-router'; import { FontAwesome } from "@expo/vector-icons"; +import { Redirect } from 'expo-router'; +import React, { useState } from 'react'; +import { Button, SafeAreaView } from 'react-native'; import { Input } from '../components'; -import { useThemeColor } from '../hooks/hooks'; +import { useThemeColor } from '../hooks/useThemeColor'; +import { useAuth } from './contexts/AuthContext'; export default function login() { const [email, setEmail] = useState(""); diff --git a/components/common/customCard/CustomCard.tsx b/components/common/customCard/CustomCard.tsx index 289df26..b19eea5 100644 --- a/components/common/customCard/CustomCard.tsx +++ b/components/common/customCard/CustomCard.tsx @@ -1,8 +1,7 @@ -import { View, Text, StyleSheet, Platform } from 'react-native' import React from 'react' +import { Platform, StyleSheet, View } from 'react-native' import { ViewProps } from 'react-native/Libraries/Components/View/ViewPropTypes' -import { useThemeColor } from '../../../hooks/hooks' -import { SHADOWS } from '../../../constants/theme' +import { useThemeColor } from '../../../hooks/useThemeColor' function generateBoxShadowStyle( xOffset: number, diff --git a/components/common/loadingSymbol/loadingSymbol.tsx b/components/common/loadingSymbol/loadingSymbol.tsx new file mode 100644 index 0000000..17fb29a --- /dev/null +++ b/components/common/loadingSymbol/loadingSymbol.tsx @@ -0,0 +1,23 @@ +import { StyleSheet, View } from "react-native"; + +const LoadingSymbol = () => { + + const color = ["blue", "red", "purple", "green", "yellow", "orange"]; + const random = Math.floor(Math.random() * color.length); + + const styles = StyleSheet.create({ + container: { + backgroundColor: color[random], + width: "100%", + height: "100%", + position: "absolute", + } + }); + + return ( + + ); +} + + +export default LoadingSymbol; \ No newline at end of file diff --git a/components/common/plus/plus.tsx b/components/common/plus/plus.tsx index 863e08e..8ae1b15 100644 --- a/components/common/plus/plus.tsx +++ b/components/common/plus/plus.tsx @@ -1,7 +1,7 @@ import { AntDesign } from '@expo/vector-icons' import React from 'react' import { StyleSheet, TouchableOpacity, ViewProps } from 'react-native' -import { useThemeColor } from '../../../hooks/hooks' +import { useThemeColor } from '../../../hooks/useThemeColor' type PlusProps = ViewProps & {onPress? : ()=> void | undefined} diff --git a/components/common/searchBar/SearchBar.tsx b/components/common/searchBar/SearchBar.tsx index c9a0968..fe538f6 100644 --- a/components/common/searchBar/SearchBar.tsx +++ b/components/common/searchBar/SearchBar.tsx @@ -1,8 +1,8 @@ -import { View, Text, ViewProps, StyleSheet, Button, TouchableOpacity, TextInput } from 'react-native' -import React from 'react' import { AntDesign } from '@expo/vector-icons'; -import { useThemeColor } from '../../../hooks/hooks'; +import React from 'react'; +import { StyleSheet, TextInput, TouchableOpacity, View, ViewProps } from 'react-native'; import { SIZES } from '../../../constants/theme'; +import { useThemeColor } from '../../../hooks/useThemeColor'; type SearchBarProps = {placeholder: string} & ViewProps diff --git a/components/home/Welcome/Welcome.tsx b/components/home/Welcome/Welcome.tsx index 5618e8d..265cce4 100644 --- a/components/home/Welcome/Welcome.tsx +++ b/components/home/Welcome/Welcome.tsx @@ -1,8 +1,8 @@ -import { View, Text, ViewProps, Image, GestureResponderEvent } from 'react-native' import React from 'react' -import { MARGINS, SIZES, SHADOWS } from '../../../constants/theme' +import { Image, Text, View, ViewProps } from 'react-native' import { TouchableOpacity } from 'react-native-gesture-handler' -import { useThemeColor } from '../../../hooks/hooks' +import { MARGINS, SIZES } from '../../../constants/theme' +import { useThemeColor } from '../../../hooks/useThemeColor' type WelcomeProps = ViewProps & {name: string, image : any, onPress: () => void | undefined} diff --git a/components/home/expenseItem/expenseItem.tsx b/components/home/expenseItem/expenseItem.tsx index acd7821..b103132 100644 --- a/components/home/expenseItem/expenseItem.tsx +++ b/components/home/expenseItem/expenseItem.tsx @@ -1,8 +1,8 @@ -import { View, Text, StyleSheet, ColorValue } from 'react-native' -import React from 'react' -import { useThemeColor } from '../../../hooks/hooks'; -import CustomCard from "../../common/customCard/CustomCard"; +import React from 'react'; +import { ColorValue, StyleSheet, Text, View } from 'react-native'; import { SIZES } from '../../../constants/theme'; +import { useThemeColor } from '../../../hooks/useThemeColor'; +import CustomCard from "../../common/customCard/CustomCard"; export type ExpenseItemProps = {color: ColorValue, category: string, title: string, date: string, value : string} export default function ExpenseItem(itemProps : ExpenseItemProps) { diff --git a/components/index.tsx b/components/index.tsx index 871d5ce..b95c4c8 100644 --- a/components/index.tsx +++ b/components/index.tsx @@ -3,6 +3,7 @@ import ExpenseItem from "./home/expenseItem/expenseItem" import Welcome from "./home/Welcome/Welcome" //common +import LoadingSymbol from "./common/loadingSymbol/loadingSymbol" import Plus from "./common/plus/plus" import SearchBar from "./common/searchBar/SearchBar" @@ -11,10 +12,8 @@ import SearchBar from "./common/searchBar/SearchBar" import Input from "./login/input" export { - ExpenseItem, - Welcome, - Plus, - SearchBar, - Input, + ExpenseItem, Input, + LoadingSymbol, Plus, + SearchBar, Welcome } diff --git a/hooks/useFetch.ts b/hooks/useFetch.ts new file mode 100644 index 0000000..790e4f2 --- /dev/null +++ b/hooks/useFetch.ts @@ -0,0 +1,29 @@ +import { useEffect, useState } from "react"; +import { executeQuery } from "../services/database"; + +const useFetch = () => { + + const [isLoading, setIsLoading] = useState(false); + const [data, setData] = useState<{[column: string]: any;}[]>([]); + + const reFetch = () => { + setIsLoading(true); + executeQuery("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;").then((result) => { + if("rows" in result[0]) { + setData(result[0]["rows"]); + } + }).catch((error: any) => { + console.error("Fetching data from database has failed: ", error); + }).finally(() => { + setIsLoading(false); + }); + } + + useEffect(() => { + reFetch(); + }, []) + + return {data, isLoading, reFetch}; +} + +export default useFetch; \ No newline at end of file diff --git a/hooks/hooks.ts b/hooks/useThemeColor.ts similarity index 73% rename from hooks/hooks.ts rename to hooks/useThemeColor.ts index 0b4ba42..c61a1eb 100644 --- a/hooks/hooks.ts +++ b/hooks/useThemeColor.ts @@ -1,7 +1,11 @@ import { useColorScheme } from "react-native"; -import colors from "../constants/colors" +import colors from "../constants/colors"; export function useThemeColor(colorName: keyof typeof colors.light & keyof typeof colors.dark): string { const theme = useColorScheme() ?? "light"; return colors[theme][colorName]; +} + +export function useUpdateData() { + } \ No newline at end of file diff --git a/services/database.ts b/services/database.ts index 554ef15..386ee09 100644 --- a/services/database.ts +++ b/services/database.ts @@ -85,15 +85,10 @@ export const deleteExpense = async (guid: string) => { } export const executeQuery = async (query: string) => { - const sqliteQuary: Query[] = [{sql: query, args: []}]; - const result = await runQuery(sqliteQuary); - - if("rows" in result[0]) { - return result[0]["rows"]; - } - - console.error("Query could not be executed!"); -}; + const sqliteQuary: Query[] = [{sql: query, args: []}]; + const result = await db.execAsync(sqliteQuary, true); + return result; +} export const deleteExpenses = async () => { try { @@ -119,15 +114,6 @@ export const deleteDatabase = () => { console.log("Database Deleted!") } -const runQuery = async (query: Query[]) => { - try { - return await db.execAsync(query, true); - } catch (error) { - console.log("Error running Quary: ", error); - throw(error); - } -}; - const closeDatabase = async () => { try { db.closeAsync();