mirror of
https://github.com/spliit-app/spliit.git
synced 2026-03-03 03:26:12 +01:00
Q: Why do mountain climbers rope themselves together?
A: To prevent the sensible ones from going home.
This commit is contained in:
@@ -9,7 +9,6 @@
|
|||||||
"check-formatting": "prettier -c src",
|
"check-formatting": "prettier -c src",
|
||||||
"prettier": "prettier -w src",
|
"prettier": "prettier -w src",
|
||||||
"postinstall": "prisma generate",
|
"postinstall": "prisma generate",
|
||||||
"build": "tsc"
|
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@formatjs/intl-localematcher": "^0.5.4",
|
"@formatjs/intl-localematcher": "^0.5.4",
|
||||||
|
|||||||
@@ -2,4 +2,4 @@ export {
|
|||||||
appRouter,
|
appRouter,
|
||||||
type AppRouter,
|
type AppRouter,
|
||||||
type AppRouterOutput,
|
type AppRouterOutput,
|
||||||
} from '@/trpc/routers/_app'
|
} from './trpc/routers/_app'
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { prisma } from '@/lib/prisma'
|
|
||||||
import { ExpenseFormValues, GroupFormValues } from '@/lib/schemas'
|
|
||||||
import { ActivityType, Expense } from '@prisma/client'
|
import { ActivityType, Expense } from '@prisma/client'
|
||||||
import { nanoid } from 'nanoid'
|
import { nanoid } from 'nanoid'
|
||||||
|
import { prisma } from './prisma'
|
||||||
|
import { ExpenseFormValues, GroupFormValues } from './schemas'
|
||||||
|
|
||||||
export function randomId() {
|
export function randomId() {
|
||||||
return nanoid()
|
return nanoid()
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { getGroupExpenses } from '@/lib/api'
|
|
||||||
import { Participant } from '@prisma/client'
|
import { Participant } from '@prisma/client'
|
||||||
import { match } from 'ts-pattern'
|
import { match } from 'ts-pattern'
|
||||||
|
import { getGroupExpenses } from './api'
|
||||||
|
|
||||||
export type Balances = Record<
|
export type Balances = Record<
|
||||||
Participant['id'],
|
Participant['id'],
|
||||||
@@ -87,7 +87,10 @@ export function getPublicBalances(reimbursements: Reimbursement[]): Balances {
|
|||||||
* This ensures that a participant executing a suggested reimbursement
|
* This ensures that a participant executing a suggested reimbursement
|
||||||
* does not result in completely new repayment suggestions.
|
* does not result in completely new repayment suggestions.
|
||||||
*/
|
*/
|
||||||
function compareBalancesForReimbursements(b1: any, b2: any): number {
|
function compareBalancesForReimbursements(
|
||||||
|
b1: { total: number; participantId: string },
|
||||||
|
b2: { total: number; participantId: string },
|
||||||
|
): number {
|
||||||
// positive balances come before negative balances
|
// positive balances come before negative balances
|
||||||
if (b1.total > 0 && 0 > b2.total) {
|
if (b1.total > 0 && 0 > b2.total) {
|
||||||
return -1
|
return -1
|
||||||
@@ -95,7 +98,7 @@ function compareBalancesForReimbursements(b1: any, b2: any): number {
|
|||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
// if signs match, sort based on userid
|
// if signs match, sort based on userid
|
||||||
return b1.participantId < b2.participantId ? -1 : 1
|
return b1.participantId.localeCompare(b2.participantId)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getSuggestedReimbursements(
|
export function getSuggestedReimbursements(
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { PrismaClient } from '@prisma/client'
|
|||||||
|
|
||||||
declare const global: Global & { prisma?: PrismaClient }
|
declare const global: Global & { prisma?: PrismaClient }
|
||||||
|
|
||||||
export let p: PrismaClient = undefined as any as PrismaClient
|
export let p: PrismaClient = undefined as unknown as PrismaClient
|
||||||
|
|
||||||
if (typeof window === 'undefined') {
|
if (typeof window === 'undefined') {
|
||||||
// await delay(1000)
|
// await delay(1000)
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { getGroupExpenses } from '@/lib/api'
|
import { getGroupExpenses } from './api'
|
||||||
|
|
||||||
export function getTotalGroupSpending(
|
export function getTotalGroupSpending(
|
||||||
expenses: NonNullable<Awaited<ReturnType<typeof getGroupExpenses>>>,
|
expenses: NonNullable<Awaited<ReturnType<typeof getGroupExpenses>>>,
|
||||||
@@ -55,14 +55,15 @@ export function getTotalActiveUserShare(
|
|||||||
// Calculate the user's share based on their percentage of the total expense
|
// Calculate the user's share based on their percentage of the total expense
|
||||||
total += (expense.amount * userPaidFor.shares) / 10000 // Assuming shares are out of 10000 for percentage
|
total += (expense.amount * userPaidFor.shares) / 10000 // Assuming shares are out of 10000 for percentage
|
||||||
break
|
break
|
||||||
case 'BY_SHARES':
|
case 'BY_SHARES': // Calculate the user's share based on their shares relative to the total shares
|
||||||
// Calculate the user's share based on their shares relative to the total shares
|
{
|
||||||
const totalShares = paidFors.reduce(
|
const totalShares = paidFors.reduce(
|
||||||
(sum, paidFor) => sum + paidFor.shares,
|
(sum, paidFor) => sum + paidFor.shares,
|
||||||
0,
|
0,
|
||||||
)
|
)
|
||||||
total += (expense.amount * userPaidFor.shares) / totalShares
|
total += (expense.amount * userPaidFor.shares) / totalShares
|
||||||
break
|
break
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -1,21 +0,0 @@
|
|||||||
import { defaultShouldDehydrateQuery, QueryClient } from '@tanstack/react-query'
|
|
||||||
import superjson from 'superjson'
|
|
||||||
|
|
||||||
export function makeQueryClient() {
|
|
||||||
return new QueryClient({
|
|
||||||
defaultOptions: {
|
|
||||||
queries: {
|
|
||||||
staleTime: 30 * 1000,
|
|
||||||
},
|
|
||||||
dehydrate: {
|
|
||||||
serializeData: superjson.serialize,
|
|
||||||
shouldDehydrateQuery: (query) =>
|
|
||||||
defaultShouldDehydrateQuery(query) ||
|
|
||||||
query.state.status === 'pending',
|
|
||||||
},
|
|
||||||
hydrate: {
|
|
||||||
deserializeData: superjson.deserialize,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
import { categoriesRouter } from '@/trpc/routers/categories'
|
|
||||||
import { groupsRouter } from '@/trpc/routers/groups'
|
|
||||||
import { inferRouterOutputs } from '@trpc/server'
|
import { inferRouterOutputs } from '@trpc/server'
|
||||||
import { createTRPCRouter } from '../init'
|
import { createTRPCRouter } from '../init'
|
||||||
|
import { categoriesRouter } from './categories'
|
||||||
|
|
||||||
export const appRouter = createTRPCRouter({
|
export const appRouter = createTRPCRouter({
|
||||||
groups: groupsRouter,
|
groups: groupsRouter,
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { createTRPCRouter } from '@/trpc/init'
|
import { createTRPCRouter } from '../../init'
|
||||||
import { listCategoriesProcedure } from '@/trpc/routers/categories/list.procedure'
|
import { listCategoriesProcedure } from './list.procedure'
|
||||||
|
|
||||||
export const categoriesRouter = createTRPCRouter({
|
export const categoriesRouter = createTRPCRouter({
|
||||||
list: listCategoriesProcedure,
|
list: listCategoriesProcedure,
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { getCategories } from '@/lib/api'
|
import { getCategories } from '../../../lib/api'
|
||||||
import { baseProcedure } from '@/trpc/init'
|
import { baseProcedure } from '../../init'
|
||||||
|
|
||||||
export const listCategoriesProcedure = baseProcedure.query(async () => {
|
export const listCategoriesProcedure = baseProcedure.query(async () => {
|
||||||
return { categories: await getCategories() }
|
return { categories: await getCategories() }
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { createTRPCRouter } from '@/trpc/init'
|
import { createTRPCRouter } from '../../../init'
|
||||||
import { listGroupActivitiesProcedure } from '@/trpc/routers/groups/activities/list.procedure'
|
import { listGroupActivitiesProcedure } from './list.procedure'
|
||||||
|
|
||||||
export const activitiesRouter = createTRPCRouter({
|
export const activitiesRouter = createTRPCRouter({
|
||||||
list: listGroupActivitiesProcedure,
|
list: listGroupActivitiesProcedure,
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { getActivities } from '@/lib/api'
|
|
||||||
import { baseProcedure } from '@/trpc/init'
|
|
||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
|
import { getActivities } from '../../../../lib/api'
|
||||||
|
import { baseProcedure } from '../../../init'
|
||||||
|
|
||||||
export const listGroupActivitiesProcedure = baseProcedure
|
export const listGroupActivitiesProcedure = baseProcedure
|
||||||
.input(
|
.input(
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { createTRPCRouter } from '@/trpc/init'
|
import { createTRPCRouter } from '../../../init'
|
||||||
import { listGroupBalancesProcedure } from '@/trpc/routers/groups/balances/list.procedure'
|
import { listGroupBalancesProcedure } from './list.procedure'
|
||||||
|
|
||||||
export const groupBalancesRouter = createTRPCRouter({
|
export const groupBalancesRouter = createTRPCRouter({
|
||||||
list: listGroupBalancesProcedure,
|
list: listGroupBalancesProcedure,
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
import { getGroupExpenses } from '@/lib/api'
|
import { z } from 'zod'
|
||||||
|
import { getGroupExpenses } from '../../../../lib/api'
|
||||||
import {
|
import {
|
||||||
getBalances,
|
getBalances,
|
||||||
getPublicBalances,
|
getPublicBalances,
|
||||||
getSuggestedReimbursements,
|
getSuggestedReimbursements,
|
||||||
} from '@/lib/balances'
|
} from '../../../../lib/balances'
|
||||||
import { baseProcedure } from '@/trpc/init'
|
import { baseProcedure } from '../../../init'
|
||||||
import { z } from 'zod'
|
|
||||||
|
|
||||||
export const listGroupBalancesProcedure = baseProcedure
|
export const listGroupBalancesProcedure = baseProcedure
|
||||||
.input(z.object({ groupId: z.string().min(1) }))
|
.input(z.object({ groupId: z.string().min(1) }))
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { createGroup } from '@/lib/api'
|
|
||||||
import { groupFormSchema } from '@/lib/schemas'
|
|
||||||
import { baseProcedure } from '@/trpc/init'
|
|
||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
|
import { createGroup } from '../../../lib/api'
|
||||||
|
import { groupFormSchema } from '../../../lib/schemas'
|
||||||
|
import { baseProcedure } from '../../init'
|
||||||
|
|
||||||
export const createGroupProcedure = baseProcedure
|
export const createGroupProcedure = baseProcedure
|
||||||
.input(
|
.input(
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { createExpense } from '@/lib/api'
|
|
||||||
import { expenseFormSchema } from '@/lib/schemas'
|
|
||||||
import { baseProcedure } from '@/trpc/init'
|
|
||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
|
import { createExpense } from '../../../../lib/api'
|
||||||
|
import { expenseFormSchema } from '../../../../lib/schemas'
|
||||||
|
import { baseProcedure } from '../../../init'
|
||||||
|
|
||||||
export const createGroupExpenseProcedure = baseProcedure
|
export const createGroupExpenseProcedure = baseProcedure
|
||||||
.input(
|
.input(
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { deleteExpense } from '@/lib/api'
|
|
||||||
import { baseProcedure } from '@/trpc/init'
|
|
||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
|
import { deleteExpense } from '../../../../lib/api'
|
||||||
|
import { baseProcedure } from '../../../init'
|
||||||
|
|
||||||
export const deleteGroupExpenseProcedure = baseProcedure
|
export const deleteGroupExpenseProcedure = baseProcedure
|
||||||
.input(
|
.input(
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { getExpense } from '@/lib/api'
|
|
||||||
import { baseProcedure } from '@/trpc/init'
|
|
||||||
import { TRPCError } from '@trpc/server'
|
import { TRPCError } from '@trpc/server'
|
||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
|
import { getExpense } from '../../../../lib/api'
|
||||||
|
import { baseProcedure } from '../../../init'
|
||||||
|
|
||||||
export const getGroupExpenseProcedure = baseProcedure
|
export const getGroupExpenseProcedure = baseProcedure
|
||||||
.input(z.object({ groupId: z.string().min(1), expenseId: z.string().min(1) }))
|
.input(z.object({ groupId: z.string().min(1), expenseId: z.string().min(1) }))
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import { createTRPCRouter } from '@/trpc/init'
|
import { createTRPCRouter } from '../../../init'
|
||||||
import { createGroupExpenseProcedure } from '@/trpc/routers/groups/expenses/create.procedure'
|
import { createGroupExpenseProcedure } from './create.procedure'
|
||||||
import { deleteGroupExpenseProcedure } from '@/trpc/routers/groups/expenses/delete.procedure'
|
import { deleteGroupExpenseProcedure } from './delete.procedure'
|
||||||
import { getGroupExpenseProcedure } from '@/trpc/routers/groups/expenses/get.procedure'
|
import { getGroupExpenseProcedure } from './get.procedure'
|
||||||
import { listGroupExpensesProcedure } from '@/trpc/routers/groups/expenses/list.procedure'
|
import { listGroupExpensesProcedure } from './list.procedure'
|
||||||
import { updateGroupExpenseProcedure } from '@/trpc/routers/groups/expenses/update.procedure'
|
import { updateGroupExpenseProcedure } from './update.procedure'
|
||||||
|
|
||||||
export const groupExpensesRouter = createTRPCRouter({
|
export const groupExpensesRouter = createTRPCRouter({
|
||||||
list: listGroupExpensesProcedure,
|
list: listGroupExpensesProcedure,
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { getGroupExpenses } from '@/lib/api'
|
|
||||||
import { baseProcedure } from '@/trpc/init'
|
|
||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
|
import { getGroupExpenses } from '../../../../lib/api'
|
||||||
|
import { baseProcedure } from '../../../init'
|
||||||
|
|
||||||
export const listGroupExpensesProcedure = baseProcedure
|
export const listGroupExpensesProcedure = baseProcedure
|
||||||
.input(
|
.input(
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { updateExpense } from '@/lib/api'
|
|
||||||
import { expenseFormSchema } from '@/lib/schemas'
|
|
||||||
import { baseProcedure } from '@/trpc/init'
|
|
||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
|
import { updateExpense } from '../../../../lib/api'
|
||||||
|
import { expenseFormSchema } from '../../../../lib/schemas'
|
||||||
|
import { baseProcedure } from '../../../init'
|
||||||
|
|
||||||
export const updateGroupExpenseProcedure = baseProcedure
|
export const updateGroupExpenseProcedure = baseProcedure
|
||||||
.input(
|
.input(
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { getGroup } from '@/lib/api'
|
|
||||||
import { baseProcedure } from '@/trpc/init'
|
|
||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
|
import { getGroup } from '../../../lib/api'
|
||||||
|
import { baseProcedure } from '../../init'
|
||||||
|
|
||||||
export const getGroupProcedure = baseProcedure
|
export const getGroupProcedure = baseProcedure
|
||||||
.input(z.object({ groupId: z.string().min(1) }))
|
.input(z.object({ groupId: z.string().min(1) }))
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { getGroup, getGroupExpensesParticipants } from '@/lib/api'
|
|
||||||
import { baseProcedure } from '@/trpc/init'
|
|
||||||
import { TRPCError } from '@trpc/server'
|
import { TRPCError } from '@trpc/server'
|
||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
|
import { getGroup, getGroupExpensesParticipants } from '../../../lib/api'
|
||||||
|
import { baseProcedure } from '../../init'
|
||||||
|
|
||||||
export const getGroupDetailsProcedure = baseProcedure
|
export const getGroupDetailsProcedure = baseProcedure
|
||||||
.input(z.object({ groupId: z.string().min(1) }))
|
.input(z.object({ groupId: z.string().min(1) }))
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
import { createTRPCRouter } from '@/trpc/init'
|
import { createTRPCRouter } from '../../init'
|
||||||
import { activitiesRouter } from '@/trpc/routers/groups/activities'
|
import { activitiesRouter } from './activities'
|
||||||
import { groupBalancesRouter } from '@/trpc/routers/groups/balances'
|
import { groupBalancesRouter } from './balances'
|
||||||
import { createGroupProcedure } from '@/trpc/routers/groups/create.procedure'
|
import { createGroupProcedure } from './create.procedure'
|
||||||
import { groupExpensesRouter } from '@/trpc/routers/groups/expenses'
|
import { groupExpensesRouter } from './expenses'
|
||||||
import { getGroupProcedure } from '@/trpc/routers/groups/get.procedure'
|
import { getGroupProcedure } from './get.procedure'
|
||||||
import { groupStatsRouter } from '@/trpc/routers/groups/stats'
|
|
||||||
import { updateGroupProcedure } from '@/trpc/routers/groups/update.procedure'
|
|
||||||
import { getGroupDetailsProcedure } from './getDetails.procedure'
|
import { getGroupDetailsProcedure } from './getDetails.procedure'
|
||||||
import { listGroupsProcedure } from './list.procedure'
|
import { listGroupsProcedure } from './list.procedure'
|
||||||
|
import { groupStatsRouter } from './stats'
|
||||||
|
import { updateGroupProcedure } from './update.procedure'
|
||||||
|
|
||||||
export const groupsRouter = createTRPCRouter({
|
export const groupsRouter = createTRPCRouter({
|
||||||
expenses: groupExpensesRouter,
|
expenses: groupExpensesRouter,
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { getGroups } from '@/lib/api'
|
|
||||||
import { baseProcedure } from '@/trpc/init'
|
|
||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
|
import { getGroups } from '../../../lib/api'
|
||||||
|
import { baseProcedure } from '../../init'
|
||||||
|
|
||||||
export const listGroupsProcedure = baseProcedure
|
export const listGroupsProcedure = baseProcedure
|
||||||
.input(
|
.input(
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
import { getGroupExpenses } from '@/lib/api'
|
import { z } from 'zod'
|
||||||
|
import { getGroupExpenses } from '../../../../lib/api'
|
||||||
import {
|
import {
|
||||||
getTotalActiveUserPaidFor,
|
getTotalActiveUserPaidFor,
|
||||||
getTotalActiveUserShare,
|
getTotalActiveUserShare,
|
||||||
getTotalGroupSpending,
|
getTotalGroupSpending,
|
||||||
} from '@/lib/totals'
|
} from '../../../../lib/totals'
|
||||||
import { baseProcedure } from '@/trpc/init'
|
import { baseProcedure } from '../../../init'
|
||||||
import { z } from 'zod'
|
|
||||||
|
|
||||||
export const getGroupStatsProcedure = baseProcedure
|
export const getGroupStatsProcedure = baseProcedure
|
||||||
.input(
|
.input(
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { createTRPCRouter } from '@/trpc/init'
|
import { createTRPCRouter } from '../../../init'
|
||||||
import { getGroupStatsProcedure } from '@/trpc/routers/groups/stats/get.procedure'
|
import { getGroupStatsProcedure } from './get.procedure'
|
||||||
|
|
||||||
export const groupStatsRouter = createTRPCRouter({
|
export const groupStatsRouter = createTRPCRouter({
|
||||||
get: getGroupStatsProcedure,
|
get: getGroupStatsProcedure,
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { updateGroup } from '@/lib/api'
|
|
||||||
import { groupFormSchema } from '@/lib/schemas'
|
|
||||||
import { baseProcedure } from '@/trpc/init'
|
|
||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
|
import { updateGroup } from '../../../lib/api'
|
||||||
|
import { groupFormSchema } from '../../../lib/schemas'
|
||||||
|
import { baseProcedure } from '../../init'
|
||||||
|
|
||||||
export const updateGroupProcedure = baseProcedure
|
export const updateGroupProcedure = baseProcedure
|
||||||
.input(
|
.input(
|
||||||
|
|||||||
@@ -12,10 +12,6 @@
|
|||||||
"isolatedModules": true,
|
"isolatedModules": true,
|
||||||
"jsx": "preserve",
|
"jsx": "preserve",
|
||||||
"incremental": true,
|
"incremental": true,
|
||||||
"paths": {
|
|
||||||
"@/*": ["./src/*"]
|
|
||||||
},
|
|
||||||
"outDir": "./dist",
|
|
||||||
"declaration": true
|
"declaration": true
|
||||||
},
|
},
|
||||||
"include": ["./src/index.ts", "./reset.d.ts"],
|
"include": ["./src/index.ts", "./reset.d.ts"],
|
||||||
|
|||||||
Reference in New Issue
Block a user