Skip to content

Commit 1ba7137

Browse files
committed
feat: display rejected quotes
1 parent cba749e commit 1ba7137

File tree

4 files changed

+162
-1
lines changed

4 files changed

+162
-1
lines changed

src/components/AppSidebar.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,6 @@ const data = {
4646
{
4747
title: "Rejected",
4848
url: "/quotes/rejected",
49-
disabled: true,
5049
},
5150
{
5251
title: "Expired",

src/main.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import CashFlowPage from "./pages/balances/CashFlowPage"
1919
import OfferedQuotesPage from "./pages/quotes/OfferedQuotesPage"
2020
import DeniedQuotesPage from "./pages/quotes/DeniedQuotesPage"
2121
import ExpiredQuotesPage from "./pages/quotes/ExpiredQuotesPage"
22+
import RejectedQuotesPage from "./pages/quotes/RejectedQuotesPage"
2223

2324
const queryClient = new QueryClient()
2425

@@ -45,6 +46,7 @@ void prepare().then(() => {
4546
<Route path="quotes/accepted" element={<AcceptedQuotesPage />} />
4647
<Route path="quotes/offered" element={<OfferedQuotesPage />} />
4748
<Route path="quotes/denied" element={<DeniedQuotesPage />} />
49+
<Route path="quotes/rejected" element={<RejectedQuotesPage />} />
4850
<Route path="quotes/expired" element={<ExpiredQuotesPage />} />
4951
<Route path="quotes/:id" element={<QuotePage />} />
5052
<Route path="settings" element={<SettingsPage />} />

src/pages/quotes/QuotesPage.tsx

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ function Loader() {
1818
<Skeleton className="h-32 rounded-lg" />
1919
<Skeleton className="h-32 rounded-lg" />
2020
<Skeleton className="h-32 rounded-lg" />
21+
<Skeleton className="h-32 rounded-lg" />
2122
</div>
2223
)
2324
}
@@ -59,6 +60,14 @@ function PageBody() {
5960
}),
6061
})
6162

63+
const { data: quotesRejected } = useSuspenseQuery({
64+
...listQuotesOptions({
65+
query: {
66+
status: "rejected",
67+
} as unknown as ListQuotesData["query"],
68+
}),
69+
})
70+
6271
return (
6372
<div className="flex flex-col gap-1.5 my-2">
6473
<Link to={"/quotes/pending"}>
@@ -132,6 +141,21 @@ function PageBody() {
132141
</div>
133142
</Card>
134143
</Link>
144+
<Link to={"/quotes/rejected"}>
145+
<Card className="flex-1 self-stretch">
146+
<div className="flex items-center">
147+
<div className="flex-1 flex flex-col justify-center">
148+
<CardHeader>
149+
<CardTitle>Rejected quotes</CardTitle>
150+
</CardHeader>
151+
<CardContent className="text-2xl">{quotesRejected.quotes.length} rejected</CardContent>
152+
</div>
153+
<div className="flex p-8">
154+
<ChevronRight size={48} className="text-neutral-400" />
155+
</div>
156+
</div>
157+
</Card>
158+
</Link>
135159
<Link to={"/quotes/expired"}>
136160
<Card className="flex-1 self-stretch">
137161
<div className="flex items-center">
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
import { Breadcrumbs } from "@/components/Breadcrumbs"
2+
import { PageTitle } from "@/components/PageTitle"
3+
import { Button } from "@/components/ui/button"
4+
import { Skeleton } from "@/components/ui/skeleton"
5+
import { ListQuotesData } from "@/generated/client"
6+
import { listQuotesOptions } from "@/generated/client/@tanstack/react-query.gen"
7+
import useLocalStorage from "@/hooks/use-local-storage"
8+
import { cn } from "@/lib/utils"
9+
import { useSuspenseQuery } from "@tanstack/react-query"
10+
import { LoaderIcon } from "lucide-react"
11+
import { Suspense } from "react"
12+
import { Link, useNavigate } from "react-router"
13+
14+
function Loader() {
15+
return (
16+
<div className="flex flex-col gap-1.5 py-2">
17+
<Skeleton className="h-4 rounded-lg" />
18+
<Skeleton className="h-16 rounded-lg" />
19+
<Skeleton className="h-16 rounded-lg" />
20+
<Skeleton className="h-16 rounded-lg" />
21+
<Skeleton className="h-16 rounded-lg" />
22+
<Skeleton className="h-16 rounded-lg" />
23+
</div>
24+
)
25+
}
26+
27+
function QuoteListRejected() {
28+
const navigate = useNavigate()
29+
30+
const { data, isFetching } = useSuspenseQuery({
31+
...listQuotesOptions({
32+
query: {
33+
status: "rejected",
34+
} as unknown as ListQuotesData["query"],
35+
}),
36+
})
37+
38+
return (
39+
<>
40+
<div className="flex items-center gap-1">
41+
<LoaderIcon
42+
className={cn("stroke-1 animate-spin", {
43+
"animate-spin": isFetching,
44+
invisible: !isFetching,
45+
})}
46+
/>
47+
</div>
48+
49+
<div className="flex flex-col gap-1 my-2">
50+
{data.quotes.length === 0 && <div className="py-2 font-bold">No rejected quotes.</div>}
51+
{data.quotes.map((it, index) => {
52+
return (
53+
<div key={index} className="flex gap-1 items-center text-sm">
54+
<span className="font-mono">
55+
{isFetching ? (
56+
<>{it.id}</>
57+
) : (
58+
<>
59+
<Link to={"/quotes/:id".replace(":id", it.id)}>{it.id}</Link>
60+
</>
61+
)}
62+
</span>
63+
64+
<Button
65+
size="sm"
66+
disabled={isFetching}
67+
onClick={() => {
68+
void navigate("/quotes/:id".replace(":id", it.id))
69+
}}
70+
>
71+
View
72+
</Button>
73+
</div>
74+
)
75+
})}
76+
</div>
77+
</>
78+
)
79+
}
80+
81+
function DevSection() {
82+
const [devMode] = useLocalStorage("devMode", false)
83+
84+
const { data: quotesRejected } = useSuspenseQuery({
85+
...listQuotesOptions({
86+
query: {
87+
status: "rejected",
88+
} as unknown as ListQuotesData["query"],
89+
}),
90+
})
91+
92+
return (
93+
<>
94+
{devMode && (
95+
<>
96+
<pre className="text-sm bg-accent text-accent-foreground rounded-lg p-2 my-2">
97+
{JSON.stringify(quotesRejected, null, 2)}
98+
</pre>
99+
</>
100+
)}
101+
</>
102+
)
103+
}
104+
105+
function PageBody() {
106+
return (
107+
<div className="flex flex-col gap-2">
108+
<div>
109+
<QuoteListRejected />
110+
</div>
111+
</div>
112+
)
113+
}
114+
115+
export default function RejectedQuotesPage() {
116+
return (
117+
<>
118+
<Breadcrumbs
119+
parents={[
120+
<>
121+
<Link to="/quotes">Quotes</Link>
122+
</>,
123+
]}
124+
>
125+
Rejected
126+
</Breadcrumbs>
127+
<PageTitle>Rejected Quotes</PageTitle>
128+
<Suspense fallback={<Loader />}>
129+
<PageBody />
130+
</Suspense>
131+
<Suspense>
132+
<DevSection />
133+
</Suspense>
134+
</>
135+
)
136+
}

0 commit comments

Comments
 (0)