Skip to content

Commit dcf5084

Browse files
authored
Don't limit trade history (#839)
* Don't limit trade history * revert: end after incrementing
1 parent 36231de commit dcf5084

File tree

6 files changed

+77
-92
lines changed

6 files changed

+77
-92
lines changed

frontend/src/pages/trade/TradeOffers.tsx

Lines changed: 3 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,14 @@ import { useTranslation } from 'react-i18next'
22
import { Spinner } from '@/components/Spinner'
33
import TradePartner from '@/pages/trade/components/TradePartner.tsx'
44
import { useAccount } from '@/services/account/useAccount'
5-
import { useTrades } from '@/services/trade/useTrade.ts'
5+
import { useActiveTrades } from '@/services/trade/useTrade.ts'
66
import type { TradeRow } from '@/types'
77

88
function TradeOffers() {
99
const { t } = useTranslation(['trade-matches', 'common'])
1010

1111
const { data: account, isLoading: isLoadingAccount } = useAccount()
12-
const { data: trades, isLoading: isLoadingTrades } = useTrades()
12+
const { data: trades, isLoading: isLoadingTrades } = useActiveTrades()
1313

1414
if (isLoadingAccount || isLoadingTrades) {
1515
return <Spinner size="lg" overlay />
@@ -25,38 +25,22 @@ function TradeOffers() {
2525

2626
//split into two groups for finished and ongoing trades
2727
const friends = groupTrades(trades, account.friend_id)
28-
const friendsHasTrades = Object.fromEntries(
29-
Object.entries(friends).map(([key, value]) => [key, Number(activeTrades(value as TradeRow[], account.friend_id).length === 0)]),
30-
)
3128
const friendsLastActivity = Object.fromEntries(
3229
Object.entries(friends).map(([key, value]) => [key, Math.max(...(value as TradeRow[]).map((row) => new Date(row.updated_at).getTime()))]),
3330
)
3431
const friendIds = Object.keys(friends).toSorted((a, b) => {
35-
if (friendsHasTrades[a] !== friendsHasTrades[b]) {
36-
return friendsHasTrades[a] - friendsHasTrades[b]
37-
}
3832
return friendsLastActivity[b] - friendsLastActivity[a]
3933
})
4034

4135
return (
4236
<div className="flex flex-col items-center mx-auto gap-6 sm:px-4 mb-12 w-full">
4337
{friendIds.map((friend_id) => (
44-
<TradePartner key={friend_id} friendId={friend_id} />
38+
<TradePartner key={friend_id} friendId={friend_id} activeTrades={friends[friend_id] as TradeRow[]} />
4539
))}
4640
</div>
4741
)
4842
}
4943

50-
function activeTrades(arr: TradeRow[], id: string) {
51-
return arr.filter((row) => {
52-
if (row.offering_friend_id === id) {
53-
return !row.offerer_ended
54-
} else {
55-
return !row.receiver_ended
56-
}
57-
})
58-
}
59-
6044
function groupTrades(arr: TradeRow[], id: string) {
6145
return Object.groupBy(arr, (row) => {
6246
if (row.offering_friend_id === id) {

frontend/src/pages/trade/components/TradeList.tsx

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,21 +12,16 @@ import type { CardAmountUpdate, CollectionRow, TradeRow, TradeStatus } from '@/t
1212

1313
interface Props {
1414
trades: TradeRow[]
15-
viewHistory: boolean
1615
}
1716

18-
function TradeList({ trades, viewHistory }: Props) {
17+
function TradeList({ trades }: Props) {
1918
const { t } = useTranslation('trade-matches')
2019
const { toast } = useToast()
2120

2221
const { data: account } = useAccount()
2322
const { data: ownedCards = new Map<number, CollectionRow>() } = useCollection()
2423
const updateCardsMutation = useUpdateCards()
2524

26-
function interesting(row: TradeRow) {
27-
return (row.offering_friend_id === account?.friend_id && !row.offerer_ended) || (row.receiving_friend_id === account?.friend_id && !row.receiver_ended)
28-
}
29-
const filteredTrades = viewHistory ? trades.filter((x) => !interesting(x)) : trades.filter(interesting)
3025
const [selectedTradeId, setSelectedTradeId] = useState<number | undefined>(undefined)
3126
const updateTradeMutation = useUpdateTrade()
3227

@@ -138,9 +133,9 @@ function TradeList({ trades, viewHistory }: Props) {
138133
}
139134
}
140135

141-
const selectedTrade = filteredTrades.find((r) => r.id === selectedTradeId)
136+
const selectedTrade = trades.find((r) => r.id === selectedTradeId)
142137

143-
if (filteredTrades.length === 0) {
138+
if (trades.length === 0) {
144139
return null
145140
}
146141

@@ -151,7 +146,7 @@ function TradeList({ trades, viewHistory }: Props) {
151146
<h4 className="text-lg font-medium w-1/2 ml-8">{t('youReceive')}</h4>
152147
</div>
153148
<ul className="flex flex-col gap-2 md:gap-0">
154-
{filteredTrades
149+
{trades
155150
.toSorted((a, b) => (a.created_at > b.created_at ? -1 : 1))
156151
.map((x) => (
157152
<TradeListRow key={x.id} row={x} selectedTradeId={selectedTradeId} setSelectedTradeId={setSelectedTradeId} />

frontend/src/pages/trade/components/TradePartner.tsx

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,38 @@
1+
import { useQuery } from '@tanstack/react-query'
12
import { ChevronRight } from 'lucide-react'
23
import { useState } from 'react'
34
import { useTranslation } from 'react-i18next'
45
import { Link } from 'react-router'
6+
import { Spinner } from '@/components/Spinner'
57
import { Button } from '@/components/ui/button.tsx'
68
import { FriendIdDisplay } from '@/components/ui/friend-id-display.tsx'
79
import { Switch } from '@/components/ui/switch.tsx'
810
import TradeList from '@/pages/trade/components/TradeList.tsx'
911
import { usePublicAccount } from '@/services/account/useAccount.ts'
10-
import { useTrades } from '@/services/trade/useTrade.ts'
12+
import { getAllTrades } from '@/services/trade/tradeService'
13+
import type { TradeRow } from '@/types'
1114

1215
interface TradePartnerProps {
1316
friendId: string
17+
activeTrades: TradeRow[]
1418
}
1519

16-
function TradePartner({ friendId }: TradePartnerProps) {
20+
function TradePartner({ friendId, activeTrades }: TradePartnerProps) {
1721
const { t } = useTranslation(['trade-matches', 'common'])
1822

19-
const { data: trades, isLoading: isLoadingTrades } = useTrades()
2023
const { data: friendAccount, isLoading: isLoadingAccount } = usePublicAccount(friendId)
2124

2225
const [viewHistory, setViewHistory] = useState<boolean>(false)
26+
const allTrades = useQuery({
27+
queryKey: ['trades', friendId],
28+
queryFn: () => getAllTrades(friendId),
29+
enabled: viewHistory,
30+
})
2331

24-
if (isLoadingTrades || isLoadingAccount) {
32+
if (isLoadingAccount) {
2533
return null
2634
}
2735

28-
if (!trades) {
29-
return <p className="text-xl text-center py-8">{t('common:error')}</p>
30-
}
31-
32-
const partnerTrades = trades.filter((t) => t.offering_friend_id === friendId || t.receiving_friend_id === friendId)
33-
3436
return (
3537
<div className="w-full">
3638
<div className="flex justify-between items-center mb-1 mx-1">
@@ -52,7 +54,15 @@ function TradePartner({ friendId }: TradePartnerProps) {
5254
</Link>
5355
</span>
5456
</div>
55-
{friendAccount !== null && <TradeList trades={partnerTrades} viewHistory={viewHistory} />}
57+
{viewHistory ? (
58+
allTrades.isLoading ? (
59+
<Spinner size="md" />
60+
) : (
61+
allTrades.data && <TradeList trades={allTrades.data} />
62+
)
63+
) : (
64+
<TradeList trades={activeTrades} />
65+
)}
5666
</div>
5767
)
5868
}

frontend/src/services/auth/useAuth.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ export function useLogout() {
2626
await queryClient.invalidateQueries({ queryKey: ['user'] })
2727
await queryClient.invalidateQueries({ queryKey: ['account'] })
2828
await queryClient.invalidateQueries({ queryKey: ['collection'] })
29-
await queryClient.invalidateQueries({ queryKey: ['trade'] })
29+
await queryClient.invalidateQueries({ queryKey: ['trades'] })
3030
if (email) {
3131
removeLocalCacheItems(email)
3232
}
@@ -64,7 +64,7 @@ export function useVerifyOTP() {
6464
await queryClient.invalidateQueries({ queryKey: ['user'] })
6565
await queryClient.invalidateQueries({ queryKey: ['account'] })
6666
await queryClient.invalidateQueries({ queryKey: ['collection'] })
67-
await queryClient.invalidateQueries({ queryKey: ['trade'] })
67+
await queryClient.invalidateQueries({ queryKey: ['trades'] })
6868
},
6969
})
7070
}

frontend/src/services/trade/tradeService.ts

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,31 @@
11
import { supabase } from '@/lib/supabase.ts'
22
import type { TradePartners, TradeRow } from '@/types'
33

4-
export const getTrades = async () => {
5-
const { data, error } = await supabase.from('trades').select().limit(35).order('updated_at', { ascending: false })
4+
export async function getActiveTrades(userFriendId: string) {
5+
if (!userFriendId.match(/^\d{16}$/)) {
6+
throw new Error('Error fetching active trades: Invalid friendId')
7+
}
8+
const { data, error } = await supabase
9+
.from('trades')
10+
.select()
11+
.or(`and(offering_friend_id.eq.${userFriendId},offerer_ended.eq.false),and(receiving_friend_id.eq.${userFriendId},receiver_ended.eq.false)`)
612

713
if (error) {
8-
console.log('supa error', error)
9-
throw new Error('Error fetching trades')
14+
throw new Error(`Error fetching active trades: ${error.message}`)
15+
}
16+
17+
return data.map((x) => ({ ...x, created_at: new Date(x.created_at), updated_at: new Date(x.updated_at) })) as TradeRow[]
18+
}
19+
20+
export async function getAllTrades(friendId: string) {
21+
if (!friendId.match(/^\d{16}$/)) {
22+
throw new Error('Error fetching active trades: Invalid friendId')
1023
}
24+
const { data, error } = await supabase.from('trades').select().or(`offering_friend_id.eq.${friendId},receiving_friend_id.eq.${friendId}`)
1125

12-
console.log('fetched trades', data)
26+
if (error) {
27+
throw new Error(`Error fetching active trades with ${friendId}: ${error.message}`)
28+
}
1329

1430
return data.map((x) => ({ ...x, created_at: new Date(x.created_at), updated_at: new Date(x.updated_at) })) as TradeRow[]
1531
}
Lines changed: 26 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,22 @@
11
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
2+
import { supabase } from '@/lib/supabase'
23
import { useAccount } from '@/services/account/useAccount.ts'
3-
import { getTrades, getTradingPartners, insertTrade, updateTrade } from '@/services/trade/tradeService.ts'
4+
import { getActiveTrades, getTradingPartners, insertTrade, updateTrade } from '@/services/trade/tradeService.ts'
45
import type { TradeRow } from '@/types'
56

6-
export function useTrades() {
7+
export function useActiveTrades() {
8+
const { data: account } = useAccount()
9+
const friendId = account?.friend_id
710
return useQuery({
8-
queryKey: ['trade'],
9-
queryFn: getTrades,
11+
queryKey: ['trades'],
12+
queryFn: () => getActiveTrades(friendId as string),
13+
enabled: Boolean(friendId),
14+
throwOnError: true,
1015
})
1116
}
1217

1318
export function useTradingPartners(enabled: boolean, cardId: number | undefined) {
1419
const { data: account } = useAccount()
15-
1620
return useQuery({
1721
queryKey: ['trading-partners', cardId],
1822
queryFn: () => getTradingPartners(account?.email as string, cardId),
@@ -27,9 +31,7 @@ export function useInsertTrade() {
2731

2832
return useMutation({
2933
mutationFn: (trade: TradeRow) => insertTrade(trade),
30-
onSuccess: async () => {
31-
await queryClient.invalidateQueries({ queryKey: ['trade'] })
32-
},
34+
onSuccess: () => queryClient.invalidateQueries({ queryKey: ['trades'] }),
3335
})
3436
}
3537

@@ -38,52 +40,30 @@ export function useUpdateTrade() {
3840

3941
return useMutation({
4042
mutationFn: ({ id, trade }: { id: number; trade: Partial<TradeRow> }) => updateTrade(id, trade),
41-
onSuccess: async () => {
42-
await queryClient.invalidateQueries({ queryKey: ['trade'] })
43-
await queryClient.invalidateQueries({ queryKey: ['actionableTradeCount'] })
44-
},
43+
onSuccess: () => queryClient.invalidateQueries({ queryKey: ['trades'] }),
4544
})
4645
}
4746

4847
export function useActionableTradeCount() {
49-
const { data: trades } = useTrades()
5048
const { data: account } = useAccount()
5149

5250
return useQuery({
53-
queryKey: ['actionableTradeCount', trades, account?.friend_id],
54-
queryFn: () => {
55-
console.log('openTrades', trades, account)
56-
if (!account || !trades) {
57-
console.log('no account or trades')
58-
return 0
51+
queryKey: ['trades', 'new'],
52+
queryFn: async () => {
53+
if (!account) {
54+
throw new Error('Account is needed to fetch new trades')
5955
}
60-
61-
// trades where i'm the receiver but didn't accept/decline yet
62-
const sentTrades = trades?.filter((t) => t.receiving_friend_id === account?.friend_id && t.status === 'offered')
63-
console.log('sentTrades', sentTrades)
64-
65-
const nonCompletedTrades = trades?.filter((t) => {
66-
if (t.status !== 'finished') {
67-
return false //trade marked as completed
68-
}
69-
70-
if (t.offering_friend_id === account?.friend_id && t.offerer_ended) {
71-
return false //I initiated and also ended
72-
}
73-
if (t.receiving_friend_id === account?.friend_id && t.receiver_ended) {
74-
return false //I received and also ended
75-
}
76-
77-
if (!sentTrades?.includes(t)) {
78-
return false //already counted in the sentTrades array, so don't count twice
79-
}
80-
81-
return true
82-
})
83-
84-
console.log('nonCompletedTrades', nonCompletedTrades)
85-
86-
return sentTrades?.length + nonCompletedTrades?.length
56+
const { count, error } = await supabase
57+
.from('trades')
58+
.select('*', { count: 'exact', head: true })
59+
.eq('status', 'offered')
60+
.eq('receiving_friend_id', account?.friend_id)
61+
if (error) {
62+
console.log('supabase error', error)
63+
throw new Error('Failed fetching new trades')
64+
}
65+
return count as number
8766
},
67+
enabled: Boolean(account?.friend_id),
8868
})
8969
}

0 commit comments

Comments
 (0)