mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-30 01:48:12 +00:00
138 lines
4.3 KiB
TypeScript
138 lines
4.3 KiB
TypeScript
import { Banknote, CreditCard, Wallet } from "lucide-react";
|
|
import {
|
|
Bar,
|
|
BarChart,
|
|
CartesianGrid,
|
|
Cell,
|
|
Legend,
|
|
ResponsiveContainer,
|
|
Tooltip,
|
|
XAxis,
|
|
YAxis,
|
|
} from "recharts";
|
|
import { Grid, Paper, Stack, Text } from "@mantine/core";
|
|
|
|
import type { IOverviewBillingTab } from "@/types/overview";
|
|
import { OverviewDonutChart } from "../OverviewDonutChart";
|
|
import { OverviewKpiStrip } from "../OverviewKpiStrip";
|
|
import { OverviewPaymentChart } from "../OverviewPaymentChart";
|
|
import { overviewChartColors } from "../overview.styles";
|
|
|
|
function formatCurrency(amount: number, currency: "ETB" | "USD") {
|
|
return new Intl.NumberFormat("en-US", {
|
|
style: "currency",
|
|
currency,
|
|
maximumFractionDigits: 0,
|
|
}).format(amount);
|
|
}
|
|
|
|
const METHOD_LABELS: Record<string, string> = {
|
|
telebirr: "Telebirr",
|
|
"cbe-birr": "CBE Birr",
|
|
ebirr: "eBirr",
|
|
};
|
|
|
|
interface OverviewBillingTabPanelProps {
|
|
data: IOverviewBillingTab;
|
|
}
|
|
|
|
export function OverviewBillingTabPanel({ data }: OverviewBillingTabPanelProps) {
|
|
const methodChartData = data.paymentsByMethod.map((item) => ({
|
|
name: METHOD_LABELS[item.method] ?? item.method,
|
|
count: item.count,
|
|
}));
|
|
|
|
return (
|
|
<Stack gap="lg">
|
|
<OverviewKpiStrip
|
|
items={[
|
|
{
|
|
label: "Revenue MTD (ETB)",
|
|
value: formatCurrency(data.kpis.revenueMtdEtb, "ETB"),
|
|
icon: Banknote,
|
|
accent: "emerald",
|
|
},
|
|
{
|
|
label: "Revenue MTD (USD)",
|
|
value: formatCurrency(data.kpis.revenueMtdUsd, "USD"),
|
|
icon: Wallet,
|
|
},
|
|
{
|
|
label: "Pending payments",
|
|
value: data.kpis.pendingPayments,
|
|
icon: CreditCard,
|
|
accent: "amber",
|
|
},
|
|
{
|
|
label: "Successful MTD",
|
|
value: data.kpis.successfulPaymentsMtd,
|
|
icon: Banknote,
|
|
},
|
|
]}
|
|
/>
|
|
|
|
<Grid gap="md">
|
|
<Grid.Col span={{ base: 12, lg: 8 }}>
|
|
<OverviewPaymentChart data={data.paymentTrend} />
|
|
</Grid.Col>
|
|
<Grid.Col span={{ base: 12, lg: 4 }}>
|
|
<OverviewDonutChart
|
|
title="Revenue by currency (MTD)"
|
|
data={data.revenueByCurrency.map((item) => ({
|
|
name: item.currency,
|
|
value: item.amount,
|
|
}))}
|
|
emptyMessage="No revenue this month"
|
|
/>
|
|
</Grid.Col>
|
|
</Grid>
|
|
|
|
<Grid gap="md">
|
|
<Grid.Col span={{ base: 12, md: 6 }}>
|
|
<OverviewDonutChart
|
|
title="Payments by status"
|
|
data={data.paymentsByStatus.map((item) => ({
|
|
name: item.status.replace(/-/g, " "),
|
|
value: item.count,
|
|
}))}
|
|
/>
|
|
</Grid.Col>
|
|
<Grid.Col span={{ base: 12, md: 6 }}>
|
|
<Paper p="lg" radius="lg" withBorder h="100%" style={{ minHeight: 300 }}>
|
|
<Stack gap="md">
|
|
<Text fw={600}>Payments by method</Text>
|
|
{methodChartData.length === 0 ? (
|
|
<Text size="sm" c="dimmed" ta="center" py="xl">
|
|
No payment methods recorded
|
|
</Text>
|
|
) : (
|
|
<ResponsiveContainer width="100%" height={260}>
|
|
<BarChart data={methodChartData} margin={{ top: 8, right: 8, left: 0, bottom: 0 }}>
|
|
<CartesianGrid strokeDasharray="3 3" stroke="#e5e7eb" />
|
|
<XAxis dataKey="name" tick={{ fontSize: 11 }} stroke="#94a3b8" />
|
|
<YAxis allowDecimals={false} tick={{ fontSize: 12 }} stroke="#94a3b8" />
|
|
<Tooltip />
|
|
<Legend />
|
|
<Bar dataKey="count" name="Transactions" radius={[6, 6, 0, 0]}>
|
|
{methodChartData.map((entry, index) => (
|
|
<Cell
|
|
key={entry.name}
|
|
fill={
|
|
overviewChartColors.pipeline[
|
|
index % overviewChartColors.pipeline.length
|
|
]
|
|
}
|
|
/>
|
|
))}
|
|
</Bar>
|
|
</BarChart>
|
|
</ResponsiveContainer>
|
|
)}
|
|
</Stack>
|
|
</Paper>
|
|
</Grid.Col>
|
|
</Grid>
|
|
</Stack>
|
|
);
|
|
}
|