Use tRPC for recent groups page (#253)

* Use tRPC for recent groups page

* Use tRPC for adding group by URL

* Use tRPC for saving visited group

* Group context
This commit is contained in:
Sebastien Castiel
2024-10-20 17:43:42 -04:00
parent 39c1a2ffc6
commit 4db788680e
31 changed files with 314 additions and 260 deletions

View File

@@ -34,14 +34,11 @@ import { getImageData, usePresignedUpload } from 'next-s3-upload'
import Image from 'next/image'
import { useRouter } from 'next/navigation'
import { PropsWithChildren, ReactNode, useState } from 'react'
import { useCurrentGroup } from '../current-group-context'
const MAX_FILE_SIZE = 5 * 1024 ** 2
export function CreateFromReceiptButton({ groupId }: { groupId: string }) {
return <CreateFromReceiptButton_ groupId={groupId} />
}
function CreateFromReceiptButton_({ groupId }: { groupId: string }) {
export function CreateFromReceiptButton() {
const t = useTranslations('CreateFromReceipt')
const isDesktop = useMediaQuery('(min-width: 640px)')
@@ -70,15 +67,14 @@ function CreateFromReceiptButton_({ groupId }: { groupId: string }) {
}
description={<>{t('Dialog.description')}</>}
>
<ReceiptDialogContent groupId={groupId} />
<ReceiptDialogContent />
</DialogOrDrawer>
)
}
function ReceiptDialogContent({ groupId }: { groupId: string }) {
const { data: groupData } = trpc.groups.get.useQuery({ groupId })
function ReceiptDialogContent() {
const { group } = useCurrentGroup()
const { data: categoriesData } = trpc.categories.list.useQuery()
const group = groupData?.group
const categories = categoriesData?.categories
const locale = useLocale()

View File

@@ -64,7 +64,7 @@ const enforceCurrencyPattern = (value: string) =>
.replace(/[^-\d.]/g, '') // remove all non-numeric characters
const getDefaultSplittingOptions = (
group: AppRouterOutput['groups']['get']['group'],
group: NonNullable<AppRouterOutput['groups']['get']['group']>,
) => {
const defaultValue = {
splitMode: 'EVENLY' as const,
@@ -145,7 +145,7 @@ export function ExpenseForm({
onDelete,
runtimeFeatureFlags,
}: {
group: AppRouterOutput['groups']['get']['group']
group: NonNullable<AppRouterOutput['groups']['get']['group']>
categories: AppRouterOutput['categories']['list']['categories']
expense?: AppRouterOutput['groups']['expenses']['get']['expense']
onSubmit: (value: ExpenseFormValues, participantId?: string) => Promise<void>
@@ -250,7 +250,6 @@ export function ExpenseForm({
>(new Set())
const sExpense = isIncome ? 'Income' : 'Expense'
const sPaid = isIncome ? 'received' : 'paid'
useEffect(() => {
setManuallyEditedParticipants(new Set())

View File

@@ -11,6 +11,7 @@ import Link from 'next/link'
import { forwardRef, useEffect, useMemo, useState } from 'react'
import { useInView } from 'react-intersection-observer'
import { useDebounce } from 'use-debounce'
import { useCurrentGroup } from '../current-group-context'
const PAGE_SIZE = 20
@@ -56,12 +57,12 @@ function getGroupedExpensesByDate(expenses: ExpensesType) {
}, {})
}
export function ExpenseList({ groupId }: { groupId: string }) {
const { data: groupData } = trpc.groups.get.useQuery({ groupId })
export function ExpenseList() {
const { groupId, group } = useCurrentGroup()
const [searchText, setSearchText] = useState('')
const [debouncedSearchText] = useDebounce(searchText, 300)
const participants = groupData?.group.participants
const participants = group?.participants
useEffect(() => {
if (!participants) return
@@ -103,6 +104,7 @@ const ExpenseListForSearch = ({
searchText: string
}) => {
const utils = trpc.useUtils()
const { group } = useCurrentGroup()
useEffect(() => {
// Until we use tRPC more widely and can invalidate the cache on expense
@@ -124,11 +126,7 @@ const ExpenseListForSearch = ({
const expenses = data?.pages.flatMap((page) => page.expenses)
const hasMore = data?.pages.at(-1)?.hasMore ?? false
const { data: groupData, isLoading: groupIsLoading } =
trpc.groups.get.useQuery({ groupId })
const isLoading =
expensesAreLoading || !expenses || groupIsLoading || !groupData
const isLoading = expensesAreLoading || !expenses || !group
useEffect(() => {
if (inView && hasMore && !isLoading) fetchNextPage()
@@ -172,7 +170,7 @@ const ExpenseListForSearch = ({
<ExpenseCard
key={expense.id}
expense={expense}
currency={groupData.group.currency}
currency={group.currency}
groupId={groupId}
/>
))}

View File

@@ -15,6 +15,7 @@ import { Download, Plus } from 'lucide-react'
import { Metadata } from 'next'
import { useTranslations } from 'next-intl'
import Link from 'next/link'
import { useCurrentGroup } from '../current-group-context'
export const revalidate = 3600
@@ -23,13 +24,12 @@ export const metadata: Metadata = {
}
export default function GroupExpensesPageClient({
groupId,
enableReceiptExtract,
}: {
groupId: string
enableReceiptExtract: boolean
}) {
const t = useTranslations('Expenses')
const { groupId } = useCurrentGroup()
return (
<>
@@ -50,9 +50,7 @@ export default function GroupExpensesPageClient({
<Download className="w-4 h-4" />
</Link>
</Button>
{enableReceiptExtract && (
<CreateFromReceiptButton groupId={groupId} />
)}
{enableReceiptExtract && <CreateFromReceiptButton />}
<Button asChild size="icon">
<Link
href={`/groups/${groupId}/expenses/create`}
@@ -65,7 +63,7 @@ export default function GroupExpensesPageClient({
</div>
<CardContent className="p-0 pt-2 pb-4 sm:pb-6 flex flex-col gap-4 relative">
<ExpenseList groupId={groupId} />
<ExpenseList />
</CardContent>
</Card>

View File

@@ -8,14 +8,9 @@ export const metadata: Metadata = {
title: 'Expenses',
}
export default async function GroupExpensesPage({
params: { groupId },
}: {
params: { groupId: string }
}) {
export default async function GroupExpensesPage() {
return (
<GroupExpensesPageClient
groupId={groupId}
enableReceiptExtract={env.NEXT_PUBLIC_ENABLE_RECEIPT_EXTRACT}
/>
)