From 22dbe2b3b5d64dfe48273daf31ee15d18fbd906e Mon Sep 17 00:00:00 2001 From: Max Koon <22125083+k2on@users.noreply.github.com> Date: Wed, 15 Oct 2025 15:52:15 -0400 Subject: [PATCH] feat: show transaction info --- api/src/zero.ts | 49 ++++++++++++++++++----------- app/index.tsx | 32 ++++++++++++------- shared/src/db/schema/public.ts | 6 ++++ shared/src/mutators.ts | 18 ----------- shared/src/queries.ts | 3 +- shared/src/zero-schema.gen.ts | 56 ++++++++++++++++++++++++++++++++++ 6 files changed, 116 insertions(+), 48 deletions(-) diff --git a/api/src/zero.ts b/api/src/zero.ts index 77e7078..7790f48 100644 --- a/api/src/zero.ts +++ b/api/src/zero.ts @@ -24,7 +24,7 @@ import { Configuration, CountryCode, PlaidApi, PlaidEnvironments, Products } fro import { randomUUID } from "crypto"; import { db } from "./db"; import { balance, plaidAccessTokens, plaidLink, transaction } from "@money/shared/db"; -import { asc, desc, eq, sql } from "drizzle-orm"; +import { asc, desc, eq, sql, type InferInsertModel } from "drizzle-orm"; const configuration = new Configuration({ @@ -79,6 +79,7 @@ const createMutators = (authData: AuthData | null) => { token: link_token, }); }, + async get(_, { link_token }) { isLoggedIn(authData); @@ -100,29 +101,41 @@ const createMutators = (authData: AuthData | null) => { token: data.access_token, }); }, + async updateTransactions() { isLoggedIn(authData); - const accessToken = await db.query.plaidAccessTokens.findFirst({ - where: eq(plaidAccessTokens.userId, authData.user.id) + const accounts = await db.query.plaidAccessTokens.findMany({ + where: eq(plaidAccessTokens.userId, authData.user.id), }); - if (!accessToken) throw Error("No plaid account"); - - const { data } = await plaidClient.transactionsGet({ - access_token: accessToken.token, - start_date: "2025-10-01", - end_date: "2025-10-15", - }); - - for (const t of data.transactions) { - await db.insert(transaction).values({ - id: randomUUID(), - user_id: authData.user.id, - name: t.name, - amount: t.amount.toString(), - }); + if (accounts.length == 0) { + console.error("No accounts"); + return; } + for (const account of accounts) { + const { data } = await plaidClient.transactionsGet({ + access_token: account.token, + start_date: "2025-10-01", + end_date: "2025-10-15", + }); + + const transactions = data.transactions.map(tx => ({ + id: randomUUID(), + user_id: authData.user.id, + plaid_id: tx.transaction_id, + name: tx.name, + amount: tx.amount as any, + datetime: tx.datetime ? new Date(tx.datetime) : new Date(tx.date), + authorized_datetime: tx.authorized_datetime ? new Date(tx.authorized_datetime) : undefined, + json: JSON.stringify(tx), + } satisfies InferInsertModel)); + + await db.insert(transaction).values(transactions).onConflictDoNothing({ + target: transaction.plaid_id, + }) + } }, + async updateBalences() { isLoggedIn(authData); const accounts = await db.query.plaidAccessTokens.findMany({ diff --git a/app/index.tsx b/app/index.tsx index 819df8b..a4c3a5d 100644 --- a/app/index.tsx +++ b/app/index.tsx @@ -1,8 +1,9 @@ import { authClient } from '@/lib/auth-client'; -import { Button, Linking, ScrollView, Text, View } from 'react-native'; +import { Button, Linking, Pressable, ScrollView, Text, View } from 'react-native'; import { useQuery, useZero } from "@rocicorp/zero/react"; import { queries, type Mutators, type Schema } from '@money/shared'; import { useEffect, useState } from 'react'; +import { transaction } from '@/shared/src/db'; export default function HomeScreen() { const { data: session } = authClient.useSession(); @@ -34,7 +35,7 @@ export default function HomeScreen() { }, [transactions]); return ( - + {plaidLink &&