Skip to content

Commit d08f58f

Browse files
committed
started with interval logic
1 parent 0a513e5 commit d08f58f

File tree

8 files changed

+186
-89
lines changed

8 files changed

+186
-89
lines changed

src/constants.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
export const DEFAULT_BAR_WIDTH = 20;
1+
export const DEFAULT_BAR_WIDTH = 20;

src/index.css

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
html,
2-
body, #root {
2+
body,
3+
#root {
34
margin: 0;
45
padding: 0;
56
font-family: sans-serif;

src/stories/Component.stories.tsx

Lines changed: 23 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -11,27 +11,30 @@ export default {
1111
}
1212
} as ComponentMeta<typeof Component>;
1313

14-
const Template: ComponentStory<typeof Component> = (args) => (
15-
<Component {...args} />
16-
);
14+
const Template: ComponentStory<typeof Component> = (args) => <Component {...args} />;
1715

1816
export const WaterFallChart = Template.bind({});
1917
WaterFallChart.args = {
20-
transactions: [{
21-
label: 'Income',
22-
value: 300
23-
},{
24-
label: 'Expense1',
25-
value: -60
26-
},{
27-
label: 'Gain1',
28-
value: 200
29-
},{
30-
label: 'Expense2',
31-
value: -100
32-
},{
33-
label: 'Gain2',
34-
value: 200
35-
}
36-
]
18+
transactions: [
19+
{
20+
label: 'Income',
21+
value: 300
22+
},
23+
{
24+
label: 'Expense1',
25+
value: -60
26+
},
27+
{
28+
label: 'Gain1',
29+
value: 200
30+
},
31+
{
32+
label: 'Expense2',
33+
value: -100
34+
},
35+
{
36+
label: 'Gain2',
37+
value: 200
38+
}
39+
]
3740
};

src/types/types.d.ts

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,23 @@
11
export type IWaterfallGraphProps = {
22
transactions: Array<ITransaction>;
3-
}
3+
};
44

55
export type ITransaction = {
66
label: string;
77
value: number;
88
color?: string;
9-
}
9+
};
1010

1111
export type IChartElement = {
1212
name: string;
1313
value: number;
1414
yVal: number;
1515
cumulativeSum: number;
16-
}
16+
};
17+
1718
export type IUseWaterfallChartReturnType = {
1819
chartElements: Array<IChartElement>;
1920
yAxisUnitsPerPixel: number;
20-
yValueForZeroLine: number
21-
}
21+
yValueForZeroLine: number;
22+
yAxisPoints: Array<number>;
23+
};

src/waterfall-chart/WaterFallChart.tsx

Lines changed: 59 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,86 +1,100 @@
1-
import React, { FC, useEffect, useRef, useState } from "react";
2-
import { IWaterfallGraphProps } from "../types/types";
3-
import { useWaterfallChart } from './utils';
1+
import React, { FC, useEffect, useRef, useState } from 'react';
2+
import { IWaterfallGraphProps } from '../types/types';
3+
import { useWaterfallChart } from './utils';
44
import styles from './styles.module.scss';
55
import '../index.css';
6-
import { DEFAULT_BAR_WIDTH } from "../constants";
6+
import { DEFAULT_BAR_WIDTH } from '../constants';
77

