Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(mobile): add store data refetching in interval #213

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 7 additions & 17 deletions apps/mobile/app/(app)/(tabs)/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,10 @@ import { Text } from '@/components/ui/text'
import { useColorScheme } from '@/hooks/useColorScheme'
import { formatDateShort } from '@/lib/date'
import { theme } from '@/lib/theme'
import { walletQueries } from '@/queries/wallet'
import { useTransactionList } from '@/stores/transaction/hooks'
import { dayjsExtended } from '@6pm/utilities'
import { t } from '@lingui/macro'
import { useLingui } from '@lingui/react'
import { useQueryClient } from '@tanstack/react-query'
import { format } from 'date-fns/format'
import { LinearGradient } from 'expo-linear-gradient'
import { groupBy, mapValues, orderBy, sumBy } from 'lodash-es'
Expand All @@ -29,7 +27,6 @@ export default function HomeScreen() {
const { top, bottom } = useSafeAreaInsets()
const { colorScheme } = useColorScheme()
const [walletAccountId, setWalletAccountId] = useState<string | undefined>()
const queryClient = useQueryClient()
const [filter, setFilter] = useState<HomeFilter>(HomeFilter.All)
const [view, setView] = useState<HomeView>(HomeView.SpentThisWeek)
const [customTimeRange, setCustomTimeRange] = useState<{
Expand All @@ -51,18 +48,11 @@ export default function HomeScreen() {
}
}, [customTimeRange, filter])

const { transactions, isLoading, isRefetching, refetch } = useTransactionList(
{
walletAccountId,
categoryId,
...timeRange,
},
)

const handleRefresh = () => {
refetch()
queryClient.invalidateQueries({ queryKey: walletQueries.list._def })
}
const { transactions, isLoading } = useTransactionList({
walletAccountId,
categoryId,
...timeRange,
})

