Skip to content

Commit 0f1ee58

Browse files
Use MultiSelect in Sats Flow
1 parent c5a7e87 commit 0f1ee58

File tree

2 files changed

+79
-38
lines changed

2 files changed

+79
-38
lines changed

apps/frontend/src/components/bookkeeper/SatsFlow/SatsFlowGraph/SatsFlowGraph.tsx

Lines changed: 30 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,15 @@ import { SatsFlowPeriod } from '../../../../types/bookkeeper.type';
99
import { useSelector } from 'react-redux';
1010
import { selectUIConfigUnit } from '../../../../store/rootSelectors';
1111

12+
const ALL_EVENTS_VALUES = [
13+
{ name: 'routed', dataKey: 'routed', fill: "rgba(201, 222, 83, 1)" },
14+
{ name: 'invoice_fee', dataKey: 'invoice_fee', fill: "rgba(237, 88, 59, 1)" },
15+
{ name: 'received_invoice', dataKey: 'received_invoice', fill: "rgba(121, 203, 96, 1)" },
16+
{ name: 'paid_invoice', dataKey: 'paid_invoice', fill: "rgba(240, 147, 46, 1)" },
17+
{ name: 'deposit', dataKey: 'deposit', fill: "rgba(0, 198, 160, 1)" },
18+
{ name: 'onchain_fee', dataKey: 'onchain_fee', fill: "rgba(242, 207, 32, 1)" },
19+
];
20+
1221
const SatsFlowGraphTooltip = ({ active, payload, label, unit, periods }: any) => {
1322
if (active && payload && payload.length >= 0) {
1423
const period = periods.find(d => d.period_key === label);
@@ -32,41 +41,36 @@ const SatsFlowGraphTooltip = ({ active, payload, label, unit, periods }: any) =>
3241
return null;
3342
}
3443
})}
35-
</div>
44+
</div>
3645
);
3746
}
3847
return null;
3948
};
4049

41-
const SatsFlowGraphLegend = (props: any) => {
42-
const { payload } = props;
50+
const SatsFlowGraphLegend = ({ eventValues }: { eventValues: typeof ALL_EVENTS_VALUES }) => {
4351
return (
4452
<Row className='gx-3 gy-1 justify-content-center align-items-center'>
45-
{payload
46-
.filter((entry: any) => entry.value !== 'net_inflow_msat')
47-
.map((entry: any, index: number) => (
48-
<Col key={`item-${index}`} xs='auto' className='col-sats-flow-lagend d-flex align-items-center'>
49-
<div className='sats-flow-lagend-bullet' style={{ backgroundColor: entry.color }}/>
50-
<span className='span-sats-flow-lagend'>{titleCase(entry.value.replace(/_/g, ' '))}</span>
51-
</Col>
52-
))
53-
}
53+
{eventValues.map((entry, index) => (
54+
<Col key={`item-${index}`} xs='auto' className='col-sats-flow-lagend d-flex align-items-center'>
55+
<div className='sats-flow-lagend-bullet' style={{ backgroundColor: entry.fill }} />
56+
<span className='span-sats-flow-lagend'>{titleCase(entry.name.replace(/_/g, ' '))}</span>
57+
</Col>
58+
))}
5459
</Row>
55-
)
60+
);
5661
};
5762

5863
const CustomActiveDot = (props) => <circle cx={props.cx} cy={props.cy} r={4} fill="var(--bs-body-color)" />;
5964

