Add tRPC, use it for group expenses, balances and information page (#246)

* Add tRPC, use it for group expense list

* Use tRPC for balances

* Use tRPC in group information + better loading states
This commit is contained in:
Sebastien Castiel
2024-10-19 17:42:11 -04:00
committed by GitHub
parent 727803ea5c
commit 66e15e419e
24 changed files with 671 additions and 239 deletions

10
src/trpc/routers/_app.ts Normal file
View File

@@ -0,0 +1,10 @@
import { groupsRouter } from '@/trpc/routers/groups'
import { inferRouterOutputs } from '@trpc/server'
import { createTRPCRouter } from '../init'
export const appRouter = createTRPCRouter({
groups: groupsRouter,
})
export type AppRouter = typeof appRouter
export type AppRouterOutput = inferRouterOutputs<AppRouter>

View File

@@ -0,0 +1,6 @@
import { createTRPCRouter } from '@/trpc/init'
import { listGroupBalancesProcedure } from '@/trpc/routers/groups/balances/list.procedure'
export const groupBalancesRouter = createTRPCRouter({
list: listGroupBalancesProcedure,
})

View File

@@ -0,0 +1,19 @@
import { getGroupExpenses } from '@/lib/api'
import {
getBalances,
getPublicBalances,
getSuggestedReimbursements,
} from '@/lib/balances'
import { baseProcedure } from '@/trpc/init'
import { z } from 'zod'
export const listGroupBalancesProcedure = baseProcedure
.input(z.object({ groupId: z.string().min(1) }))
.query(async ({ input: { groupId } }) => {
const expenses = await getGroupExpenses(groupId)
const balances = getBalances(expenses)
const reimbursements = getSuggestedReimbursements(balances)
const publicBalances = getPublicBalances(reimbursements)
return { balances: publicBalances, reimbursements }
})

View File

@@ -0,0 +1,6 @@
import { createTRPCRouter } from '@/trpc/init'
import { listGroupExpensesProcedure } from '@/trpc/routers/groups/expenses/list.procedure'
export const groupExpensesRouter = createTRPCRouter({
list: listGroupExpensesProcedure,
})

View File

@@ -0,0 +1,29 @@
import { getGroupExpenses } from '@/lib/api'
import { baseProcedure } from '@/trpc/init'
import { z } from 'zod'
export const listGroupExpensesProcedure = baseProcedure
.input(
z.object({
groupId: z.string().min(1),
cursor: z.number().optional(),
limit: z.number().optional(),
filter: z.string().optional(),
}),
)
.query(async ({ input: { groupId, cursor = 0, limit = 10, filter } }) => {
const expenses = await getGroupExpenses(groupId, {
offset: cursor,
length: limit + 1,
filter,
})
return {
expenses: expenses.slice(0, limit).map((expense) => ({
...expense,
createdAt: new Date(expense.createdAt),
expenseDate: new Date(expense.expenseDate),
})),
hasMore: !!expenses[limit],
nextCursor: cursor + limit,
}
})

View File

@@ -0,0 +1,10 @@
import { createTRPCRouter } from '@/trpc/init'
import { groupBalancesRouter } from '@/trpc/routers/groups/balances'
import { groupExpensesRouter } from '@/trpc/routers/groups/expenses'
import { groupInformationRouter } from '@/trpc/routers/groups/information'
export const groupsRouter = createTRPCRouter({
expenses: groupExpensesRouter,
balances: groupBalancesRouter,
information: groupInformationRouter,
})

View File

@@ -0,0 +1,21 @@
import { getGroup } from '@/lib/api'
import { baseProcedure } from '@/trpc/init'
import { TRPCError } from '@trpc/server'
import { z } from 'zod'
export const getGroupInformationProcedure = baseProcedure
.input(
z.object({
groupId: z.string().min(1),
}),
)
.query(async ({ input: { groupId } }) => {
const group = await getGroup(groupId)
if (!group) {
throw new TRPCError({
code: 'NOT_FOUND',
message: 'Group not found.',
})
}
return { information: group.information ?? '' }
})

View File

@@ -0,0 +1,6 @@
import { createTRPCRouter } from '@/trpc/init'
import { getGroupInformationProcedure } from '@/trpc/routers/groups/information/get.procedure'
export const groupInformationRouter = createTRPCRouter({
get: getGroupInformationProcedure,
})