Skip to content

Commit 4c34235

Browse files
committed
chore: add Quote page
1 parent c6a7e6b commit 4c34235

File tree

6 files changed

+128
-13
lines changed

6 files changed

+128
-13
lines changed

src/main.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import SettingsPage from "./pages/settings/SettingsPage"
1010
import meta from "./constants/meta"
1111
import { QueryClient, QueryClientProvider } from "@tanstack/react-query"
1212
import InfoPage from "./pages/info/InfoPage"
13+
import QuotePage from "./pages/quotes/QuotePage"
1314

1415
const queryClient = new QueryClient()
1516

@@ -30,6 +31,7 @@ void prepare().then(() => {
3031
<Route index element={<HomePage />} />
3132
<Route path="balances" element={<BalancesPage />} />
3233
<Route path="quotes" element={<QuotesPage />} />
34+
<Route path="quotes/:id" element={<QuotePage />} />
3335
<Route path="settings" element={<SettingsPage />} />
3436
<Route path="info" element={<InfoPage />} />
3537
</Route>

src/mocks/db.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ export const db = factory({
1616
suggested_expiration: nullable(String), // pending
1717
ttl: nullable(String), // offered
1818
signatures: Array<string>, // accepted
19-
tstamp: nullable(String) // rejected
20-
}
19+
tstamp: nullable(String), // rejected
20+
},
2121
})
2222

2323
db.info.create({

src/mocks/handlers.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import { fetchAdminQuotePending } from "./handlers/admin_quotes"
1+
import { fetchAdminLookupQuote, fetchAdminQuotePending } from "./handlers/admin_quotes"
22
import { fetchBalances } from "./handlers/balances"
33
import { fetchInfo } from "./handlers/info"
44

5-
export const handlers = [fetchInfo, fetchBalances, fetchAdminQuotePending]
5+
export const handlers = [fetchInfo, fetchBalances, fetchAdminQuotePending, fetchAdminLookupQuote]

src/mocks/handlers/admin_quotes.ts

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,35 @@
1-
import { http, delay, HttpResponse } from "msw"
1+
import { http, delay, HttpResponse, StrictResponse } from "msw"
22
import { API_URL } from "@/constants/api"
3-
import { ADMIN_QUOTE_PENDING } from "@/constants/endpoints"
4-
import { ListPendingQuotesResponse } from "@/generated/client"
3+
import { ADMIN_QUOTE_BY_ID, ADMIN_QUOTE_PENDING } from "@/constants/endpoints"
4+
import { AdminLookupQuoteResponse, InfoReply, ListPendingQuotesResponse } from "@/generated/client"
55
import { db } from "../db"
66

77
export const fetchAdminQuotePending = http.get<never, never, ListPendingQuotesResponse>(
88
`${API_URL}${ADMIN_QUOTE_PENDING}`,
99
async () => {
1010
await delay(1_000)
1111

12-
const data = db.quotes.getAll().filter((it) => it.status === 'pending');
12+
const data = db.quotes.getAll().filter((it) => it.status === "pending")
1313

1414
return HttpResponse.json({
1515
quotes: data.map((it) => it.id),
1616
})
1717
},
1818
)
19+
20+
export const fetchAdminLookupQuote = http.get<never, never, AdminLookupQuoteResponse>(
21+
`${API_URL}${ADMIN_QUOTE_BY_ID}`,
22+
async ({ params }) => {
23+
const { id } = params
24+
25+
await delay(1_000)
26+
27+
const data = db.quotes.getAll().filter((it) => it.id === id)
28+
29+
if (data.length === 0) {
30+
return HttpResponse.json(null, { status: 404 }) as unknown as StrictResponse<InfoReply>
31+
}
32+
33+
return HttpResponse.json(data[0] as InfoReply)
34+
},
35+
)

src/pages/quotes/QuotePage.tsx

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
import { Breadcrumbs } from "@/components/Breadcrumbs"
2+
import { PageTitle } from "@/components/PageTitle"
3+
import { Skeleton } from "@/components/ui/skeleton"
4+
import { InfoReply } from "@/generated/client"
5+
import useApiClient from "@/hooks/use-api-client"
6+
import useLocalStorage from "@/hooks/use-local-storage"
7+
import { useSuspenseQuery } from "@tanstack/react-query"
8+
import { Suspense } from "react"
9+
import { useParams } from "react-router"
10+
11+
function Loader() {
12+
return (
13+
<div className="flex flex-col gap-1.5 py-2">
14+
<Skeleton className="h-48 rounded-lg" />
15+
</div>
16+
)
17+
}
18+
19+
function Quote({ value }: { value: InfoReply }) {
20+
return (
21+
<>
22+
<div className="flex flex-col gap-1">
23+
<div className="flex-1">{value.id}</div>
24+
</div>
25+
</>
26+
)
27+
}
28+
29+
function DevSection({ id }: { id: InfoReply["id"] }) {
30+
const [devMode] = useLocalStorage("devMode", false)
31+
32+
const client = useApiClient()
33+
34+
const { data } = useSuspenseQuery({
35+
queryKey: ["quote", id],
36+
queryFn: () =>
37+
client.adminLookupQuote({
38+
path: {
39+
id,
40+
},
41+
}),
42+
})
43+
44+
return (
45+
<>
46+
{devMode && (
47+
<>
48+
<pre className="text-sm bg-accent text-accent-foreground rounded-lg p-2 my-2">
49+
{JSON.stringify(data, null, 2)}
50+
</pre>
51+
</>
52+
)}
53+
</>
54+
)
55+
}
56+
57+
function PageBody({ id }: { id: InfoReply["id"] }) {
58+
const client = useApiClient()
59+
60+
const { data } = useSuspenseQuery({
61+
queryKey: ["quote", id],
62+
queryFn: () =>
63+
client.adminLookupQuote({
64+
path: {
65+
id,
66+
},
67+
}),
68+
})
69+
70+
return (
71+
<>
72+
{data.data && (
73+
<>
74+
<Quote value={data.data} />
75+
</>
76+
)}
77+
</>
78+
)
79+
}
80+
81+
export default function QuotePage() {
82+
const { id } = useParams<{ id: InfoReply["id"] }>()
83+
84+
if (!id) {
85+
throw Error("Missing `id` param.")
86+
}
87+
88+
return (
89+
<>
90+
<Breadcrumbs>Quote {id}</Breadcrumbs>
91+
<PageTitle>Quote {id}</PageTitle>
92+
<Suspense fallback={<Loader />}>
93+
<PageBody id={id} />
94+
<DevSection id={id} />
95+
</Suspense>
96+
</>
97+
)
98+
}

src/pages/quotes/QuotesPage.tsx

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,9 @@ function QuoteListPendingRaw() {
2727

2828
return (
2929
<>
30-
{data.data && (
31-
<pre className="text-sm bg-accent text-accent-foreground rounded-lg p-2 my-2">
32-
{JSON.stringify(data.data, null, 2)}
33-
</pre>
34-
)}
30+
<pre className="text-sm bg-accent text-accent-foreground rounded-lg p-2 my-2">
31+
{JSON.stringify(data, null, 2)}
32+
</pre>
3533
</>
3634
)
3735
}

0 commit comments

Comments
 (0)