60-
function SatsFlowGraph({periods}: {periods: SatsFlowPeriod[]}) {
65+
function SatsFlowGraph({ periods }: { periods: SatsFlowPeriod[] }) {
6166
const uiConfigUnit = useSelector(selectUIConfigUnit);
62-
const barValues = [
63-
{ name: 'routed', dataKey: 'routed', fill: "rgba(201, 222, 83, 1)" },
64-
{ name: 'invoice_fee', dataKey: 'invoice_fee', fill: "rgba(237, 88, 59, 1)" },
65-
{ name: 'received_invoice', dataKey: 'received_invoice', fill: "rgba(121, 203, 96, 1)" },
66-
{ name: 'paid_invoice', dataKey: 'paid_invoice', fill: "rgba(240, 147, 46, 1)" },
67-
{ name: 'deposit', dataKey: 'deposit', fill: "rgba(0, 198, 160, 1)" },
68-
{ name: 'onchain_fee', dataKey: 'onchain_fee', fill: "rgba(242, 207, 32, 1)" }
69-
];
67+
const eventValues = useMemo(() => {
68+
const presentTags = new Set(
69+
periods.flatMap(period => period.tag_groups.map(group => group.tag))
70+
);
71+
return ALL_EVENTS_VALUES.filter(bar => presentTags.has(bar.name));
72+
}, [periods]);
73+
7074
const data = useMemo(() => transformSatsFlowGraphData(periods), [periods]);
7175

7276
return (
@@ -79,22 +83,22 @@ function SatsFlowGraph({periods}: {periods: SatsFlowPeriod[]}) {
7983
>
8084
<CartesianGrid strokeDasharray='3 3' />
8185
<XAxis dataKey='name' />
82-
<YAxis
86+
<YAxis
8387
tickFormatter={(value) => {
8488
const formatted = formatCurrency(value, Units.MSATS, uiConfigUnit, false, 0, 'string');
8589
return typeof formatted === 'string' ? formatted : String(formatted);
8690
}}
8791
/>
8892
<Tooltip content={<SatsFlowGraphTooltip unit={uiConfigUnit} periods={periods} />} />
89-
<Legend content={SatsFlowGraphLegend} />
90-
{barValues.map((value: any) => (
93+
<Legend content={<SatsFlowGraphLegend eventValues={eventValues} />} />
94+
{eventValues.map((value: any) => (
9195
<Bar name={value.name} key={value.name} dataKey={value.dataKey} stackId='bar' fill={value.fill} />
9296
))}
9397
<Line className='series-net-inflow' type='monotone' dataKey='net_inflow_msat' activeDot={<CustomActiveDot />} />
9498
</ComposedChart>
9599
</ResponsiveContainer>
96100
</div>
97101
);
98-
};
102+
}
99103

100104
export default memo(SatsFlowGraph);

apps/frontend/src/components/bookkeeper/SatsFlow/SatsFlowRoot.tsx

Lines changed: 49 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import { useCallback, useEffect, useState } from 'react';
21
import './SatsFlowRoot.scss';
2+
import { useCallback, useEffect, useState } from 'react';
33
import { useNavigate } from 'react-router-dom';
44
import { Card, Col, Row } from 'react-bootstrap';
55
import { CloseSVG } from '../../../svgs/Close';
@@ -13,20 +13,46 @@ const SatsFlowRoot = () => {
1313
const navigate = useNavigate();
1414
const satsFlowPeriods = useSelector(selectSatsFlowPeriods);
1515
const [showZeroActivityPeriods, setShowZeroActivityPeriods] = useState<boolean>(false);
16+
const [selectedTags, setSelectedTags] = useState<string[]>([]);
17+
const [tagFilterMode, setTagFilterMode] = useState<string>('include');
1618
const [satsFlowData, setSatsFlowData] = useState<SatsFlowPeriod[]>(satsFlowPeriods);
1719

18-
const filterSatsFlowData = (periods, showZeroActivity) => {
19-
return (showZeroActivity) ? periods : periods.filter(key => key.tag_groups.length > 0)
20-
}
20+
const applyFilters = useCallback((
21+
periods: SatsFlowPeriod[],
22+
showZeroActivity: boolean,
23+
tags: string[],
24+
filterMode: string
25+
): SatsFlowPeriod[] => {
26+
const tagFiltered: SatsFlowPeriod[] = tags.length === 0
27+
? periods
28+
: periods.map(period => ({
29+
...period,
30+
tag_groups: period.tag_groups.filter(group => {
31+
const isMatch = tags.includes(group.tag);
32+
return filterMode === 'include' ? isMatch : !isMatch;
33+
}),
34+
}));
35+
return showZeroActivity
36+
? tagFiltered
37+
: tagFiltered.filter(period => period.tag_groups.length > 0);
38+
}, []);
2139

2240
const handleShowZeroActivityChange = useCallback((show: boolean) => {
2341
setShowZeroActivityPeriods(show);
24-
setSatsFlowData(filterSatsFlowData(satsFlowPeriods, show));
25-
}, [satsFlowPeriods]);
42+
setSatsFlowData(applyFilters(satsFlowPeriods, show, selectedTags, tagFilterMode));
43+
}, [satsFlowPeriods, selectedTags, tagFilterMode, applyFilters]);
44+
45+
const multiSelectChangeHandler = useCallback((selectedOptions: string[], filterMode: string) => {
46+
setTimeout(() => {
47+
setSelectedTags(selectedOptions);
48+
setTagFilterMode(filterMode);
49+
setSatsFlowData(applyFilters(satsFlowPeriods, showZeroActivityPeriods, selectedOptions, filterMode));
50+
}, 0);
51+
}, [satsFlowPeriods, showZeroActivityPeriods, applyFilters]);
2652

2753
useEffect(() => {
28-
setSatsFlowData(filterSatsFlowData(satsFlowPeriods, showZeroActivityPeriods));
29-
}, [satsFlowPeriods, showZeroActivityPeriods]);
54+
setSatsFlowData(applyFilters(satsFlowPeriods, showZeroActivityPeriods, selectedTags, tagFilterMode));
55+
}, [satsFlowPeriods]);
3056

3157
return (
3258
<div data-testid='satsflow-container' className='satsflow-container'>
@@ -37,15 +63,26 @@ const SatsFlowRoot = () => {
3763
<Col className='text-end'>
3864
<span
3965
className='span-close-svg'
40-
onClick={() => {
41-
navigate('..');
42-
}}
66+
onClick={() => navigate('..')}
4367
>
4468
<CloseSVG />
4569
</span>
4670
</Col>
4771
</Row>
48-
<DataFilterOptions filter='satsflow' onShowZeroActivityChange={handleShowZeroActivityChange} />
72+
<DataFilterOptions
73+
filter='satsflow'
74+
onShowZeroActivityChange={handleShowZeroActivityChange}
75+
multiSelectValues={[
76+
{ name: 'routed', dataKey: 'routed' },
77+
{ name: 'invoice_fee', dataKey: 'invoice_fee' },
78+
{ name: 'received_invoice', dataKey: 'received_invoice' },
79+
{ name: 'paid_invoice', dataKey: 'paid_invoice' },
80+
{ name: 'deposit', dataKey: 'deposit' },
81+
{ name: 'onchain_fee', dataKey: 'onchain_fee' },
82+
]}
83+
multiSelectPlaceholder='Filter Events'
84+
multiSelectChangeHandler={multiSelectChangeHandler}
85+
/>
4986
</Card.Header>
5087
<Card.Body className='pb-4 d-flex flex-column align-items-center'>
5188
<Col xs={12} className='sats-flow-graph-container'>

0 commit comments

Comments
 (0)