Skip to content

Commit e7459a0

Browse files
committed
feat: extract AllowanceView on Home
1 parent cf336b6 commit e7459a0

File tree

2 files changed

+210
-253
lines changed

2 files changed

+210
-253
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
import { CaretLeftIcon } from "@bitcoin-design/bitcoin-icons-react/filled";
2+
import AllowanceMenu from "@components/AllowanceMenu";
3+
import Header from "@components/Header";
4+
import IconButton from "@components/IconButton";
5+
import Loading from "@components/Loading";
6+
import Progressbar from "@components/Progressbar";
7+
import PublisherCard from "@components/PublisherCard";
8+
import TransactionsTable from "@components/TransactionsTable";
9+
import dayjs from "dayjs";
10+
import relativeTime from "dayjs/plugin/relativeTime";
11+
import { FC, useState, useEffect } from "react";
12+
import { Trans, useTranslation } from "react-i18next";
13+
import { toast } from "react-toastify";
14+
import { useSettings } from "~/app/context/SettingsContext";
15+
import type { Allowance, Transaction } from "~/types";
16+
17+
dayjs.extend(relativeTime);
18+
19+
type Props = {
20+
allowance: Allowance;
21+
onGoBack: () => void;
22+
onEditComplete: () => void;
23+
onDeleteComplete: () => void;
24+
};
25+
26+
const AllowanceView: FC<Props> = (props) => {
27+
const {
28+
isLoading: isLoadingSettings,
29+
settings,
30+
getFiatValue,
31+
} = useSettings();
32+
33+
const [payments, setPayments] = useState<Transaction[] | null>(null);
34+
const [isLoadingPayments, setIsLoadingPayments] = useState(true);
35+
36+
const { t } = useTranslation("translation", { keyPrefix: "home" });
37+
38+
const showFiat = !isLoadingSettings && settings.showFiat;
39+
const hasPayments = !isLoadingPayments && !!payments?.length;
40+
const isEmptyPayments = !isLoadingPayments && payments?.length === 0;
41+
42+
// get array of payments if not done yet
43+
useEffect(() => {
44+
const getPayments = async () => {
45+
const payments: Transaction[] = props.allowance.payments.map(
46+
(payment) => ({
47+
...payment,
48+
id: `${payment.id}`,
49+
type: "sent",
50+
date: dayjs(payment.createdAt).fromNow(),
51+
title: payment.name || payment.description,
52+
publisherLink: `options.html#/publishers/${payment.id}`,
53+
})
54+
);
55+
56+
try {
57+
// attach fiatAmount if enabled
58+
for await (const payment of payments) {
59+
const totalAmountFiat = showFiat
60+
? await getFiatValue(payment.totalAmount)
61+
: "";
62+
payment.totalAmountFiat = totalAmountFiat;
63+
}
64+
65+
setPayments(payments);
66+
} catch (e) {
67+
console.error(e);
68+
if (e instanceof Error) toast.error(e.message);
69+
} finally {
70+
setIsLoadingPayments(false);
71+
}
72+
};
73+
74+
!payments && !isLoadingSettings && getPayments();
75+
}, [
76+
props.allowance.payments,
77+
isLoadingSettings,
78+
payments,
79+
getFiatValue,
80+
showFiat,
81+
]);
82+
83+
return (
84+
<div className="overflow-y-auto no-scrollbar h-full">
85+
<Header
86+
title={props.allowance.host}
87+
headerLeft={
88+
<IconButton
89+
onClick={props.onGoBack}
90+
icon={<CaretLeftIcon className="w-4 h-4" />}
91+
/>
92+
}
93+
/>
94+
<div className="mx-4">
95+
<PublisherCard
96+
title={props.allowance.name}
97+
description={""}
98+
image={props.allowance.imageURL}
99+
isCard={true}
100+
isSmall={false}
101+
/>
102+
</div>
103+
<div className="px-4 pb-5">
104+
<div className="flex justify-between items-center py-3">
105+
<dl className="mb-0">
106+
<dt className="text-xs text-gray-500 dark:text-neutral-400">
107+
{t("allowance_view.allowance")}
108+
</dt>
109+
<dd className="flex items-center mb-0 text-sm font-medium dark:text-neutral-400">
110+
{+props.allowance.totalBudget > 0
111+
? `${props.allowance.usedBudget} / ${props.allowance.totalBudget} `
112+
: "0 / 0 "}
113+
{t("allowance_view.sats_used")}
114+
<div className="ml-3 w-24">
115+
<Progressbar percentage={props.allowance.percentage} />
116+
</div>
117+
</dd>
118+
</dl>
119+
120+
<div className="flex items-center">
121+
<AllowanceMenu
122+
allowance={props.allowance}
123+
onEdit={props.onEditComplete}
124+
onDelete={props.onDeleteComplete}
125+
/>
126+
</div>
127+
</div>
128+
129+
<h2 className="mb-2 text-lg text-gray-900 font-bold dark:text-white">
130+
{t("allowance_view.recent_transactions")}
131+
</h2>
132+
133+
{isLoadingPayments && (
134+
<div className="flex justify-center">
135+
<Loading />
136+
</div>
137+
)}
138+
139+
{hasPayments && <TransactionsTable transactions={payments} />}
140+
141+
{isEmptyPayments && (
142+
<p className="text-gray-500 dark:text-neutral-400">
143+
<Trans
144+
i18nKey={"allowance_view.no_transactions"}
145+
t={t}
146+
values={{ name: props.allowance.name }}
147+
// eslint-disable-next-line react/jsx-key
148+
components={[<strong></strong>]}
149+
/>
150+
</p>
151+
)}
152+
</div>
153+
</div>
154+
);
155+
};
156+
157+
export default AllowanceView;

0 commit comments

Comments
 (0)