8-
const WaterFallChart:FC<IWaterfallGraphProps> = (props) => {
8+
const WaterFallChart: FC<IWaterfallGraphProps> = (props) => {
99
const { transactions } = props;
1010

1111
const wrapperRef = useRef<HTMLDivElement | null>(null);
1212
const [wrapperHeight, setWrapperHeight] = useState(0);
1313

1414
useEffect(() => {
15-
// Function to calculate wrapper height
15+
1616
const calculateWrapperHeight = (): void => {
1717
if (wrapperRef.current) {
18-
const height = wrapperRef?.current?.offsetHeight; // Use offsetHeight to get the height
19-
setWrapperHeight(height); // Update state with calculated height
18+
const height = wrapperRef?.current?.offsetHeight;
19+
setWrapperHeight(height);
2020
}
2121
};
2222

23-
calculateWrapperHeight(); // Call the function initially
23+
calculateWrapperHeight();
2424

25-
// Add event listener for window resize to recalculate wrapper height
2625
window.addEventListener('resize', calculateWrapperHeight);
2726

2827
return () => {
29-
// Cleanup: remove event listener on component unmount
3028
window.removeEventListener('resize', calculateWrapperHeight);
3129
};
3230
}, []);
33-
const { chartElements, yAxisUnitsPerPixel, yValueForZeroLine } = useWaterfallChart(transactions, wrapperHeight);
31+
32+
const {
33+
chartElements,
34+
yAxisUnitsPerPixel,
35+
yValueForZeroLine,
36+
yAxisPoints
37+
} = useWaterfallChart(transactions, wrapperHeight);
3438

3539
return (
36-
<div
37-
ref={wrapperRef}
38-
className={styles.chartWrapper}
39-
>
40+
<div ref={wrapperRef} className={styles.chartWrapper}>
4041
<svg className={styles.svgContainer}>
4142
{/* y-axis */}
42-
<line x1="0" y1="0" x2="0" y2="100%" style={{ strokeDasharray: 1, stroke: 'rgb(158, 158, 158)', strokeWidth: 2}} />
43+
<line
44+
x1='0'
45+
y1='0'
46+
x2='0'
47+
y2='100%'
48+
className={styles.axisLines}
49+
/>
4350
{/* x-axis */}
44-
<line x1="0" y1="100%" x2="100%" y2="100%" style={{ strokeDasharray: 1, stroke: 'rgb(158, 158, 158)', strokeWidth: 2}} />
45-
{yValueForZeroLine > 0 && (
46-
// zero line if negative values present
47-
<line
48-
x1="0"
49-
y1={yValueForZeroLine}
50-
x2="100%"
51-
y2={yValueForZeroLine}
52-
style={{ strokeDasharray: 1, stroke: 'rgb(158, 158, 158)', strokeWidth: 2}}
53-
/>
54-
)}
51+
<line
52+
x1='0'
53+
y1='100%'
54+
x2='100%'
55+
y2='100%'
56+
className={styles.axisLines}
57+
/>
58+
{/* zero line if negative values present */}
59+
<line
60+
x1='0'
61+
y1={yValueForZeroLine}
62+
x2='100%'
63+
y2={yValueForZeroLine}
64+
className={`${styles.axisLines} ${yValueForZeroLine === wrapperHeight && styles.hideLine}`}
65+
/>
5566
{chartElements?.map((chartElement, index) => (
5667
<>
5768
<rect
5869
key={chartElement?.name}
5970
width={DEFAULT_BAR_WIDTH}
6071
height={Math.abs(chartElement?.value / yAxisUnitsPerPixel)}
6172
y={chartElement?.yVal}
62-
x={((2*index)+1) * DEFAULT_BAR_WIDTH}
63-
style={{
64-
fill: chartElement?.value > 0 ? '#00B050' : '#FF0000',
65-
strokeWidth: 2,
66-
stroke: chartElement?.value > 0 ? '#00B050' : '#FF0000',
67-
zIndex: 1,
68-
transition: 'all 0.3s ease-in-out'
69-
}} />
73+
x={(2 * index + 1) * DEFAULT_BAR_WIDTH}
74+
className={`${styles.graphBar} ${chartElement?.value >= 0 ? styles.positiveGraph : styles.negativeGraph}`}
75+
/>
7076
<line
7177
key={chartElement?.name}
72-
x1={((2*index)+2) * DEFAULT_BAR_WIDTH}
73-
y1={wrapperHeight - (chartElement?.cumulativeSum / yAxisUnitsPerPixel) - (wrapperHeight - yValueForZeroLine)}
74-
x2={((2*index)+3) * DEFAULT_BAR_WIDTH}
75-
y2={wrapperHeight - (chartElement?.cumulativeSum / yAxisUnitsPerPixel) - (wrapperHeight - yValueForZeroLine)}
76-
style={{
77-
stroke: '#545453',
78-
strokeWidth: 2,
79-
zIndex: 1
80-
}} />
78+
x1={(2 * index + 2) * DEFAULT_BAR_WIDTH}
79+
y1={wrapperHeight - chartElement?.cumulativeSum / yAxisUnitsPerPixel - (wrapperHeight - yValueForZeroLine)}
80+
x2={(2 * index + 3) * DEFAULT_BAR_WIDTH}
81+
y2={wrapperHeight - chartElement?.cumulativeSum / yAxisUnitsPerPixel - (wrapperHeight - yValueForZeroLine)}
82+
className={styles.bridgeLine}
83+
/>
8184
</>
8285
))}
8386
</svg>
87+
<div className={styles.yPoints}>
88+
{yAxisPoints?.map((yAxisPoint, index) => (
89+
<div
90+
key={yAxisPoint}
91+
className={styles.yPoint}
92+
style={{bottom: (index *30) - 8 }}
93+
>
94+
{yAxisPoint}
95+
</div>
96+
))}
97+
</div>
8498
</div>
8599
);
86100
};

src/waterfall-chart/index.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
import WaterFallChart from "./WaterFallChart";
1+
import WaterFallChart from './WaterFallChart';
22

33
export default WaterFallChart;

src/waterfall-chart/styles.module.scss

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,42 @@
1717
height: 100%;
1818
width: 100%;
1919
display: block;
20-
}
20+
21+
.axisLines {
22+
stroke-dasharray: 1;
23+
stroke: rgb(158, 158, 158);
24+
stroke-width: 2;
25+
transition: all 0.3s ease-in-out;
26+
}
27+
.hideLine {
28+
opacity: 0;
29+
}
30+
.graphBar {
31+
stroke-width: 2;
32+
z-index: 1;
33+
transition: all 0.3s ease-in-out;
34+
}
35+
.positiveGraph {
36+
fill: #00B050;
37+
stroke: #00B050;
38+
}
39+
.negativeGraph {
40+
fill: #FF0000;
41+
stroke: #FF0000;
42+
}
43+
.bridgeLine {
44+
stroke: #545453;
45+
stroke-width: 2;
46+
z-index: 1;
47+
}
48+
}
49+
.yPoints {
50+
position: relative;
51+
.yPoint {
52+
position: absolute;
53+
width: 20px;
54+
font-size: 15px;
55+
line-height: 18px;
56+
color: #545453;
57+
}
58+
}

0 commit comments

Comments
 (0)