import React, { useEffect, useMemo, useRef, useState } from 'react'; import { NativeScrollEvent, NativeSyntheticEvent, StyleSheet, View } from 'react-native'; import { Calendar } from 'react-native-calendars'; import { FlatList, RefreshControl } from 'react-native-gesture-handler'; import { SafeAreaView } from 'react-native-safe-area-context'; import { EmptyListCompenent, ExpenseItem, LoadingSymbol, Plus, TextInputBar, Welcome } from '../../../components'; import useFetch from '../../../hooks/useFetch'; import { useRouter } from "expo-router"; import { addExpense } from "../../../services/database"; import { SimpleDate } from '../../../util/SimpleDate'; import { useTheme } from '../../contexts/ThemeContext'; import { useNavigation } from 'expo-router'; import { Category, Expense } from '../../../types/dbItems'; interface MarkingProps { dots?:{color:string, selectedColor?:string, key?:string}[]; selected?: boolean; selectedColor?: string; } type MarkedDates = { [key: string]: MarkingProps; } interface ExpenseEntry extends Expense { category_name?: string; color?: string; } type Filters = { search?: string; month?: string; day?: string; } const constructMarkedDates = (data : {[column: string]: any}) => { let markedDates: MarkedDates = {}; data.forEach((value: any) => { const dateKey: string = String(value["expense_datetime"]).split(" ")[0] if(markedDates[dateKey] === undefined){ markedDates[dateKey] = {dots: []} } markedDates[dateKey].dots?.push({color: value["category_color"]}) }) return markedDates; } export default function Page() { const { colors, theme } = useTheme() const navigation = useNavigation(); const router = useRouter(); const [plusShow, setPlusShow] = useState(true); const prevOffset = useRef(0); const [filter, setFilter] = useState({}) const profile = require("../../../assets/images/profile.jpg") const handleScroll = (event: NativeSyntheticEvent)=>{ const currentOffset = event.nativeEvent.contentOffset.y >= 0 ? event.nativeEvent.contentOffset.y : 0 const isScrollingUp : boolean = currentOffset <= prevOffset.current; const isTop : boolean = currentOffset === 0 prevOffset.current = currentOffset setPlusShow(isScrollingUp || isTop) } 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 expenses = useMemo( () => { console.log("expenses updated") return data.map((elem) => { return { guid: elem["expense_guid"], name: elem["expense_name"], amount: elem["expense_amount"], dateTime: elem["expense_datetime"], category_name: elem["category_name"], color: elem["category_color"]} }) }, [data]) const filteredExpenses = useMemo( () => { console.log("filter called") return expenses.filter((elem) => { if(filter.month && filter.month.substring(5, 7) !== elem.dateTime?.substring(5, 7)){ return false; } if(filter.day && filter.day.substring(8, 10) !== elem.dateTime?.substring(8, 10)){ return false; } if(filter.search && !elem.name?.toLowerCase().includes(filter.search.toLowerCase())){ return false; } return true; }) }, [expenses, filter] ) const expenseDates = useMemo( () => { let markedDates = constructMarkedDates(data) if(filter.day) { const dateKey: string = String(filter.day).split(" ")[0] if(markedDates[dateKey] === undefined){ markedDates[dateKey] = {} } markedDates[dateKey].selected = true; markedDates[dateKey].selectedColor = colors.accentColor; } return markedDates; } , [data, filter.day]) useEffect(() => { const unsubscribe = navigation.addListener('focus', () => { console.log("focus event triggered") reFetch(); }); return unsubscribe; }, [navigation]); const hanldeDaySelect = (date: string | undefined) => { if(filter.day === date) setFilter({...filter, day: undefined}); else setFilter({...filter, day: date}); } const handleMonthSelect = (date: string | undefined) => { setFilter({...filter, month: date, day: undefined}); } const handleSearch = (text: string) => { setFilter({...filter, search: text}); } console.log("rendered") return ( {plusShow && { router.push("/expense/new"); // 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 && } */} {router.push("/userSettings")}}/> { hanldeDaySelect(date.dateString) }} onMonthChange={(date) => { handleMonthSelect(date.dateString) }} /> handleSearch(text)} style={{marginBottom: 20}}> } renderItem = {({item}) => {router.push(`/expense/${guid}`)}} />} keyExtractor={item => item.guid!} ItemSeparatorComponent={() => { return (); }} refreshControl={ } onScroll={handleScroll} scrollEventThrottle={20} ListEmptyComponent={EmptyListCompenent} /> ); } const styles = StyleSheet.create({ safeAreaViewStyle: { flex: 1, paddingHorizontal: 10 }, itemSeperatorStyle: { marginVertical: 5, } });