Skip to content

Commit

Permalink
fix: expense ui
Browse files Browse the repository at this point in the history
  • Loading branch information
paolojulian committed Jul 28, 2024
1 parent 394d023 commit 2df6c6b
Show file tree
Hide file tree
Showing 11 changed files with 55 additions and 87 deletions.
3 changes: 3 additions & 0 deletions app/_layout.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import UpdateBudgetBottomSheet from '@/components/expenses/UpdateBudgetBottomSheet';
import { colors } from '@/constants/Colors';
import DefaultTheme from '@/constants/Theme';
import { useBackgroundFetch } from '@/hooks/useBackgroundFetch';
import { useCustomFonts } from '@/hooks/useCustomFonts';
Expand All @@ -8,6 +9,7 @@ import { ThemeProvider } from '@react-navigation/native';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { Stack } from 'expo-router';
import * as SplashScreen from 'expo-splash-screen';
import { StatusBar } from 'expo-status-bar';
import { useEffect } from 'react';
import { GestureHandlerRootView } from 'react-native-gesture-handler';
import 'react-native-reanimated';
Expand Down Expand Up @@ -41,6 +43,7 @@ export default function RootLayout() {

return (
<>
<StatusBar backgroundColor={colors.white} />
<GestureHandlerRootView style={{ flex: 1 }}>
<DatabaseProvider>
<QueryClientProvider client={queryClient}>
Expand Down
7 changes: 4 additions & 3 deletions app/add.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import AddFactory from '@/components/add/AddFactory';
import { isSupportedAddType } from '@/components/add/utils';
import AppSafeAreaView from '@/components/common/AppSafeAreaView';
import Container from '@/components/common/Container';
import Tabs from '@/components/common/Tabs';
import { TabItem } from '@/components/common/Tabs/TabsItem';
Expand All @@ -8,7 +9,7 @@ import ThemedView from '@/components/common/ThemedView';
import { MaterialCommunityIcons } from '@expo/vector-icons';
import { useLocalSearchParams, useNavigation } from 'expo-router';
import React, { useState } from 'react';
import { KeyboardAvoidingView, Platform, SafeAreaView, StyleSheet } from 'react-native';
import { KeyboardAvoidingView, Platform, StyleSheet } from 'react-native';

export type SupportedAddItems = 'Expense' | 'Todo';

Expand Down Expand Up @@ -36,7 +37,7 @@ export default function AddScreen() {
};

return (
<SafeAreaView style={{ flex: 1 }}>
<AppSafeAreaView>
<KeyboardAvoidingView
behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
style={styles.container}
Expand All @@ -63,7 +64,7 @@ export default function AddScreen() {
</ThemedView>
</ThemedView>
</KeyboardAvoidingView>
</SafeAreaView>
</AppSafeAreaView>
);
}

Expand Down
13 changes: 12 additions & 1 deletion components/common/EasyDatePicker/EasyDatePicker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,18 @@ type EasyDatePickerProps = {
};

export default function EasyDatePicker({ onSelectDate, selectedDate, label }: EasyDatePickerProps) {
const [selectedType, setSelectedType] = useState<EasyDatePickerTypes | null>(null);
const [selectedType, setSelectedType] = useState<EasyDatePickerTypes | null>(() => {
if (!selectedDate) {
return null;
}
if (dayjs(selectedDate).isSame(dayjs(), 'day')) {
return 'today';
}
if (dayjs(selectedDate).isSame(dayjs().add(1, 'day'), 'day')) {
return 'tomorrow';
}
return 'custom';
});

const handlePressToday = () => {
setSelectedType('today');
Expand Down
16 changes: 10 additions & 6 deletions components/common/HeaderWithBackButton/HeaderWithBackButton.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { MaterialCommunityIcons } from '@expo/vector-icons';
import PageHeader from '../PageHeader';
import { PageHeaderProps } from '../PageHeader/PageHeader';
import { View } from 'react-native';
import { colors } from '@/constants/Colors';

type HeaderWithBackButtonProps = {
onBackPress: () => void;
Expand All @@ -11,11 +13,13 @@ export default function HeaderWithBackButton({
...pageHeaderProps
}: HeaderWithBackButtonProps) {
return (
<PageHeader
LeftComponent={
<MaterialCommunityIcons name={'chevron-left'} size={32} onPress={onBackPress} />
}
{...pageHeaderProps}
/>
<View style={{ zIndex: 1, paddingBottom: 8, backgroundColor: colors.white }}>
<PageHeader
LeftComponent={
<MaterialCommunityIcons name={'chevron-left'} size={32} onPress={onBackPress} />
}
{...pageHeaderProps}
/>
</View>
);
}
31 changes: 0 additions & 31 deletions components/expenses/EditBudgetCard/EditBudgetCard.tsx

This file was deleted.

1 change: 0 additions & 1 deletion components/expenses/EditBudgetCard/index.ts

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import CategorySelect from '@/components/common/CategorySelect';
import Container from '@/components/common/Container';
import EasyDatePicker from '@/components/common/EasyDatePicker';
import RecurringExpenseField from '@/components/common/RecurringExpenseBottomSheet';
import ThemedView from '@/components/common/ThemedView';
import ComboBox from '@/components/common/forms/ComboBox';
import DatePicker from '@/components/common/forms/DatePicker';
import TextArea from '@/components/common/forms/TextArea';
import TextField from '@/components/common/forms/TextField';
import useCategories from '@/hooks/services/category/useCategories';
import { useGetOrCreateCategory } from '@/hooks/services/category/useGetOrCreateCategory';
import { Expense } from '@/hooks/services/expense/expense.types';
import { useExpense } from '@/hooks/services/expense/useExpense';
import { useUpdateExpense } from '@/hooks/services/expense/useUpdateExpense';
Expand All @@ -28,7 +27,6 @@ export default function EditExpenseForm({ id }: EditExpenseFormProps) {
const { data: categories, isLoading: isLoadingCategories } = useCategories();
const { data: expense, isLoading: isLoadingExpense } = useExpense(id);
const { mutateAsync: updateExpenseMutate } = useUpdateExpense(id);
const getOrCreateCategory = useGetOrCreateCategory();

const validateAndHandleFieldUpdate = async (
fieldName: keyof EditExpenseFormValues,
Expand All @@ -40,7 +38,7 @@ export default function EditExpenseForm({ id }: EditExpenseFormProps) {
updateExpenseMutate({ [resolvedFieldName]: value });
return true;
} catch (e) {
console.log(e);
console.error(e);
return false;
}
};
Expand All @@ -54,12 +52,6 @@ export default function EditExpenseForm({ id }: EditExpenseFormProps) {
const categoryName =
categories?.find(({ id }) => id === expense?.category_id)?.category_name || '';

const getCategoryIdByName = async (name: string) => {
const categoryId = await getOrCreateCategory(name);

return categoryId ?? null;
};

return (
<Container style={{ flex: 1 }}>
<Formik<EditExpenseFormValues>
Expand All @@ -78,7 +70,7 @@ export default function EditExpenseForm({ id }: EditExpenseFormProps) {
// No form submission needed, everything is inline editing
}}
>
{({ handleChange, handleBlur, setFieldValue, values, errors, touched }) => (
{({ handleBlur, setFieldValue, values, errors, touched }) => (
<ThemedView style={{ flex: 1, paddingBottom: 16 }}>
<ThemedView style={{ gap: 8, flex: 1 }}>
<TextField
Expand All @@ -96,27 +88,12 @@ export default function EditExpenseForm({ id }: EditExpenseFormProps) {
returnKeyLabel="Done Title"
returnKeyType="done"
/>
<ComboBox
onSelect={async value => {

<CategorySelect
onSelect={value => {
setFieldValue('category', value);
const categoryId = await getCategoryIdByName(value);
updateExpenseMutate({ category_id: categoryId });
}}
onBlur={async () => {
if (!values.category) return;
const categoryId = await getCategoryIdByName(values.category);
updateExpenseMutate({ category_id: categoryId });
}}
onChangeText={handleChange('category')}
isError={!!errors.category && !!touched.category}
errorMessage={errors.category}
options={categories?.map(({ category_name }) => category_name) ?? []}
value={values.category}
label="Category"
placeholder="e.g. Restaurant, Grocery"
keyboardType="default"
returnKeyLabel="Done Category"
returnKeyType="done"
/>
<TextField
isError={!!errors.amount && !!touched.amount}
Expand All @@ -133,13 +110,11 @@ export default function EditExpenseForm({ id }: EditExpenseFormProps) {
returnKeyLabel="Done"
returnKeyType="done"
/>
<DatePicker
value={values.transactionDate}
<EasyDatePicker
selectedDate={values.transactionDate}
onSelectDate={value => {
setFieldValue('transactionDate', value);
debouncedHandleChange('transactionDate', dayjs(value).unix());
}}
variant="border"
/>
<RecurringExpenseField
value={values.recurrence}
Expand Down
11 changes: 6 additions & 5 deletions components/expenses/EditExpenseScreen/EditExpenseScreen.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { RouteNames } from '@/app/_layout';
import AppSafeAreaView from '@/components/common/AppSafeAreaView';
import HeaderWithBackButton from '@/components/common/HeaderWithBackButton';
import ThemedView from '@/components/common/ThemedView';
import { useLocalSearchParams, useRouter } from 'expo-router';
import { SafeAreaView, ScrollView } from 'react-native';
import { ScrollView } from 'react-native';
import DeleteExpenseButton from './DeleteExpenseButton';
import EditExpenseForm from './EditExpenseForm';
import RecurredPayments from './EditExpenseForm/RecurredPayments';
Expand All @@ -29,19 +30,19 @@ export default function EditExpenseScreen() {
}

return (
<SafeAreaView style={{ flex: 1 }}>
<ScrollView style={{ flex: 1 }} stickyHeaderIndices={[0]} keyboardShouldPersistTaps="never">
<AppSafeAreaView>
<ScrollView style={{ flex: 1 }} keyboardShouldPersistTaps="never">
<HeaderWithBackButton
onBackPress={handleBackPress}
title="Expense"
RightComponent={<DeleteExpenseButton id={id} />}
/>

<ThemedView style={{ flex: 1, gap: 16 }}>
<ThemedView style={{ flex: 1, gap: 16, marginBottom: 24 }}>
<EditExpenseForm id={id} />
<RecurredPayments id={id} />
</ThemedView>
</ScrollView>
</SafeAreaView>
</AppSafeAreaView>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,6 @@ const verticalStyles = StyleSheet.create({
alignItems: 'center',
},
pieChart: {
marginTop: 0,
marginTop: 16,
},
});
9 changes: 7 additions & 2 deletions components/home/BudgetOverview/BudgetOverview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,17 @@ import Container from '@/components/common/Container';
import React from 'react';
import TotalSpentTodayCard from './TotalSpentTodayCard';
import RemainingBudgetCard from '@/components/expenses/RemainingBudgetCard';
import { View } from 'react-native';

function BudgetOverview() {
return (
<Container style={{ flexDirection: 'row', gap: 8 }}>
<RemainingBudgetCard variant="vertical" />
<TotalSpentTodayCard />
<View style={{ flex: 1 }}>
<RemainingBudgetCard variant="vertical" />
</View>
<View style={{ flex: 1 }}>
<TotalSpentTodayCard />
</View>
</Container>
);
}
Expand Down
6 changes: 3 additions & 3 deletions components/tasks/TaskWorkArea.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import TodoList from '@/components/tasks/TaskList';
import { SafeAreaView } from 'react-native';
import AppSafeAreaView from '../common/AppSafeAreaView';

export default function TaskWorkArea() {
return (
<SafeAreaView>
<AppSafeAreaView>
<TodoList />
</SafeAreaView>
</AppSafeAreaView>
);
}

0 comments on commit 2df6c6b

Please sign in to comment.