Skip to content

Commit d804fbd

Browse files
authored
Update Dashboard UI (#35)
* Remove mocks * Add debit and credit types * Show balance * Hide earnings and info from side bar * Update payee data type * Refresh keycloak * Display Ecash balance * Display anon payee * Use generic quote page for different statusses * Use initials as avatar * Use correct avatar * Update balance page * Remove dev mode * Remove dev mode * Display keycloak user * Display keycloak user * Fetch on chain balance * Remove comment * Remove unnecessary import * Only allow keyset activation for accepted quotes * Move functional get Initials to utils Stolen from https://github.com/BitcreditProtocol/E-Bill-frontend/blob/d0356f045b0d11a5cc094c698199aa9a04139d77/src/utils/strings.ts#L11 * Directly set color using bg- * Use BalanceDisplay for consistency * Minor changes * Use tanstack useQueries and add timeout * Remove is pending
1 parent e0158ea commit d804fbd

30 files changed

+570
-1547
lines changed

.env.development

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
VITE_API_BASE_URL="http://localhost:4242"
2-
VITE_API_MOCKING_ENABLED=false
32

43
VITE_KEYCLOAK_URL="http://localhost:8080/"
54
VITE_KEYCLOAK_REALM="dev"

.env.production

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1 @@
11
VITE_API_BASE_URL=http://127.0.0.1:3338
2-
VITE_API_MOCKING_ENABLED=false

src/components/AppSidebar.tsx

Lines changed: 5 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
1-
import { Bitcoin, Home, Inbox, Settings, InfoIcon, LifeBuoy, Send, TrendingUpIcon } from "lucide-react"
1+
import { Bitcoin, Home, Inbox } from "lucide-react"
22
import { Sidebar, SidebarContent, SidebarFooter, SidebarRail } from "@/components/ui/sidebar"
33
import { NavUser } from "./nav/NavUser"
4-
import { randomAvatar } from "@/utils/dev"
54
import { NavMain } from "./nav/NavMain"
6-
import { NavSecondary } from "./nav/NavSecondary"
5+
import { useKeycloak } from "../lib/keycloak-user"
76

87
const data = {
98
navMain: [
@@ -17,11 +16,6 @@ const data = {
1716
url: "/balances",
1817
icon: Bitcoin,
1918
},
20-
{
21-
title: "Earnings",
22-
url: "/earnings",
23-
icon: TrendingUpIcon,
24-
},
2519
{
2620
title: "Quotes",
2721
url: "/quotes",
@@ -47,60 +41,20 @@ const data = {
4741
title: "Rejected",
4842
url: "/quotes/rejected",
4943
},
50-
/*{
51-
title: "Expired",
52-
url: "/quotes/expired",
53-
},*/
5444
],
5545
},
56-
{
57-
title: "Settings",
58-
url: "/settings",
59-
icon: Settings,
60-
items: [
61-
{
62-
title: "General",
63-
url: "/settings",
64-
},
65-
],
66-
},
67-
{
68-
title: "Info",
69-
url: "/info",
70-
icon: InfoIcon,
71-
},
72-
],
73-
74-
navSecondary: [
75-
{
76-
title: "Support",
77-
url: "/#",
78-
icon: LifeBuoy,
79-
},
80-
{
81-
title: "Feedback",
82-
url: "/#",
83-
icon: Send,
84-
},
8546
],
8647
}
8748

