Skip to content

Commit 1f9a056

Browse files
#87 devops serveral things (#89)
* fix: remove husky folder from commited code * refactor: use context * fix: add output for errors on promises fetch * feat: add strip comments plugin * fix reverted login logic --------- Co-authored-by: marcel panse <[email protected]>
1 parent e63ec7f commit 1f9a056

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+1158
-1170
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,3 +134,5 @@ dist
134134
.yarn/build-state.yml
135135
.yarn/install-state.gz
136136
.pnp.*
137+
138+
.husky/*

.husky/_/pre-commit

Lines changed: 0 additions & 57 deletions
This file was deleted.

.husky/_/prepare-commit-msg

Lines changed: 0 additions & 57 deletions
This file was deleted.

biome.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,9 @@
6161
},
6262
"performance": {
6363
"noAccumulatingSpread": "off"
64+
},
65+
"nursery": {
66+
"useSortedClasses": "error"
6467
}
6568
}
6669
},

frontend/package.json

Lines changed: 23 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -14,38 +14,41 @@
1414
},
1515
"dependencies": {
1616
"@loadable/component": "^5.16.4",
17-
"@radix-ui/react-dialog": "^1.1.5",
18-
"@radix-ui/react-dropdown-menu": "^2.1.5",
19-
"@radix-ui/react-navigation-menu": "^1.2.4",
17+
"@radix-ui/react-dialog": "^1.1.6",
18+
"@radix-ui/react-dropdown-menu": "^2.1.6",
19+
"@radix-ui/react-navigation-menu": "^1.2.5",
2020
"@radix-ui/react-progress": "^1.1.2",
21-
"@radix-ui/react-slot": "^1.1.1",
22-
"@radix-ui/react-tabs": "^1.1.2",
23-
"@radix-ui/react-toast": "^1.2.5",
24-
"@tailwindcss/vite": "^4.0.3",
21+
"@radix-ui/react-slot": "^1.1.2",
22+
"@radix-ui/react-tabs": "^1.1.3",
23+
"@radix-ui/react-toast": "^1.2.6",
24+
"@tailwindcss/vite": "^4.0.5",
2525
"@tanstack/react-table": "^8.20.6",
26-
"@tanstack/react-virtual": "^3.12.0",
26+
"@tanstack/react-virtual": "^3.13.0",
2727
"@types/recharts": "^1.8.29",
2828
"appwrite": "^17.0.0",
2929
"class-variance-authority": "^0.7.1",
3030
"clsx": "^2.1.1",
31-
"lucide-react": "^0.474.0",
32-
"react": "^18.3.1",
33-
"react-dom": "^18.3.1",
31+
"lucide-react": "^0.475.0",
32+
"react": "^19.0.0",
33+
"react-dom": "^19.0.0",
34+
"react-error-boundary": "^5.0.0",
3435
"react-router": "^7.1.5",
3536
"recharts": "^2.15.1",
3637
"tailwind-merge": "^3.0.1",
37-
"tailwindcss": "^4.0.3",
38-
"tailwindcss-animate": "^1.0.7"
38+
"tailwindcss": "^4.0.5",
39+
"tailwindcss-animate": "^1.0.7",
40+
"valibot": "1.0.0-beta.15"
3941
},
4042
"devDependencies": {
4143
"@types/loadable__component": "^5.13.9",
42-
"@types/node": "^22.13.0",
43-
"@types/react": "^18.3.18",
44-
"@types/react-dom": "^18.3.5",
45-
"@vitejs/plugin-react-swc": "^3.5.0",
44+
"@types/node": "^22.13.1",
45+
"@types/react": "^19.0.8",
46+
"@types/react-dom": "^19.0.3",
47+
"@vitejs/plugin-react-swc": "^3.7.2",
4648
"globals": "^15.14.0",
47-
"typescript": "~5.6.2",
48-
"vite": "^6.0.5"
49+
"typescript": "~5.7.3",
50+
"vite": "^6.1.0",
51+
"vite-plugin-strip-comments": "^0.0.5"
4952
},
50-
"packageManager": "pnpm@9.15.4+sha512.b2dc20e2fc72b3e18848459b37359a32064663e5627a51e4c74b2c29dd8e8e0491483c3abb40789cfd578bf362fb6ba8261b05f0387d76792ed6e23ea3b1b6a0"
53+
"packageManager": "pnpm@10.2.1"
5154
}

frontend/src/App.tsx

Lines changed: 18 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
1-
import { COLLECTION_ID, DATABASE_ID, getDatabase } from '@/lib/Auth'
21
import { getUser } from '@/lib/Auth.ts'
32
import type { CollectionRow } from '@/types'
43
import loadable from '@loadable/component'
5-
import { type Models, Query } from 'appwrite'
64
import { useEffect, useState } from 'react'
75
import { Route, Routes } from 'react-router'
86
import { Header } from './components/ui/Header.tsx'
97
import { Toaster } from './components/ui/toaster.tsx'
8+
import { CollectionContext } from './lib/context/CollectionContext.ts'
9+
import { type User, UserContext } from './lib/context/UserContext.ts'
10+
import { fetchCollection } from './lib/fetchCollection.ts'
1011

1112
// Lazy import for chunking
1213
const Overview = loadable(() => import('./pages/overview/Overview.tsx'))
@@ -15,44 +16,32 @@ const Collection = loadable(() => import('./pages/collection/Collection.tsx'))
1516
const Trade = loadable(() => import('./pages/trade/Trade.tsx'))
1617

1718
function App() {
18-
const [user, setUser] = useState<Models.User<Models.Preferences> | null>(null)
19+
const [user, setUser] = useState<User | null>(null)
1920
const [ownedCards, setOwnedCards] = useState<CollectionRow[]>([])
2021

2122
useEffect(() => {
22-
getUser().then((user) => {
23-
if (user) {
24-
setUser(user)
25-
}
26-
})
23+
getUser().then(setUser).catch(console.error)
2724
}, [])
2825

2926
useEffect(() => {
3027
if (user) {
31-
fetchCollection()
28+
fetchCollection().then(setOwnedCards).catch(console.error)
3229
}
3330
}, [user])
3431

35-
const fetchCollection = async () => {
36-
const db = await getDatabase()
37-
38-
// this gets all your cards at once (max 5k unique cards - there aren't that many unique cards yet), not sure what it does with performance, but we'll see ;-)
39-
const { documents } = await db.listDocuments(DATABASE_ID, COLLECTION_ID, [Query.limit(5000)])
40-
41-
console.log('documents', documents)
42-
setOwnedCards(documents as unknown as CollectionRow[])
43-
}
44-
4532
return (
46-
<>
47-
<Toaster />
48-
<Header user={user} setUser={setUser} />
49-
<Routes>
50-
<Route path="/" element={<Overview user={user} ownedCards={ownedCards} />} />
51-
<Route path="/verify" element={<Verify />} />
52-
<Route path="/collection" element={<Collection user={user} ownedCards={ownedCards} setOwnedCards={setOwnedCards} />} />
53-
<Route path="/trade" element={<Trade user={user} ownedCards={ownedCards} />} />
54-
</Routes>
55-
</>
33+
<UserContext.Provider value={{ user, signOut: () => setUser(null) }}>
34+
<CollectionContext.Provider value={{ ownedCards, setOwnedCards }}>
35+
<Toaster />
36+
<Header />
37+
<Routes>
38+
<Route path="/" element={<Overview />} />
39+
<Route path="/verify" element={<Verify />} />
40+
<Route path="/collection" element={<Collection />} />
41+
<Route path="/trade" element={<Trade />} />
42+
</Routes>
43+
</CollectionContext.Provider>
44+
</UserContext.Provider>
5645
)
5746
}
5847

frontend/src/components/BarChart.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,8 @@ interface PercentageBarChartProps {
3232
footer?: string
3333
}
3434
export const BarChartComponent: FC<PercentageBarChartProps> = ({ title, data, config = {}, footer }) => (
35-
<Card className="border-2 border-solid border-gray-500 rounded-4xl ">
36-
<CardHeader className="text-center text-balance">
35+
<Card className="rounded-4xl border-2 border-gray-500 border-solid ">
36+
<CardHeader className="text-balance text-center">
3737
<CardTitle>{title}</CardTitle>
3838
</CardHeader>
3939
<CardContent>
@@ -46,7 +46,7 @@ export const BarChartComponent: FC<PercentageBarChartProps> = ({ title, data, co
4646
</BarChart>
4747
</ChartContainer>
4848
</CardContent>
49-
<CardFooter className="flex-col flex-1 items-center gap-2">{footer}</CardFooter>
49+
<CardFooter className="flex-1 flex-col items-center gap-2">{footer}</CardFooter>
5050
</Card>
5151
)
5252

frontend/src/components/FancyCard.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1+
import useMousePosition from '@/lib/hooks/useMousePosition'
12
import type { Card } from '@/types'
23
import { useCallback, useEffect, useRef, useState } from 'react'
3-
import useMousePosition from '../lib/hooks/useMousePosition'
44

55
// Generic throttle function with strict typing
66
const throttle = <T extends unknown[]>(fn: (...args: T) => void, delay: number): ((...args: T) => void) => {

frontend/src/components/Login.tsx

Lines changed: 27 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,50 +1,43 @@
11
import { Button } from '@/components/ui/button.tsx'
22
import { useToast } from '@/hooks/use-toast.ts'
3+
import { sendMagicLink } from '@/lib/Auth.ts'
34
import { useState } from 'react'
4-
import { sendMagicLink } from '../lib/Auth.ts'
5+
import { email, maxLength, nonEmpty, pipe, safeParse, string } from 'valibot'
56
import { Input } from './ui/input.tsx'
67

8+
const EmailSchema = pipe(string(), nonEmpty('Email is required'), email('Email must be valid'), maxLength(255, 'Email must be less than 255 characters'))
9+
710
export const Login = () => {
811
const { toast } = useToast()
912

1013
const [emailInput, setEmailInput] = useState('')
1114
const [emailSent, setEmailSent] = useState(false)
1215

16+
if (emailSent) {
17+
return <div className="pt-4">Thank you. Check your email for a magic login link!</div>
18+
}
19+
1320
return (
14-
<>
15-
{!emailSent && (
16-
<div className="pt-4">
17-
Fill in your email address to get a magic link to login. If you don't have an account yet, we will automatically create one for you.
18-
<div className="flex align-center justify-center gap-2 pt-4">
19-
<Input type="email" placeholder="Email" onChange={(e) => setEmailInput(e.target.value)} />
21+
<div className="pt-4">
22+
Fill in your email address to get a magic link to login. If you don't have an account yet, we will automatically create one for you.
23+
<div className="flex justify-center gap-2 pt-4 align-center">
24+
<Input type="email" placeholder="Email" onChange={(e) => setEmailInput(e.target.value)} />
2025

21-
<Button
22-
onClick={async () => {
23-
if (emailInput) {
24-
// TODO: validate email with regex
25-
const regex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/
26-
if (!regex.test(emailInput)) {
27-
toast({
28-
title: 'Please enter a valid email address',
29-
})
30-
return
31-
}
26+
<Button
27+
onClick={async () => {
28+
const result = safeParse(EmailSchema, emailInput)
29+
if (!result.success) {
30+
toast({ title: 'Please enter a valid email address' })
31+
return
32+
}
3233

33-
setEmailSent(true)
34-
await sendMagicLink(emailInput)
35-
} else {
36-
toast({
37-
title: 'Please enter an email address',
38-
})
39-
}
40-
}}
41-
>
42-
login / signup
43-
</Button>
44-
</div>
45-
</div>
46-
)}
47-
{emailSent && <div className="pt-4">Thank you. Check your email for a magic login link!</div>}
48-
</>
34+
setEmailSent(true)
35+
await sendMagicLink(emailInput)
36+
}}
37+
>
38+
login / signup
39+
</Button>
40+
</div>
41+
</div>
4942
)
5043
}

frontend/src/components/PercentageBarChart.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
'use client'
21
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'
32
import { type ChartConfig, ChartContainer, ChartTooltip, ChartTooltipContent } from '@/components/ui/chart'
43
import { Bar, BarChart, CartesianGrid, Rectangle, XAxis } from 'recharts'

0 commit comments

Comments
 (0)