const handleSetFilter = (filter: HomeFilter) => {
if (filter === HomeFilter.ByDay) {
Expand Down Expand Up @@ -134,8 +124,8 @@ export default function HomeScreen() {
}
className="flex-1 bg-card"
contentContainerStyle={{ paddingBottom: bottom + 32 }}
refreshing={isRefetching}
onRefresh={handleRefresh}
// refreshing={isRefetching}
// onRefresh={handleRefresh}
sections={transactionsGroupByDate}
keyExtractor={(item) => item.id}
renderItem={({ item: transaction }) => (
Expand Down
2 changes: 1 addition & 1 deletion apps/mobile/app/_layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ import { useWarmUpBrowser } from '@/hooks/use-warm-up-browser'
import { useColorScheme } from '@/hooks/useColorScheme'
import { queryClient } from '@/lib/client'
import { LocaleProvider } from '@/locales/provider'
import { StoreProvider } from '@/stores/store-provider'
import { StoreProvider } from '@/stores/core/store-provider'
import { BottomSheetModalProvider } from '@gorhom/bottom-sheet'
import AsyncStorage from '@react-native-async-storage/async-storage'
import NetInfo from '@react-native-community/netinfo'
Expand Down
18 changes: 14 additions & 4 deletions apps/mobile/stores/category/hooks.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,27 @@ import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
import { keyBy, omit } from 'lodash-es'
import { useMemo } from 'react'
import { z } from 'zod'
import type { StoreHookQueryOptions } from '../core/stores'
import { categoryQueries } from './queries'
import { useCategoryStore } from './store'

export const useCategoryList = () => {
export const useCategoryListQueryOptions = (
queryOptions?: StoreHookQueryOptions,
) => {
const categories = useCategoryStore().categories
const setCategoriesState = useCategoryStore((state) => state.setCategories)

const query = useQuery({
return {
...categoryQueries.all({ setCategoriesState }),
initialData: categories?.length > 0 ? categories : undefined,
})
...queryOptions,
}
}

export const useCategoryList = (queryOptions?: StoreHookQueryOptions) => {
const categories = useCategoryStore().categories
const queryOpts = useCategoryListQueryOptions(queryOptions)

const query = useQuery(queryOpts)

const { categoriesDict, incomeCategories, expenseCategories } =
useMemo(() => {
Expand Down
30 changes: 30 additions & 0 deletions apps/mobile/stores/core/store-interval-update.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { useSuspenseQueries } from '@tanstack/react-query'
import type { FC } from 'react'
import { useCategoryListQueryOptions } from '../category/hooks'
import { useTransactionListQueryOptions } from '../transaction/hooks'
import type { StoreHookQueryOptions } from './stores'
import { STORE_SYNC_INTERVAL } from './stores.const'

export type StoreIntervalUpdateProps = {
interval?: number
}

export const StoreIntervalUpdate: FC<StoreIntervalUpdateProps> = ({
interval = STORE_SYNC_INTERVAL,
}) => {
const queryOptions: StoreHookQueryOptions = {
refetchInterval: interval,
refetchIntervalInBackground: true,
}
const categoryListQueryOptions = useCategoryListQueryOptions(queryOptions)
const transactionListQueryOptions = useTransactionListQueryOptions(
undefined,
queryOptions,
)

useSuspenseQueries({
queries: [{ ...categoryListQueryOptions }, transactionListQueryOptions],
})

return null
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
useEffect,
useState,
} from 'react'
import { StoreIntervalUpdate } from './store-interval-update'
import { useResetAllStores } from './use-reset-all-stores'

export type StoreProviderProps = {
Expand Down Expand Up @@ -60,5 +61,10 @@ export const StoreProvider: FC<StoreProviderProps> = ({ children }) => {
return null
}

return children
return (
<>
<StoreIntervalUpdate />
{children}
</>
)
}
1 change: 1 addition & 0 deletions apps/mobile/stores/core/stores.const.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const STORE_SYNC_INTERVAL = 1000 * 5 // 5 seconds
4 changes: 4 additions & 0 deletions apps/mobile/stores/core/stores.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export type StoreHookQueryOptions = {
refetchInterval?: number
refetchIntervalInBackground?: boolean
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { useCallback } from 'react'
import { useBudgetStore } from './budget/store'
import { useCategoryStore } from './category/store'
import { useTransactionStore } from './transaction/store'
import { useBudgetStore } from '../budget/store'
import { useCategoryStore } from '../category/store'
import { useTransactionStore } from '../transaction/store'

export const useResetAllStores = () => {
const resetBudgetStore = useBudgetStore((state) => state._reset)
Expand Down
69 changes: 54 additions & 15 deletions apps/mobile/stores/transaction/hooks.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { UNCATEGORIZED_ID } from '@/components/home/category-chart'
import { getHonoClient } from '@/lib/client'
import { useMeQuery } from '@/queries/auth'
import { dayjsExtended } from '@6pm/utilities'
import {
type TransactionFormValues,
type TransactionPopulated,
Expand All @@ -12,22 +13,28 @@ import { keyBy } from 'lodash-es'
import { useMemo } from 'react'
import { z } from 'zod'
import { useCategoryList } from '../category/hooks'
import type { StoreHookQueryOptions } from '../core/stores'
import { transactionQueries } from './queries'
import { useTransactionStore } from './store'

export function useTransactionList({
from,
to,
walletAccountId,
budgetId,
categoryId,
}: {
from: Date
to: Date
walletAccountId?: string
budgetId?: string
categoryId?: string
}) {
// TODO: Update params here
const DEFAULT_FROM = dayjsExtended()
.subtract(10, 'year')
.startOf('year')
.toDate()
const DEFAULT_TO = dayjsExtended().add(10, 'year').endOf('year').toDate()

export const useTransactionListQueryOptions = (
{
// FIXME: This should be dynamic @bkdev98
from = DEFAULT_FROM,
to = DEFAULT_TO,
}: {
from?: Date
to?: Date
} = {},
queryOptions?: StoreHookQueryOptions,
) => {
const transactionsInRangeFromStore =
useTransactionStore().transactions.filter(
(t) =>
Expand All @@ -36,7 +43,7 @@ export function useTransactionList({
const updateTransactionsByRange = useTransactionStore(
(state) => state.updateTransactionsByRange,
)
const query = useQuery({
return {
...transactionQueries.list({
filters: { from, to },
updateTransactionsByRangeInStore: updateTransactionsByRange,
Expand All @@ -45,7 +52,39 @@ export function useTransactionList({
transactionsInRangeFromStore.length > 0
? transactionsInRangeFromStore
: undefined,
})
...queryOptions,
}
}

export function useTransactionList(
{
// FIXME: This should be dynamic @bkdev98
from = DEFAULT_FROM,
to = DEFAULT_TO,
walletAccountId,
budgetId,
categoryId,
}: {
from?: Date
to?: Date
walletAccountId?: string
budgetId?: string
categoryId?: string
} = {},
queryOptions?: StoreHookQueryOptions,
) {
const transactionsInRangeFromStore =
useTransactionStore().transactions.filter(
(t) => new Date(t.date) >= from && new Date(t.date) <= to,
)
const queryOpts = useTransactionListQueryOptions(
{
from,
to,
},
queryOptions,
)
const query = useQuery(queryOpts)

const { transactions, transactionDict, totalExpense, totalIncome } =
useMemo(() => {
Expand Down