8849
export function AppSidebar() {
50+
const { user, isLoading } = useKeycloak()
51+
8952
return (
9053
<Sidebar collapsible="icon">
9154
<SidebarContent>
9255
<NavMain items={data.navMain} />
93-
<NavSecondary items={data.navSecondary} className="mt-auto" />
9456
</SidebarContent>
95-
<SidebarFooter>
96-
<NavUser
97-
user={{
98-
name: "Account",
99-
email: "",
100-
avatar: randomAvatar("women", "0283bf290884eed3a7ca2663fc0260de2e2064d6b355ea13f98dec004b7a7ead99"),
101-
}}
102-
/>
103-
</SidebarFooter>
57+
<SidebarFooter>{!isLoading && user && <NavUser user={user} />}</SidebarFooter>
10458
<SidebarRail />
10559
</Sidebar>
10660
)

src/components/nav/NavUser.tsx

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ export function NavUser({
2323
}) {
2424
const { isMobile } = useSidebar()
2525

26+
const initials = user.name.length > 0 ? user.name[0].toUpperCase() : "U"
27+
2628
return (
2729
<SidebarMenu>
2830
<SidebarMenuItem>
@@ -31,14 +33,16 @@ export function NavUser({
3133
<SidebarMenuButton
3234
size="lg"
3335
className="data-[state=open]:bg-sidebar-accent data-[state=open]:text-sidebar-accent-foreground"
34-
tooltip={user.name}
36+
tooltip={user.name || "Unknown User"}
3537
>
3638
<Avatar className="h-8 w-8 rounded-lg">
37-
<AvatarImage src={user.avatar} alt={user.name} />
38-
<AvatarFallback className="rounded-lg">{user.name}</AvatarFallback>
39+
<div className="w-full h-full flex items-center justify-center text-white font-semibold text-sm bg-[#f59e0b]">
40+
{initials}
41+
</div>
3942
</Avatar>
43+
4044
<div className="grid flex-1 text-left text-sm leading-tight">
41-
<span className="truncate font-semibold">{user.name}</span>
45+
<span className="truncate font-semibold">{user.name || "Unknown User"}</span>
4246
<span className="truncate text-xs">{user.email}</span>
4347
</div>
4448
<ChevronsUpDown className="ml-auto size-4" />
@@ -57,7 +61,7 @@ export function NavUser({
5761
<AvatarFallback className="rounded-lg">CN</AvatarFallback>
5862
</Avatar>
5963
<div className="grid flex-1 text-left text-sm leading-tight">
60-
<span className="truncate font-semibold">{user.name}</span>
64+
<span className="truncate font-semibold">{user.name || "Unknown User"}</span>
6165
<span className="truncate text-xs">{user.email}</span>
6266
</div>
6367
</div>

src/generated/client/@tanstack/react-query.gen.ts

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
// This file is auto-generated by @hey-api/openapi-ts
22

3-
import { type Options, listQuotes, listPendingQuotes, adminLookupQuote, adminUpdateQuote, resolveOffer, enquireQuote, lookupQuote } from '../sdk.gen';
3+
import { type Options, listQuotes, listPendingQuotes, adminLookupQuote, adminUpdateQuote, resolveOffer, enquireQuote, lookupQuote, debitBalance, creditBalance } from '../sdk.gen';
44
import { queryOptions, type UseMutationOptions, type DefaultError } from '@tanstack/react-query';
5-
import type { ListQuotesData, ListPendingQuotesData, AdminLookupQuoteData, AdminUpdateQuoteData, AdminUpdateQuoteResponse, ResolveOfferData, EnquireQuoteData, EnquireQuoteResponse, LookupQuoteData } from '../types.gen';
5+
import type { ListQuotesData, ListPendingQuotesData, AdminLookupQuoteData, AdminUpdateQuoteData, AdminUpdateQuoteResponse, ResolveOfferData, EnquireQuoteData, EnquireQuoteResponse, LookupQuoteData, DebitData} from '../types.gen';
66
import { client as _heyApiClient } from '../client.gen';
77

88
export type QueryKey<TOptions extends Options> = [
@@ -195,4 +195,38 @@ export const lookupQuoteOptions = (options: Options<LookupQuoteData>) => {
195195
},
196196
queryKey: lookupQuoteQueryKey(options)
197197
});
198-
};
198+
};
199+
200+
export const debitBalanceQueryKey = (options?: Options<DebitData>) => createQueryKey('debitBalance', options);
201+
202+
export const debitBalanceOptions = (options?: Options<DebitData>) => {
203+
return queryOptions({
204+
queryFn: async ({ queryKey, signal }) => {
205+
const { data } = await debitBalance({
206+
...options,
207+
...queryKey[0],
208+
signal,
209+
throwOnError: true
210+
});
211+
return data;
212+
},
213+
queryKey: debitBalanceQueryKey(options)
214+
});
215+
};
216+
217+
export const creditBalanceQueryKey = (options?: Options<DebitData>) => createQueryKey('creditBalance', options);
218+
219+
export const creditBalanceOptions = (options?: Options<DebitData>) => {
220+
return queryOptions({
221+
queryFn: async ({ queryKey, signal }) => {
222+
const { data } = await creditBalance({
223+
...options,
224+
...queryKey[0],
225+
signal,
226+
throwOnError: true
227+
});
228+
return data;
229+
},
230+
queryKey: creditBalanceQueryKey(options)
231+
});
232+
};

src/generated/client/sdk.gen.ts

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// This file is auto-generated by @hey-api/openapi-ts
22

33
import type { Options as ClientOptions, TDataShape, Client } from '@hey-api/client-fetch';
4-
import type { ListQuotesData, ListQuotesResponse, ListPendingQuotesData, ListPendingQuotesResponse, AdminLookupQuoteData, AdminLookupQuoteResponse, AdminUpdateQuoteData, AdminUpdateQuoteResponse, ResolveOfferData, EnquireQuoteData, EnquireQuoteResponse, LookupQuoteData, LookupQuoteResponse, ActivateKeysetData, ActivateKeysetResponse } from './types.gen';
4+
import type { ListQuotesData, ListQuotesResponse, ListPendingQuotesData, ListPendingQuotesResponse, AdminLookupQuoteData, AdminLookupQuoteResponse, AdminUpdateQuoteData, AdminUpdateQuoteResponse, ResolveOfferData, EnquireQuoteData, EnquireQuoteResponse, LookupQuoteData, LookupQuoteResponse, ActivateKeysetData, ActivateKeysetResponse, DebitData, CreditData, ECashBalance, OnChainBalanceData, OnChainData} from './types.gen';
55
import { client as _heyApiClient } from './client.gen';
66

77
export type Options<TData extends TDataShape = TDataShape, ThrowOnError extends boolean = boolean> = ClientOptions<TData, ThrowOnError> & {
@@ -98,4 +98,30 @@ export const activateKeyset = <ThrowOnError extends boolean = false>(options: Op
9898
...options?.headers
9999
}
100100
});
101-
};
101+
};
102+
103+
104+
/**
105+
* --------------------------- Balance Check
106+
*/
107+
108+
export const debitBalance = <ThrowOnError extends boolean = false>(options: Options<DebitData, ThrowOnError>) => {
109+
return (options.client ?? _heyApiClient).get<ECashBalance, unknown, ThrowOnError>({
110+
url: '/v1/admin/balance/debit',
111+
...options
112+
});
113+
};
114+
115+
export const creditBalance = <ThrowOnError extends boolean = false>(options: Options<CreditData, ThrowOnError>) => {
116+
return (options.client ?? _heyApiClient).get<ECashBalance, unknown, ThrowOnError>({
117+
url: '/v1/admin/balance/credit',
118+
...options
119+
});
120+
};
121+
122+
export const onchainBalance = <ThrowOnError extends boolean = false>(options: Options<OnChainData, ThrowOnError>) => {
123+
return (options.client ?? _heyApiClient).get<OnChainBalanceData, unknown, ThrowOnError>({
124+
url: '/v1/admin/onchain/balance',
125+
...options
126+
});
127+
};

src/generated/client/types.gen.ts

Lines changed: 58 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,14 @@ export type ListReplyLight = {
2727
*/
2828
export type Amount = number;
2929

30+
31+
export type PayeePublicData = {
32+
Ident: IdentityPublicData;
33+
} | {
34+
Anon: AnonPublicData;
35+
};
36+
37+
3038
/**
3139
* --------------------------- Enquire mint quote
3240
*/
@@ -36,7 +44,7 @@ export type BillInfo = {
3644
endorsees: Array<IdentityPublicData>;
3745
id: string;
3846
maturity_date: string;
39-
payee: IdentityPublicData;
47+
payee: PayeePublicData;
4048
sum: number;
4149
};
4250

@@ -109,6 +117,12 @@ export type IdentityPublicData = PostalAddress & {
109117
type: ContactType;
110118
};
111119

120+
export type AnonPublicData = {
121+
node_id: string;
122+
email?: string | null;
123+
nostr_relays: Array<string>;
124+
}
125+
112126
/**
113127
* --------------------------- Quote info request
114128
*/
@@ -405,4 +419,46 @@ export type ActivateKeysetResponses = {
405419
200: unknown;
406420
};
407421

408-
export type ActivateKeysetResponse = ActivateKeysetResponses[keyof ActivateKeysetResponses];
422+
export type ActivateKeysetResponse = ActivateKeysetResponses[keyof ActivateKeysetResponses];
423+
424+
/**
425+
* Currency unit used for ECash
426+
*/
427+
export type CurrencyUnit = string;
428+
429+
/**
430+
* ECash balance information
431+
*/
432+
export type ECashBalance = {
433+
amount: Amount;
434+
unit: CurrencyUnit;
435+
};
436+
437+
export type DebitData = {
438+
body?: never;
439+
path?: never;
440+
query?: never;
441+
url: '/v1/admin/balance/debit';
442+
};
443+
444+
export type CreditData = {
445+
body?: never;
446+
path?: never;
447+
query?: never;
448+
url: '/v1/admin/balance/credit';
449+
};
450+
451+
export type OnChainBalanceData = {
452+
immature: number;
453+
trusted_pending: number;
454+
untrusted_pending: number;
455+
confirmed: number;
456+
};
457+
458+
459+
export type OnChainData = {
460+
body?: never;
461+
path?: never;
462+
query?: never;
463+
url: '/v1/admin/onchain/balance';
464+
};

src/lib/api-client.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,5 +23,17 @@ heyApiClient.interceptors.request.use((request) => {
2323
return request
2424
})
2525

26+
const originalFetch = window.fetch
27+
window.fetch = async function (...args) {
28+
try {
29+
console.log("Refreshing token...")
30+
await keycloak.updateToken(30)
31+
} catch (error) {
32+
console.error("Failed to refresh token:", error)
33+
}
34+
35+
return originalFetch.apply(this, args)
36+
}
37+
2638
export const client = heyApiClient
2739
export { sdk }

0 commit comments

Comments
 (0)