Skip to content

Commit 14de680

Browse files
committed
fix: invoices functionality in both frontend and backend.
1 parent a908b15 commit 14de680

File tree

12 files changed

+116
-62
lines changed

12 files changed

+116
-62
lines changed

apps/dashboard/src/components/Invoices/List.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import {
1717
} from "@/components/utils/invoice";
1818
import { Typography } from "@litespace/ui/Typography";
1919
import ImageField from "@/components/Common/ImageField";
20+
import { price } from "@litespace/utils";
2021

2122
const List: React.FC<{
2223
data: Paginated<IInvoice.Self>;
@@ -58,7 +59,7 @@ const List: React.FC<{
5859
}),
5960
columnHelper.accessor("amount", {
6061
header: intl("dashboard.invoices.amount"),
61-
cell: (info) => formatCurrency(info.getValue()),
62+
cell: (info) => formatCurrency(price.unscale(info.getValue())),
6263
}),
6364
columnHelper.accessor("status", {
6465
header: intl("dashboard.invoices.status"),

apps/web/src/components/Invoices/CreateDialog/Bank.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,10 +64,10 @@ export const Bank: React.FC<{
6464

6565
const options: SelectList<IInvoice.Bank> = useMemo(() => {
6666
return BANKS.map((bank) => ({
67-
label: getBankIntlId(bank),
67+
label: intl(getBankIntlId(bank)),
6868
value: bank,
6969
}));
70-
}, []);
70+
}, [intl]);
7171

7272
return (
7373
<div className="flex flex-col gap-8 md:gap-6">
@@ -108,7 +108,7 @@ export const Bank: React.FC<{
108108
/>
109109
<PatternInput
110110
mask=" "
111-
format="#### #### #### ####"
111+
format="#### #### #### #### ####"
112112
type="text"
113113
id="account-number"
114114
label={intl("invoices.account")}

apps/web/src/components/Invoices/CreateDialog/index.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,11 @@ export const CreateInvoiceDialog: React.FC<{
4242

4343
const onError = useOnError({
4444
type: "mutation",
45-
handler: () => toast.error({ title: intl("invoices.create-toast.error") }),
45+
handler: (error) =>
46+
toast.error({
47+
title: intl("invoices.create-toast.error"),
48+
description: intl(error.messageId),
49+
}),
4650
});
4751

4852
const createInvoice = useCreateInvoice({ onSuccess, onError });

apps/web/src/components/Invoices/InvoicesOverview.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,9 @@ export const InvoicesOverview: React.FC<{ tutorId?: number }> = ({
2727
</Typography>
2828

2929
<Overview
30-
totalRevenue={query.data?.invoices.total || 0}
30+
fulfilledRevenue={query.data?.invoices.fulfilled || 0}
3131
availableRevenue={query.data?.spendable || 0}
32-
pendingInvoicesCount={query.data?.invoices.pending || 0}
32+
pendingRevenue={query.data?.invoices.pending || 0}
3333
futureRevenue={query.data?.income.future || 0}
3434
loading={query.isPending}
3535
error={query.isError}

apps/web/src/components/Invoices/List.tsx

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,12 @@ export const List: React.FC<{ userId?: number }> = ({ userId }) => {
3636

3737
const onError = useOnError({
3838
type: "mutation",
39-
handler: () => {
39+
handler: (error) => {
4040
setId(0);
41-
toast.error({ title: intl("invoices.cancel-toast.error") });
41+
toast.error({
42+
title: intl("invoices.cancel-toast.error"),
43+
description: intl(error.messageId),
44+
});
4245
},
4346
});
4447

@@ -53,6 +56,7 @@ export const List: React.FC<{ userId?: number }> = ({ userId }) => {
5356
>
5457
{intl("invoices.table.title")}
5558
</Typography>
59+
5660
<Button
5761
size="large"
5862
endIcon={<TransactionMinus className="icon stroke-[1.5]" />}
@@ -62,6 +66,7 @@ export const List: React.FC<{ userId?: number }> = ({ userId }) => {
6266
{intl("invoices.withdrawal-request.create")}
6367
</Typography>
6468
</Button>
69+
6570
<CreateInvoiceDialog
6671
open={open}
6772
close={() => setOpen(false)}

apps/web/src/components/Invoices/Table.tsx

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import dayjs from "@/lib/dayjs";
2+
import { formatBankString } from "@/lib/format";
23
import AlertCircle from "@litespace/assets/AlertCircle";
34
import Calendar from "@litespace/assets/Calendar";
45
import DollarCircle from "@litespace/assets/DollarCircle";
56
import EmptyInvoices from "@litespace/assets/EmptyInvoices";
6-
import TransactionMinus from "@litespace/assets/TransactionMinus";
77
import Trash from "@litespace/assets/Trash";
88
import Wallet from "@litespace/assets/Wallet";
99
import { IInvoice, Void } from "@litespace/types";
@@ -17,6 +17,7 @@ import {
1717
} from "@litespace/ui/Table";
1818
import { Typography } from "@litespace/ui/Typography";
1919
import { formatNumber } from "@litespace/ui/utils";
20+
import { price } from "@litespace/utils";
2021
import { createColumnHelper } from "@tanstack/react-table";
2122
import cn from "classnames";
2223
import { isEmpty } from "lodash";
@@ -76,7 +77,7 @@ export const Table: React.FC<{
7677
className="text-natural-800 font-semibold text-body"
7778
>
7879
{intl("labels.currency.egp", {
79-
value: formatNumber(info.getValue()),
80+
value: formatNumber(price.unscale(info.getValue())),
8081
})}
8182
</Typography>
8283
),
@@ -97,7 +98,9 @@ export const Table: React.FC<{
9798
tag="p"
9899
className="text-body font-semibold text-natural-800"
99100
>
100-
{info.row.original.receiver}
101+
{info.getValue() !== IInvoice.WithdrawMethod.Bank
102+
? info.row.original.receiver
103+
: formatBankString(info.row.original.receiver)}
101104
</Typography>
102105
</div>
103106
),
@@ -192,14 +195,6 @@ const EmptyList = () => {
192195
>
193196
{intl("invoices.table.empty")}
194197
</Typography>
195-
<Button
196-
size="large"
197-
endIcon={<TransactionMinus className="icon stroke-[1.5]" />}
198-
>
199-
<Typography tag="span" className="text">
200-
{intl("invoices.withdrawal-request.create")}
201-
</Typography>
202-
</Button>
203198
</div>
204199
</div>
205200
);

apps/web/src/lib/format.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
/**
2+
* Bank receiver is assumed to follow this pattern: [bank-name]:[bank-acount-number],
3+
* for instance, CIB:123123123123213.
4+
*/
5+
export function formatBankString(bankReceiver: string) {
6+
const [bankName, bankAccountNumber] = bankReceiver.split(":");
7+
const numOfGroups = Math.ceil(bankAccountNumber.length / 4);
8+
9+
const crafted: string[] = [`${bankName}:`];
10+
for (let i = 0; i < numOfGroups; i++) {
11+
const k = i * numOfGroups;
12+
crafted.push(bankAccountNumber.slice(k, k + 4));
13+
}
14+
15+
return crafted.join(" ");
16+
}

packages/ui/src/components/InvoicesOverview/InvoicesOverview.stories.tsx

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,9 @@ type Story = StoryObj<typeof InvoicesOverview>;
2222

2323
export const Primary: Story = {
2424
args: {
25-
totalRevenue: faker.number.int({ min: 100, max: 10_000 }),
25+
fulfilledRevenue: faker.number.int({ min: 100, max: 10_000 }),
2626
availableRevenue: faker.number.int({ min: 100, max: 10_000 }),
27-
pendingInvoicesCount: faker.number.int({ min: 0, max: 10 }),
27+
pendingRevenue: faker.number.int({ min: 0, max: 10 }),
2828
futureRevenue: faker.number.int({ min: 100, max: 10_000 }),
2929
loading: false,
3030
error: false,
@@ -34,9 +34,9 @@ export const Primary: Story = {
3434

3535
export const LargeNumbers: Story = {
3636
args: {
37-
totalRevenue: faker.number.int({ min: 100_000, max: 1_000_000 }),
37+
fulfilledRevenue: faker.number.int({ min: 100_000, max: 1_000_000 }),
3838
availableRevenue: faker.number.int({ min: 100_000, max: 1_000_000 }),
39-
pendingInvoicesCount: faker.number.int({ min: 0, max: 10 }),
39+
pendingRevenue: faker.number.int({ min: 0, max: 10 }),
4040
futureRevenue: faker.number.int({ min: 100_000, max: 1_000_000 }),
4141
loading: false,
4242
error: false,
@@ -46,9 +46,9 @@ export const LargeNumbers: Story = {
4646

4747
export const Loading: Story = {
4848
args: {
49-
totalRevenue: faker.number.int({ min: 100_000, max: 1_000_000 }),
49+
fulfilledRevenue: faker.number.int({ min: 100_000, max: 1_000_000 }),
5050
availableRevenue: faker.number.int({ min: 100_000, max: 1_000_000 }),
51-
pendingInvoicesCount: faker.number.int({ min: 0, max: 10 }),
51+
pendingRevenue: faker.number.int({ min: 0, max: 10 }),
5252
futureRevenue: faker.number.int({ min: 100_000, max: 1_000_000 }),
5353
loading: true,
5454
error: false,
@@ -58,9 +58,9 @@ export const Loading: Story = {
5858

5959
export const Error: Story = {
6060
args: {
61-
totalRevenue: faker.number.int({ min: 100_000, max: 1_000_000 }),
61+
fulfilledRevenue: faker.number.int({ min: 100_000, max: 1_000_000 }),
6262
availableRevenue: faker.number.int({ min: 100_000, max: 1_000_000 }),
63-
pendingInvoicesCount: faker.number.int({ min: 0, max: 10 }),
63+
pendingRevenue: faker.number.int({ min: 0, max: 10 }),
6464
futureRevenue: faker.number.int({ min: 100_000, max: 1_000_000 }),
6565
loading: false,
6666
error: true,

packages/ui/src/components/InvoicesOverview/InvoicesOverview.tsx

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,19 +8,20 @@ import Money from "@litespace/assets/Money";
88
import TransactionMinus from "@litespace/assets/TransactionMinus";
99
import EmptyWalletTime from "@litespace/assets/EmptyWalletTime";
1010
import { formatNumber } from "@/components/utils";
11+
import { price } from "@litespace/utils";
1112

1213
export const InvoicesOverview: React.FC<{
13-
totalRevenue: number;
14+
fulfilledRevenue: number;
1415
availableRevenue: number;
15-
pendingInvoicesCount: number;
16+
pendingRevenue: number;
1617
futureRevenue: number;
1718
loading: boolean;
1819
error: boolean;
1920
retry: Void;
2021
}> = ({
21-
totalRevenue,
22+
fulfilledRevenue,
2223
availableRevenue,
23-
pendingInvoicesCount,
24+
pendingRevenue,
2425
futureRevenue,
2526
loading,
2627
error,
@@ -52,9 +53,9 @@ export const InvoicesOverview: React.FC<{
5253
icon={
5354
<ChartSquare className="[&>*]:stroke-natural-50 w-3 h-3 md:w-4 md:h-4" />
5455
}
55-
title="tutor-invoices.overview.total-revenue"
56+
title="tutor-invoices.overview.fulfilled-revenue"
5657
value={intl("labels.currency.egp", {
57-
value: formatNumber(totalRevenue),
58+
value: formatNumber(price.unscale(fulfilledRevenue)),
5859
})}
5960
color="brand"
6061
className="col-span-2 lg:col-span-1"
@@ -64,7 +65,7 @@ export const InvoicesOverview: React.FC<{
6465
icon={<Money className="[&>*]:stroke-natural-50 h-3 md:w-4 md:h-4" />}
6566
title="tutor-invoices.overview.available-revenue"
6667
value={intl("labels.currency.egp", {
67-
value: formatNumber(availableRevenue),
68+
value: formatNumber(price.unscale(availableRevenue)),
6869
})}
6970
color="secondary"
7071
className="col-span-2 lg:col-span-1"
@@ -75,7 +76,9 @@ export const InvoicesOverview: React.FC<{
7576
<TransactionMinus className="[&>*]:stroke-natural-50 h-3 md:w-4 md:h-4" />
7677
}
7778
title="tutor-invoices.overview.pending-invoices-count"
78-
value={formatNumber(pendingInvoicesCount)}
79+
value={intl("labels.currency.egp", {
80+
value: formatNumber(price.unscale(pendingRevenue)),
81+
})}
7982
color="warning"
8083
className="col-span-2 lg:col-span-1"
8184
/>
@@ -85,7 +88,7 @@ export const InvoicesOverview: React.FC<{
8588
<EmptyWalletTime className="[&>*]:stroke-natural-50 h-3 md:w-4 md:h-4" />
8689
}
8790
value={intl("labels.currency.egp", {
88-
value: formatNumber(futureRevenue),
91+
value: formatNumber(price.unscale(futureRevenue)),
8992
})}
9093
title="tutor-invoices.overview.future-revenue"
9194
color="destructive"

packages/ui/src/locales/ar-eg.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -434,7 +434,7 @@
434434
"invoices.create-dialog.instapay.label": "ادخل العنوان البريدي الخاص بإنستاباي",
435435
"invoices.create-dialog.username.label": "اسم المستخدم",
436436
"invoices.create-dialog.instapay.placeholder": "litespace@instapay",
437-
"invoices.create-dialog.account-number.placeholder": "1234567890123456",
437+
"invoices.create-dialog.account-number.placeholder": "•••• •••• •••• 1234",
438438
"invoices.table.empty": "لا توجد طلبات سحب سابقة",
439439
"invoices.table.loading": "برجاء الانتظار... جاري تحميل طلبات السحب!",
440440
"invoices.table.error": " عذرًا، حدث خطأ أثناء تحميل طلبات السحب، برجاء المحاولة مرة أخرى",
@@ -721,7 +721,7 @@
721721
"tutor-settings.topics.selection-dialog.error": "عذرًا، حدث خطأ أثناء تحميل المجالات المتاحة، برجاء المحاولة مرة أخرى",
722722
"tutor-settings.account-settings.notifications.title": "الإشعارات",
723723
"tutor-invoices.overview.title": "الأرباح",
724-
"tutor-invoices.overview.total-revenue": "إجمالي الأرباح",
724+
"tutor-invoices.overview.fulfilled-revenue": "إجمالي الأرباح",
725725
"tutor-invoices.overview.available-revenue": "المتاح للسحب",
726726
"tutor-invoices.overview.pending-invoices-count": "تحت المعالجة",
727727
"tutor-invoices.overview.future-revenue": "الأرباح القادمة",

0 commit comments

Comments
 (0)