Skip to content

Commit 42873dd

Browse files
59 looking for trade (#68)
* Looking For Trade Implementation and Lint Fixes * Lint Fixes * Adjusted scroll bar to be on the side rather than the middle of the page, and added back in Pack Headers * Add Trade Values to Cards * Pull Owned Cards and User from App Component * feat: overview page calculations, added cardsdb lib (#69) * Cardsdb (#70) * feat: overview page calculations, added cardsdb lib * some refactoring and working on bar chart with probabilities * Add new updates * Adding in for branch fix * Ran npm install * Remove Cards File Again --------- Co-authored-by: Marcel Panse <marcel.panse@gmail.com>
1 parent 3d0ee06 commit 42873dd

File tree

4 files changed

+239
-3
lines changed

4 files changed

+239
-3
lines changed

frontend/package-lock.json

Lines changed: 63 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

frontend/src/App.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ function App() {
4848
<Route path="/" element={<Overview user={user} ownedCards={ownedCards} />} />
4949
<Route path="/verify" element={<Verify />} />
5050
<Route path="/collection" element={<Collection user={user} ownedCards={ownedCards} setOwnedCards={setOwnedCards} />} />
51-
<Route path="/trade" element={<Trade />} />
51+
<Route path="/trade" element={<Trade user={user} ownedCards={ownedCards} />} />
5252
</Routes>
5353
</ThemeProvider>
5454
)
Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
import type { Card } from '@/types'
2+
import { type Row, createColumnHelper, getCoreRowModel, getGroupedRowModel, useReactTable } from '@tanstack/react-table'
3+
import { useVirtualizer } from '@tanstack/react-virtual'
4+
import { useMemo, useRef } from 'react'
5+
import type { Card as CardType } from '../types'
6+
import FancyCard from './FancyCard'
7+
8+
const tradeableRaritiesDictionary: { [id: string]: number } = {
9+
'◊': 0,
10+
'◊◊': 0,
11+
'◊◊◊': 120,
12+
'◊◊◊◊': 500,
13+
'☆': 500,
14+
}
15+
16+
export function LookingForTrade({ cards }: { cards: CardType[] }) {
17+
const columnHelper = createColumnHelper<CardType>()
18+
const parentRef = useRef<HTMLDivElement>(null)
19+
20+
const columns = useMemo(() => {
21+
return [
22+
columnHelper.accessor('image', {
23+
id: 'imageUrl',
24+
}),
25+
columnHelper.accessor('card_id', {
26+
id: 'card_id',
27+
}),
28+
columnHelper.accessor('name', {
29+
id: 'name',
30+
}),
31+
columnHelper.accessor('pack', {
32+
id: 'pack',
33+
}),
34+
]
35+
}, [])
36+
37+
// Columns and data are defined in a stable reference, will not cause infinite loop!
38+
const table = useReactTable({
39+
columns,
40+
data: cards.filter((c) => Object.keys(tradeableRaritiesDictionary).includes(c.rarity)),
41+
enableGrouping: true,
42+
getCoreRowModel: getCoreRowModel(),
43+
getGroupedRowModel: getGroupedRowModel(),
44+
initialState: {
45+
grouping: ['pack'],
46+
},
47+
})
48+
const groupedRows = table.getRowModel().rows
49+
50+
const groupedGridRows = groupedRows.map((groupRow) => {
51+
const header = { type: 'header', row: groupRow }
52+
const dataRows = groupRow.subRows.map((subRow) => ({ type: 'data', row: subRow }))
53+
54+
const gridRows = []
55+
for (let i = 0; i < dataRows.length; i += 5) {
56+
gridRows.push(dataRows.slice(i, i + 5))
57+
}
58+
59+
return { header, gridRows }
60+
})
61+
62+
const flattenedRows = groupedGridRows.flatMap((group) => [
63+
{ type: 'header', height: 45, data: group.header }, // Group header
64+
...group.gridRows.map((gridRow) => ({ type: 'gridRow', height: 269, data: gridRow })), // Grid rows
65+
])
66+
67+
const rowVirtualizer = useVirtualizer({
68+
getScrollElement: () => parentRef.current,
69+
count: flattenedRows.length,
70+
estimateSize: (index) => (flattenedRows[index].type === 'header' ? 45 : 269) + 12,
71+
overscan: 5,
72+
})
73+
74+
return (
75+
<div ref={parentRef} className="h-[calc(100vh-180px)] overflow-y-auto">
76+
<div
77+
style={{
78+
height: `${rowVirtualizer.getTotalSize()}px`,
79+
position: 'relative',
80+
}}
81+
className="w-full"
82+
>
83+
{rowVirtualizer.getVirtualItems().map((virtualRow) => {
84+
const row = flattenedRows[virtualRow.index]
85+
console.log('Row', row)
86+
return (
87+
<div
88+
key={virtualRow.key}
89+
style={{
90+
position: 'absolute',
91+
top: 0,
92+
left: 0,
93+
width: '100%',
94+
height: `${virtualRow.size}px`,
95+
transform: `translateY(${virtualRow.start}px)`,
96+
}}
97+
>
98+
{row.type === 'header' ? (
99+
<h2 className="mt-10 w-[900px] mx-auto scroll-m-20 border-b pb-2 text-3xl font-semibold tracking-tight transition-colors first:mt-0">
100+
{(row.data as { type: string; row: Row<Card> }).row.getValue('pack')}
101+
</h2>
102+
) : (
103+
<div className="flex justify-center gap-5">
104+
{(row.data as { type: string; row: Row<Card> }[]).map(({ row: subRow }) => {
105+
const card = subRow.original
106+
return (
107+
<div
108+
key={`div_${subRow.original.card_id}`}
109+
className="flex flex-col items-center gap-y-2 w-fit border border-gray-700 p-4 rounded-lg shadow-md hover:shadow-lg transition duration-200 group"
110+
>
111+
<FancyCard key={`card_${card.card_id}`} card={card} selected={true} setIsSelected={() => {}} />
112+
<p className="text-[12px] font-semibold whitespace-nowrap overflow-hidden text-ellipsis max-w-[130px]">
113+
{card.card_id} - {card.name}
114+
</p>
115+
<div className="bg-gray-600 rounded-xl">
116+
<span className="text-lg font-semibold m-3">{tradeableRaritiesDictionary[card.rarity]}</span>
117+
</div>
118+
</div>
119+
)
120+
})}
121+
</div>
122+
)}
123+
</div>
124+
)
125+
})}
126+
</div>
127+
</div>
128+
)
129+
}

frontend/src/pages/trade/Trade.tsx

Lines changed: 46 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,47 @@
1-
export function Trade() {
2-
return <h1>Coming soon</h1>
1+
import { LookingForTrade } from '@/components/LookingForTrade'
2+
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'
3+
import { a1Cards, a1aCards, a2Cards, paCards } from '@/lib/CardsDB'
4+
import type { CollectionRow } from '@/types'
5+
import type { Models } from 'appwrite'
6+
7+
interface Props {
8+
user: Models.User<Models.Preferences> | null
9+
ownedCards: CollectionRow[]
10+
}
11+
12+
export function Trade({ user, ownedCards }: Props) {
13+
const lookingForTradeCards = () => {
14+
const allCards = [...a1Cards, ...a2Cards, ...a1aCards, ...paCards]
15+
const missingCards = allCards.filter((ac) => ownedCards.findIndex((oc) => oc.card_id === ac.card_id) === -1)
16+
return missingCards
17+
}
18+
19+
if (user) {
20+
return (
21+
<div className="flex flex-col gap-y-4">
22+
<Tabs defaultValue="looking_for">
23+
<div className="max-w-[900px] mx-auto">
24+
<TabsList className="m-auto mt-4 mb-8">
25+
<TabsTrigger value="looking_for">Looking For</TabsTrigger>
26+
<TabsTrigger value="for_trade">For Trade</TabsTrigger>
27+
<TabsTrigger value="buying_tokens">Buying Tokens</TabsTrigger>
28+
</TabsList>
29+
</div>
30+
<div className="max-w-auto mx-auto">
31+
<TabsContent value="looking_for">
32+
<LookingForTrade cards={lookingForTradeCards()} />
33+
</TabsContent>
34+
<TabsContent value="for_trade">
35+
<span>For Trade</span>
36+
</TabsContent>
37+
<TabsContent value="buying_tokens">
38+
<span>Buying Tokens</span>
39+
</TabsContent>
40+
</div>
41+
</Tabs>
42+
</div>
43+
)
44+
}
45+
46+
return null
347
}

0 commit comments

Comments
 (0)